PHP代码审计分段讲解(14)

30题利用提交数组绕过逻辑

本篇博客是PHP代码审计分段讲解系列题解的最后一篇,对于我这个懒癌患者来说,很多事情知易行难,坚持下去,继续学习和提高自己。

源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<?php
$role = "guest";
$flag = "flag{test_flag}";
$auth = false;
if(isset($_COOKIE["role"])){
    $role = unserialize(base64_decode($_COOKIE["role"]));
    if($role === "admin"){
        $auth = true;
    }
    else{
        $auth = false;
    }
}
else{
    $role = base64_encode(serialize($role));
    setcookie('role',$role);
}
if($auth){
    if(isset($_POST['filename'])){
        $filename = $_POST['filename'];
        $data = $_POST['data'];
        if(preg_match('[<>?]', $data)) {
            die('No No No!'.$data);
        }
        else {
            $s = implode($data);
            if(!preg_match('[<>?]', $s)){
                $flag='None.';
            }
            $rand = rand(1,10000000);
            $tmp="./uploads/".md5(time() + $rand).$filename;
            file_put_contents($tmp, $flag);
            echo "your file is in " . $tmp;
        }
    }
    else{
        echo "Hello admin, now you can upload something you are easy to forget.";
        echo "<br />there are the source.<br />";
        echo '<textarea rows="10" cols="100">';
        echo htmlspecialchars(str_replace($flag,'flag{???}',file_get_contents(__FILE__)));
        echo '</textarea>';
    }
}
else{
    echo "Sorry. You have no permissions.";
}
?>

首先给出了$role和$auth的初始值

1
2
$role = "guest";
$auth = false;

如果在COOKIE中没有传值的话,就会进入else,将初始值设定在COOKIE里

1
2
3
4
else{
    $role = base64_encode(serialize($role));
    setcookie('role',$role);
}

从后面的逻辑上看,我们需要令

1
$auth=true

所以需要手动传入role值,通过逻辑

1
2
3
4
5
6
7
8
9
if(isset($_COOKIE["role"])){
    $role = unserialize(base64_decode($_COOKIE["role"]));
    if($role === "admin"){
        $auth = true;
    }
    else{
        $auth = false;
    }
}

这里对传入的 role 进行base64解密后反序列化,将结果赋值给$role

1
$role = unserialize(base64_decode($_COOKIE["role"]));

然后想要令

1
$auth=true

前提条件为:

1
$role === "admin"

这个是我们可以控制的

编写代码

1
2
3
4
5
<?php
    $role='admin';
    $role1=base64_encode(serialize($role));
    echo $role1;
?>

得到

role=czo1OiJhZG1pbiI7

1.png

可以看到成功绕过了第一个点

继续往下看

当 $auth 为 true的时候,进行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
if(isset($_POST['filename'])){
    $filename = $_POST['filename'];
    $data = $_POST['data'];
    if(preg_match('[<>?]', $data)) {
        die('No No No!'.$data);
    }
    else {
        $s = implode($data);
        if(!preg_match('[<>?]', $s)){
            $flag='None.';
        }
        $rand = rand(1,10000000);
        $tmp="./uploads/".md5(time() + $rand).$filename;
        file_put_contents($tmp, $flag);
        echo "your file is in " . $tmp;
    }
}

可以看出来是上传文件的代码,具体为:

传入文件名和文件内容:filename 和 data

1
2
3
if(isset($_POST['filename'])){
    $filename = $_POST['filename'];
    $data = $_POST['data'];

判断$data中是否有一句话木马标识,有的话则退出

1
2
3
if(preg_match('[<>?]', $data)) {
        die('No No No!'.$data);
    }

没有的话 else 结构,这里有一句

1
$s = implode($data);

应该是上传一句话木马的突破点。

关于 implode()函数,有:

定义:

implode()函数返回由数组元素组合成的字符串

示例:

1
2
3
4
<?php
$arr = array('Hello','World!','Beautiful','Day!');
echo implode(" ",$arr);
?>

输出:

1
Hello World! Beautiful Day!

而我们在前面的代码审计中,知道preg_match()函数只能处理字符串,当传入的变量是数组是会返回false,这里正好满足,可以编写代码测试

1
2
3
4
5
6
7
8
<?php
    $data[]='<?php phpinfo();?>';
    if(preg_match('[<>?]', $data)) {
            die('No No No!'.$data);
    }else{
        echo "yes!";
    }
?>

输出为

1
2
3
yes!
 
PHP Warning:  preg_match() expects parameter 2 to be string, array given in /usercode/file.php on line 3

虽然有警告,但是还是成功绕过了。

这里的代码

1
2
3
if(!preg_match('[<>?]', $s)){
            $flag='None.';
        }

表示如果变量$s中没有匹配到特定字符的话就令$flag为空,这样在后面的文件写入时,也不能获取到flag了。

1
2
3
$rand = rand(1,10000000);
$tmp="./uploads/".md5(time() + $rand).$filename;
file_put_contents($tmp, $flag);

这里是生成一个随机的文件名,并且将 flag 内容写进去

最后是输出文件名

1
echo "your file is in " . $tmp;

我们绕过后 flag 会写入到 文件名随机生成的文件中,该文件名最后是可知的。

按照之前分析的过程,很容易可以构建出payload

3.jpg

访问获取flag

 结束


__EOF__

本文作者春告鳥
本文链接https://www.cnblogs.com/Cl0ud/p/13393754.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   春告鳥  阅读(416)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示