利用条件
- session.upload_progress.enabled为开启状态
- session.upload_progress.name知道这个变量的值
- session.save_path知道session的路径
- 有session_start()或者session.auto_start()为开启状态
成因
最初是PHP为上传进度条设计的一个功能,在上传文件较大的情况下,PHP将进行流式上传,并将进度信息放在Session中,此时即使用户没有初始化Session,PHP也会自动初始化Session。
session.upload_progress.enabled的开启,会自动记录上传文件的进度到session文件中,即便这个是没有任何意义,本质上是没有什么太大的危害,但是同站点内存在文件包含漏洞的话,危害一下子就上来了,当session文件存在php代码时,就会造成命令执行,大概原理就是通过前端创建一个文件上传的源码,然后定义一个session.upload_progress.name的值,这个值可以是普通的字符,也可以是php代码,最终这个值会被写入到session文件中,就好比下面那个例子1一样。
参数解析
| 参数 | 解析 | 状态 |
| --------------------------------- | ---------------------------------------------------------- | --------------------------------------- |
| session.upload_progress.enabled | 开启文件上传时的状态写入到session中 | 默认为ON |
| session.upload_progress.name | 文件上传的name值 | 默认为 PHP_SESSION_UPLOAD_PROGRESS |
| session.upload_progress.prefix | 文件上传状态的写入前缀 | 默认为upload_progress_ |
| session.upload_progress.cleanup | 当文件上传成功后,自动清除session文件中写入的状态 | 默认为ON |
| session.save_path | session文件保存的路径 | Linux下默认为/var/lib/php/session/ |
| session.auto_start | 自动记录session,这个参数为On时,可以不用session_start() | 默认为off |
| session.use_strict_mode | 当这个参数值为0的时候,可以自定义SESSID | 默认为0 |
常见的session文件路径:
/var/lib/php/sess_PHPSESSID
/var/lib/php/sessions/sess_PHPSESSID
/tmp/sess_PHPSESSID
/tmp/sessions/sess_PHPSESSID
例子1
写入文件的时候,格式是
- session.upload_progress.prefix + session.upload_progress.name
假如session.upload_progress.name写的是\<?php system(\$_GET['vfree']);?>时,写入session文件的就是:
upload_progress_\<?php system(\$_GET['vfree']);?>|a:5:{s:10:"start_time";i:1658749324;s:14:"content_length";i:404;s:15:"bytes_processed";i:404;s:4:"done";b:1;s:5:"files";a:1:{i:0;a:7:{s:10:"field_name";s:5:"file1";s:4:"name";s:5:"2.png";s:8:"tmp_name";s:22:"C:\Windows\php5B4D.tmp";s:5:"error";i:0;s:4:"done";b:1;s:10:"start_time";i:1658749324;s:15:"bytes_processed";i:26;}}}
大概信息解析如下:
环境模拟复现
在开始之前,我们必须要弄清楚两个问题,第一个问题就是我怎么开启session并写入,其次就是session.upload_progress.cleanup默认是开启的,也就是说当上传完成后,就会立刻清除掉刚刚写进去的代码,那该怎么包含呢?
第一个问题,上面提到的session.auto_start可以在没有session_start的情况下,自动生成session,当然,这个参数也必须开启;
第二个问题,可以通过文件竞争来对抗cleanup,通过不断发包读取,达到这种效果,为了实验的方便性,本次操作将session.upload_progress_cleanup关闭了!
假设有以上源码,查看phpinfo的参数
重点关注画红线的参数,可以看到session.upload_progress.cleanup处于关闭状态,session.upload_progress.enabled为开启状态,满足这两个条件就说明可能存在session文件上传状态包含,所以可以在index.php页面中构造一个文件上传的代码,如下:
然后开启抓包,并且任意选择一个文件进行上传
这里因为session.use_strict.mode为0,所以可以自定义PHPSESSID,且要传入一个name是PHP_SESSION_UPLOAD_PROGRESS的值,这个值的会写入到session文件中,所以就可以写一个命令执行的php代码,修改好一切后,发送请求到客户端(下图的PHPSESSID是修改后的)
返回200的状态码,查看session文件,内容如下,看到了我们的php代码已经写进去了,所以可以直接进行包含
通过index.php的include对session文件进行包含,phpinfo中已知session路径为D:\phpstudy_pro\Extensions\tmp\tmp,并且也知道session文件名sess_vFREE,所以可以直接包含session文件并且执行命令,执行结果如下:
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论