这几天做中南大学的院赛web题碰到了一道上传题,正好利用到了去年发布的一个cve,虽然漏洞有点鸡肋,但是作为一种姿势了解一下还是不错的,故此记录总结一下

漏洞概述

在Apache 2.4.0到2.4.29版本中使用到了如下的配置信息:

1
2
3
<FilesMatch \.php$>
SetHandler application/x-httpd-php
</FilesMatch>

这是一个php文件的解析表达式,我们可以注意到$,这个解析漏洞的根本原因就是这个$。我们知道$在正则表达式中用来匹配字符串结尾位置,在菜鸟教程中对正则表达符$的解释如下:

1
匹配输入字符串的结尾位置。如果设置了 RegExp 对象的 Multiline 属性,则 $ 也匹配 ‘\n’ 或 ‘\r’。要匹配 $ 字符本身,请使用 \$。

说明了$是可以匹配到字符串结尾的换行符,也就是说,如果我们此时有个文件后缀名为:.php\n,Apache是会将其作为php文件进行解析的

漏洞利用

了解了该解析漏洞,我们便可以利用它来绕过上传的黑名单限制,例如存在下面的上传逻辑:

1
2
3
4
5
6
7
8
9
<?php
if(isset($_FILES['file'])) {
$name = basename($_POST['name']);
$ext = pathinfo($name,PATHINFO_EXTENSION);
if(in_array($ext, ['php', 'php3', 'php4', 'php5', 'phtml', 'pht'])) {
exit('bad file');
}
move_uploaded_file($_FILES['file']['tmp_name'], './' . $name);
}

这里使用到了黑名单过滤方式,但是如果我们利用上述漏洞,上传一个文件名为:1.php\x0a,那么便可以成功绕过黑名单的限制上传php文件

实例演示

实例来自于中南大学的院赛ctf中的一道题,题目名字是upload something

题目页面如下:

上传文件时可以发现,不论正常上传什么文件,login.php都显示bad file

我们抓包可以发现,请求包中额外post一个参数name

这就想到了我们分析的Apache解析漏洞,如果文件名取自$_FILES['file']['name'],就会自动把换行符去掉,而文件名取自post参数name中,就能很好的利用到这个解析漏洞

下面我们上传一个包含换行符的文件,这里需要注意只能时\x0a而不是\x0d\x0a\x0d\x0a的情况是我们直接添加一个换行符,我们利用burp的hex功能在test666.php后面添加一个\x0a

从响应包中可以看到上传成功了,但是相应页面success.html中并没有告诉我们上传文件的目录

但是我们在请求包中还可以看到一个参数dir = /upload/,所以猜测上传目录为·/upload/test666.php%0a

访问成功,最后就是上木马拿shell了

最后我们可以看一下upload.php的源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?php
if(isset($_FILES['file'])) {


$name = basename($_POST['name']);
$ext = pathinfo($name,PATHINFO_EXTENSION);




$ext = pathinfo($name,PATHINFO_EXTENSION);
if(preg_match('/php/',$ext)){
if(in_array($ext, ['php', 'php3', 'php4', 'php5', 'phtml'])) {
header("location:hacker.html");
exit('bad file');

}

if(!move_uploaded_file($_FILES['file']['tmp_name'], '../upload/'. $name)){
exit('upload failed');
}else{
header("location:success.html");
}

//move_uploaded_file($_FILES['file']['tmp_name'], './' . $name);
}else{
header("location:hacker.html");
exit('bad file');
}
}
?>

验证的逻辑就是首先利用正则匹配验证后缀名是否包含了php,第二步就是利用黑名单过滤,但是由于未过滤php%0a,并且取post参数name作为文件名,所以便可以很好的利用到apache的解析漏洞,另外我们还可以看一下apache配置文件,文件目录在/etc/apache2/conf-available/docker-php.conf

1
2
3
<FilesMatch \.php$>
SetHandler application/x-httpd-php
</FilesMatch>

正如我们前面提到的配置文件内容一样,$能匹配到换行符\x0a,这就造成了该解析漏洞

总结

这个漏洞利用的条件如下:

  • 获取文件名时不能用$_FILES['file']['name'],因为他会自动把换行去掉,这一点有点鸡肋
  • Apache版本为2.4.0到2.4.29
  • 服务器必须是linux系统,因为windows环境下不支持后缀名带有换行符\x0a

总体上而言,只要取$FILES['file']['name']作为文件名,就可以无视该解析漏洞,所以该漏洞总体来说实际用处不大,但是由于根本成因在于$,在以后的其他某些漏洞可以还有利用到的地方,作为一种姿势学习一下还是蛮有趣的。

最后附上参考链接: