【译】实战演练:看我是如何将LFI变为RFI的
字数 1614 2025-08-29 08:31:41
从LFI到RFI:利用文件描述符实现漏洞升级
1. 文件包含漏洞基础
1.1 PHP文件包含漏洞原理
PHP文件包含漏洞产生于通过PHP函数引入文件时,由于文件名未经合理校验,导致意外文件操作。最常见的是本地文件包含(LFI)漏洞。
典型漏洞代码示例:
if ($_GET['method']) {
include $_GET['method'];
} else {
include 'index.php';
}
1.2 本地文件包含(LFI)利用方式
攻击者可以提交类似https://example.com/search.php?method=upload/1.jpg的URL,其中1.jpg是攻击者上传的包含恶意PHP代码的图片文件,从而执行恶意代码。
2. 从LFI到RFI的突破性发现
2.1 关键发现
- JAR包文件利用:Web应用程序在特定配置下可以加载服务器上的JAR包文件并执行其中的Java类
- 静态代码块执行:可以在Java类中定义静态代码块,在类加载时自动执行
示例恶意Java类:
public class LoadRunner {
static {
System.out.println("Load runner'ed");
// 这里可以放置恶意代码
}
public static void main(String[] args) {}
}
2.2 挑战与解决方案
主要挑战:
- 如何让应用程序加载攻击者控制的JAR包文件
- 如何确定JAR包文件在服务器上的路径
解决方案:
- 利用Linux的
/proc/[PID]/fd/*文件描述符机制访问上传的文件 - 通过猜测HTTP请求处理程序的PID和文件描述符编号来定位文件
3. 文件描述符利用技术详解
3.1 Linux文件描述符机制
在Linux中,当一个进程打开文件时,会在/proc/[PID]/fd/目录下创建对应的文件描述符链接。这使得我们可以:
- 不需要猜测随机生成的文件名或路径
- 只需猜测PID和文件描述符编号即可访问文件
3.2 实际利用步骤
- 上传恶意文件:通过文件上传功能将恶意JAR包上传到服务器
- 获取PID:确定HTTP请求处理程序的进程ID
- 查找文件描述符:在
/proc/[PID]/fd/目录下查找对应的文件描述符 - 通过LFI包含:利用LFI漏洞包含
/proc/[PID]/fd/[编号]路径
3.3 减少搜索空间的技巧
- 多文件上传:同时上传多个相同文件,增加命中概率
- PID预测:服务器重启后PID分配顺序通常一致,可缩小PID猜测范围
4. 实战演示:Flask框架案例
4.1 测试环境搭建
Flask示例应用代码:
from flask import Flask, request
import os
UPLOAD_FOLDER = "/tmp"
app = Flask(__name__)
app.config["UPLOAD_FOLDER"] = UPLOAD_FOLDER
@app.route("/", methods=["GET"])
def show_me_the_money():
x = request # 访问request对象会触发文件描述符创建
import code
code.interact(local=locals()) # 进入交互式调试环境
if __name__ == "__main__":
app.run()
4.2 文件上传脚本
import requests
response = requests.get(
"http://127.0.0.1:5000/",
files={
"upload_file": open("/tmp/hullo", "rb"),
# 可添加多个文件增加命中率
},
)
4.3 查找文件描述符
- 获取Flask进程PID:
ps aux | grep flask - 查看文件描述符目录:
ls -la /proc/[PID]/fd/ - 确认文件内容:
cat /proc/[PID]/fd/[编号]
5. 关键注意事项
-
文件大小限制:小文件可能被直接读入内存而不创建文件描述符(如Flask中1MB以下文件)
- 解决方案:在JAR包中添加填充数据使其超过阈值
-
框架特性差异:
- Flask和Django等框架是"惰性加载"请求体数据
- 只有访问请求体数据时才会创建文件描述符
-
请求处理程序要求:
- 处理程序必须访问FILES字典或请求体数据
- 需要定位到会处理上传文件的请求处理程序
6. 攻击利用流程总结
- 识别目标系统中的LFI漏洞
- 寻找文件上传功能或请求体数据处理点
- 上传特制JAR包文件(确保大小超过内存加载阈值)
- 确定Web服务器进程PID
- 通过LFI包含
/proc/[PID]/fd/[编号]路径 - 触发JAR包中静态代码块的执行
7. 防御建议
- 输入验证:严格校验文件包含路径,禁止包含用户可控的完整路径
- 禁用危险函数:如非必要,禁用
include、require等危险函数 - 文件上传限制:
- 限制上传文件类型
- 使用随机不可预测的存储路径
- 及时关闭文件描述符
- 进程隔离:Web服务器进程使用低权限用户运行
- 访问控制:限制对
/proc目录的访问
通过这种创新的方法,安全研究人员可以将传统的LFI漏洞升级为更危险的RFI漏洞,极大地扩展了攻击面。理解这种技术有助于开发更安全的Web应用程序和更有效的防御措施。