当前位置: 代码迷 >> 综合 >> Bugku 冬至红包
  详细解决方案

Bugku 冬至红包

热度:60   发布时间:2023-11-24 20:44:48.0

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长度与 exam49()使payloadexam长度相等,在代码间加入无意义的语句。flag,php等都被过滤了但是我们可以用数组拼接flag,并且[]的过滤可以用{}替代[]在数组中。

构造payload:

$a=blag;$a{
    0}=f;111111111111111111111;?><?=$$a;?> or 
$a=flgg;$a{
    2}=a;111111111111111111111;?><?=$$a;?>

直接得到flag
在这里插入图片描述