利用seesion.upload_progress实现文件包含

利用Session.upload_progress实现文件包含

上一篇文章中我们讲到了Session反序列化,但不知道大家有没有发现一个问题,就是我们是利用GET传参将我们构造好的恶意代码传入Session中的,但假如没有GET传参呢?我们还能往Seesion中写入恶意代码吗?

答案肯定是可以的,不然我写这文章还有啥意义呢哈哈哈,这里就要介绍出这篇文章的主人公:session.upload_progress

1.session.upload_progress是什么?

这里我们还是看看官方文档:https://www.php.net/manual/zh/session.upload-progress.php

image.png

就是说在上传任意文件时,当我们POST上传一个与session.upload_progress.name同名的变量时,它就会在$_SESSION中增加一组数据

2.相关配置

我们在官方文档中看到了非常多的配置,而这些配置是成功实现上传的前提

1.session.upload_progress.enabled:当这个配置为On时,代表upload_progress功能开始,也意味着当浏览器向服务器上传一个文件时,php将会把此次文件上传的详细信息(如上传时间、上传进度等)存储在session当中,也就是说如果这个选项关掉了,这种方法就用不了了,好在它是默认开启的

image.png

2.session.upload_progress.cleanup:这个选项默认也是On,也就是说当文件上传结束时,session文件中有关上传进度的信息立马就会被删除掉;这里就给我们的操作造成了很大的困难,我们就只能使用条件竞争的方式不停的发包,争取在它被删除掉之前就成功利用

image.png

3.session.upload_progress.name:这个的默认值是PHP_SESSION_UPLOAD_PROGRESS,也就是说我们要POST上传的变量名也要为PHP_SESSION_UPLOAD_PROGRESS,并且PHP_SESSION_UPLOAD_PROGRESS变量的值也会被写入Session中,最重要的就是它的值可控

image.png

4.session.upload_progress.prefix:这个其实我感觉作用不是很大,它的默认值为: upload_progress_,通过官方文档我们可以得知,它写入session文件内容的格式为session.upload_progress.prefix+session.upload_progress.name连接在一起的值,那么在我们这种配置的情况下,它的格式就是upload_progress_+PHP_SESSION_UPLOAD_PROGRESS的值

image.png

5.session.use_strict_mode:之前测试时我们都是通过session_start()打开的session,那假如没有session_start()岂不是就不能利用了?但由于session.use_strict_mode这个选项默认是不开启的,相当于我们就可以自己定义session_id,比如我在请求包中设置COOKIEPHPSESSID=haha,那么就会生成一个sess_hahasession文件,此时php会自动初始化session,并产生一个键值,格式如上

image.png

3.文件包含

既然我们可以通过session.upload_progress将恶意代码写入到Session文件中,而且文件名字和文件路径我们都可控,那一个很常见的思路就是将恶意代码写入Session文件之后,利用文件包含来包含它,但由于session.upload_progress.cleanup = On的存在,我们需要用burp不停发包,然后用同样的方式不停的发送文件包含的数据包,看能不能包含成功,接下来就开始测试:

先写一个存在文件包含漏洞的页面,命名为test4.php

1
2
3
4
5
6
<?php
highlight_file(__FILE__);
error_reporting(0);
$file=$_GET['file'];
include($file);
?>

然后再写一个表单,这个表单要用POST上传两个东西,一个是任意文件,一个是变量名为PHP_SESSION_UPLOAD_PROGRESS的变量

1
2
3
4
5
6
7
8
9
<html>
<body>
<form action="" method="POST" enctype="multipart/form-data">
<input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="111" />
<input type="file" name="file" />
<input type="submit" value="submit" />
</form>
</body>
</html>

好了,准备开始操作!在表单这个页面随便选择一个文件,用burp抓包,如下图:

image.png

先将我们想要写入的恶意代码写进去,就写入到PHP_SESSION_UPLOAD_PROGRESS的值中,接在111的后面就行,这里我就用<?php system('whoami')?>来演示,然后我们把PHPSESSID的值改为lalala,这里我们先不用条件竞争,就先发一次包,看在存储Session的目录下D:\phpStudy\PHPTutorial\tmp\tmp有没有生成sess_lalala这个文件:

image.png

image.png

可以看到文件以及成功生成了,但大小是0kb,那里面肯定是没有东西的,这就是因为我们上文提到的session.upload_progress.cleanup将它自动删除掉了,所以说我们才需要条件竞争不停的发包,相当于写的比它删的快,这样就可以成功写进去了,我们把这个数据包发送到burp的爆破模块中,利用爆破不停的发包,这里我设置的发包次数是100000次,由于网速的原因,它还是需要跑很久的,这就给了我们时间去完成文件包含的操作,次数太少了可能还没包含到就被删了:

image.png

image.png

然后开始攻击,看它能不能把成功文件写进去:

image.png

开始跑了,然后我们就去存Session文件的那个文件夹,看那个文件里面有没有内容写进去:

image.png

发现已经成功写进去了,看来我们写的确实比删的要快一点,然后我们这时候去完成文件包含肯定是可以成功的,成功执行了whoami

image.png

4.反序列化

Session反序列化的内容请看上篇文章,这里只是简单提一下,我认为按理来说利用PHP_SESSION_UPLOAD_PROGRESS上传文件也能实现,因为这里是通过条件竞争把我们想要的方法写入到Session文件中,而上一篇文章讲的是直接写入进去,虽然写入的方法不同但结果应该是相同的,但这里我试了很多次都没有成功,应该是数据包数据比较多,burp的发包速度不够快导致竞争不过,所以这里我就演示不了了,可以写个python脚本试试,具体请参照这篇文章https://www.freebuf.com/vuls/202819.html,里面有些注意事项我就搬运过来了:

1.PHPSESSID必须要有,因为要竞争同一个文件

2.这里不能像上面文件包含一样把恶意代码写在PHP_SESSION_UPLOAD_PROGRESS值中,因为值中一旦出现了|就会使数据写入失败,这里要写在filename的值中,而且filename值中不能有汉字

3.要将字符串中的双引号转义,以防止与最外层的双引号冲突

4.上传的文件要大些,否则很难竞争成功,我也有可能是因为写的文件不够大导致未能成功

参考文章:

https://blog.csdn.net/weixin_46330722/article/details/111657006?spm=1001.2014.3001.5501