Files
vulhub/php/inclusion/README.zh-cn.md
Aaron 63285f61aa
Some checks failed
Vulhub Format Check and Lint / format-check (push) Has been cancelled
Vulhub Format Check and Lint / markdown-check (push) Has been cancelled
Vulhub Docker Image CI / longtime-images-test (push) Has been cancelled
Vulhub Docker Image CI / images-test (push) Has been cancelled
first commit
2025-09-06 16:08:15 +08:00

3.1 KiB
Raw Permalink Blame History

PHP文件包含漏洞利用phpinfo

PHP文件包含漏洞中如果找不到可以包含的文件我们可以通过包含临时文件的方法来getshell。因为临时文件名是随机的如果目标网站上存在phpinfo则可以通过phpinfo来获取临时文件名进而进行包含。

参考链接:

漏洞环境

执行如下命令启动环境:

docker compose up -d

目标环境是官方最新版PHP7.2说明该漏洞与PHP版本无关。

环境启动后,访问http://your-ip:8080/phpinfo.php即可看到一个PHPINFO页面访问http://your-ip:8080/lfi.php?file=/etc/passwd,可见的确存在文件包含漏洞。

利用方法简述

在给PHP发送POST数据包时如果数据包里包含文件区块无论你访问的代码中有没有处理文件上传的逻辑PHP都会将这个文件保存成一个临时文件通常是/tmp/php[6个随机字符]),文件名可以在$_FILES变量中找到。这个临时文件,在请求结束后就会被删除。

同时因为phpinfo页面会将当前请求上下文中所有变量都打印出来所以我们如果向phpinfo页面发送包含文件区块的数据包则即可在返回包里找到$_FILES变量的内容,自然也包含临时文件名。

在文件包含漏洞找不到可利用的文件时,即可利用这个方法,找到临时文件名,然后包含之。

但文件包含漏洞和phpinfo页面通常是两个页面理论上我们需要先发送数据包给phpinfo页面然后从返回页面中匹配出临时文件名再将这个文件名发送给文件包含漏洞页面进行getshell。在第一个请求结束时临时文件就被删除了第二个请求自然也就无法进行包含。

这个时候就需要用到条件竞争,具体流程如下:

  1. 发送包含了webshell的上传数据包给phpinfo页面这个数据包的header、get等位置需要塞满垃圾数据
  2. 因为phpinfo页面会将所有数据都打印出来1中的垃圾数据会将整个phpinfo页面撑得非常大
  3. php默认的输出缓冲区大小为4096可以理解为php每次返回4096个字节给socket连接
  4. 所以我们直接操作原生socket每次读取4096个字节。只要读取到的字符里包含临时文件名就立即发送第二个数据包
  5. 此时第一个数据包的socket连接实际上还没结束因为php还在继续每次输出4096个字节所以临时文件此时还没有删除
  6. 利用这个时间差第二个数据包也就是文件包含漏洞的利用即可成功包含临时文件最终getshell

漏洞复现

利用脚本exp.py实现了上述过程,成功包含临时文件后,会执行<?php file_put_contents('/tmp/g', '<?=eval($_REQUEST[1])?>')?>,写入一个新的文件/tmp/g,这个文件就会永久留在目标机器上。

用python2执行python exp.py your-ip 8080 100

可见执行到第289个数据包的时候就写入成功。然后利用lfi.php即可执行任意命令