xctf-web ics-05
题目描述就是简单的一句话,也没看明白啥意思。
进靶场环境看着有点类似一个管理后台。
唯一有跳转的地方就在设备维护中心这里,而且 url 里面传了参数 page,利用点应该就在这里。
这里需要用到 php 中的伪协议对 index.php 的源码进行读取。先来学习一下伪协议的部分知识。
php:// –访问各个输入/输出流(I/O streams)
PHP 提供了一些杂项输入/输出(IO)流,允许访问 PHP 的输入输出流、标准输入输出和错误描述符, 内存中、磁盘备份的临时文件流以及可以操作其他读取写入文件资源的过滤器。
引自——http://docs.php.net
最常使用的一个伪协议是 php://filter,可以利用该协议来进行任意文件的读取。
php://filter 是一种元封装器, 设计用于数据流打开时的筛选过滤应用。
这对于一体式(all-in-one)的文件函数非常有用,类似 readfile()、 file() 和 file_get_contents(), 在数据流内容读取之前没有机会应用其他过滤器。
引自——http://docs.php.net
php://filter 目标使用以下的参数作为其路径的一部分。
名称 | 描述 |
---|---|
resource=<要过滤的数据流> | 这个参数是必须的,他指定了要筛选过滤的数据流。 |
read=<读链的筛选列表> | 该参数可选,可以设定一个或多个过滤器名称,以管道符 | 分隔。 |
write=<写链的筛选列表> | 该参数可选,可以设定一个或多个过滤器名称,以管道符 |
《 | 任何没有以 read= 或 write= 作为前缀的筛选器列表会视情况应用于读或写链。 |
其中read参数值可为:
- string.strip_tags: 将数据流中的所有html标签清除
- string.toupper: 将数据流中的内容转换为大写
- string.tolower: 将数据流中的内容转换为小写
- convert.base64-encode: 将数据流中的内容转换为base64编码
下面就尝试构造 payload 查看 index.php 的源码。
payload:php://filter/read=convert.base64-encode/resource=index.php
成功拿到 base64 加密的源码,解密查看源码。
index.php 的关键代码:
1 | if ($_SERVER['HTTP_X_FORWARDED_FOR'] === '127.0.0.1') |
这段代码主要用了两个函数:
$_SERVER: 是一个包含了诸如头信息(header)、路径(path)、以及脚本位置(script locations)等等信息的数组。
preg_replace:函数执行一个正则表达式的搜索和替换。参数如下:
- $ pattern:要搜索的模式,可以是字符串或一个字符串数组。
- $ replacement:用于替换的字符串或字符串数组。
- $ subject:要搜索替换的目标字符串或字符串数组。
- $ limit:可选,对于每个模式用于每个主题字符串的最大可替换次数。默认是-1(无限制)。
- $ count:可选,为替换执行的次数。
所以这段代码主要先是检验了 http 请求头中的 X-Forwarded-For 参数的值是不是 127.0.0.1,然后对 GET 方式传入的三个参数进行正则匹配。
这里的利用点在于 preg_replace 这个函数。该函数可以利用正则中 /e 修正符使 preg_replace() 将 replacement 参数当作 PHP 代码执行。(在适当的逆向引用替换完之后)。
注:要确保 replacement 构成一个合法的 PHP 代码字符串,否则 PHP 会在报告在包含 preg_replace() 的行中出现语法解析错误。
所以我们就可以尝试构造 payload 尝试执行命令,查找 flag 文件。
payload:?pat=/test/e&rep=system("ls")&sub=%20test
然后就是继续构造,找到 flag。
payloag:?pat=/test/e&rep=system("cat%20s3chahahaDir/flag/flag.php")&sub=%20test