文件上传(一)
关于文件上传
文件上传漏洞是指由于程序员在对用户文件上传部分的控制不足或者处理缺陷,而导致的用户可以越过其本身权限向服务器上上传可执行的动态脚本文件。这里上传的文件可以是木马,病毒,恶意脚本或者WebShell等。“文件上传”本身没有问题,有问题的是文件上传后,服务器怎么处理、解释文件。如果服务器的处理逻辑做的不够安全,则会导致严重的后果。
十分眼熟
<?php @eval($_POST[cmd]);?>
这个想必都很熟悉,经典的一句话木马,通过服务器的php环境执行这个代码,再通过访问和传参来达到get shell的目的。也就是后门文件。
在一般ctf做题过程中我们通常使用antsword来连接方便操作。
ps:asp、php、jsp或者cgi等网页文件都可以做到相同效果
论攻防道
<?php
// 检查是否有文件上传
if ($_FILES['file']['error'] !== UPLOAD_ERR_OK) {
echo json_encode(['error' => 'File upload error']);
exit;
}
// 指定文件上传目录和文件名
$uploadDir = '/path/to/upload/directory/';
$uploadFile = $uploadDir . basename($_FILES['file']['name']);
?>
attack
这样的未做任何防护的文件上传,我们直接上传一句话木马的php文件即可getshell,使用antsword连接可以控制该服务器下的所有(如果使用docker建的当这句话没有,我们需要容器逃逸技术等,但我不会逃逸,,,,,,,用docker只能控制一个docker下的文件
<?php @eval($_POST[cmd]);?>
defend
很显然我们需要对文件进行审查,比如我们可以在前端页面写一个检查脚本来对文件类型进行检查于是乎:
<li id="show_code">
<h3>代码</h3>
<pre>
<code class="line-numbers language-javascript">function checkFile() {
var file = document.getElementsByName('upload_file')[0].value;
if (file == null || file == "") {
alert("请选择要上传的文件!");
return false;
}
//定义允许上传的文件类型
var allow_ext = ".jpg|.png|.gif";
//提取上传文件的类型
var ext_name = file.substring(file.lastIndexOf("."));
//判断上传文件类型是否允许上传
if (allow_ext.indexOf(ext_name + "|") == -1) {
var errMsg = "该文件不允许上传,请上传" + allow_ext + "类型的文件,当前文件类型为:" + ext_name;
alert(errMsg);
return false;
}
}
</code>
</pre>
</li>
这样子,在上传文件时就可以限制文件类型什么的了,非常的非常的非常的............
attack
然而这个实在太容易绕过了,,,(当然,我故意的
因为是前端页面,所以,直接可以降维打击,前端页面在用户手里,不受服务器影响,我们直接注释掉,或者禁用js就可以轻松解决了,,当然还可以加一个禁止右键看源码,不过你禁止右键管我ctrl+u什么事?(
defend
ok,兄弟们,在前端页面写防护实在是没用,那我们写后端不就行了,用php这种需要后端环境的写一下黑名单
<li id="show_code">
<h3>代码</h3>
<pre>
<code class="line-numbers language-php">$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
$deny_ext = array('.asp','.aspx','.php','.jsp');
$file_name = trim($_FILES['upload_file']['name']);
$file_name = deldot($file_name);//删除文件名末尾的点
$file_ext = strrchr($file_name, '.');
$file_ext = strtolower($file_ext); //转换为小写
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
$file_ext = trim($file_ext); //收尾去空
if(!in_array($file_ext, $deny_ext)) {
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext;
if (move_uploaded_file($temp_file,$img_path)) {
$is_upload = true;
} else {
$msg = '上传出错!';
}
} else {
$msg = '不允许上传.asp,.aspx,.php,.jsp后缀文件!';
}
} else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
}
}
</code>
</pre>
</li>
或者来个白名单
<li id="show_code">
<h3>代码</h3>
<pre>
<code class="line-numbers language-php">$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
$ext_arr = array('jpg','png','gif');
$file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1);
if(in_array($file_ext,$ext_arr)){
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;
if(move_uploaded_file($temp_file,$img_path)){
$is_upload = true;
} else {
$msg = '上传出错!';
}
} else{
$msg = "只允许上传.jpg|.png|.gif类型文件!";
}
}
</code>
</pre>
</li>
ok,当然这两个网上找的,自己实在是懒得写,,,,
attack
一般条件下,白名单是真的非常狗,他限制你输入的东西,只让你传那么几个文件,连.htaccess文件都无差别ban掉了(这个后面再讲
但是我们也不是啥办法也没有,找找其他方法不就行了,ctf一般不会这么搞,但在现实环境中都是白名单,审查及其严格,而且还有二次渲染来破坏你文件(像我们学校内网的好多服务都是这么开的,找不到一点下手的地方,死活绕不过
1.我们大小写绕过,像这样.Php,都是通过他过滤不严格来绕过
2.利用一下漏洞,列如:
apache1.x,2.x的解析漏洞,上传如a.php.rar a.php.gif 类型的文件名,可以避免对于php文件的过滤机制,但是由于apache在解析文件名的时候是从右向左读,如果遇到不能识别的扩展名则跳过,rar等扩展名是apache不能识别的,因此就会直接将类型识别为php,从而达到了注入php代码的目的。
nginx(0.5.x, 0.6.x, 0.7 <= 0.7.65, 0.8 <= 0.8.37)空字节漏洞 xxx.jpg%00.php 这样的文件名会被解析为php代码运行(fastcgi会把这个文件当php看,不受空字节影响,但是检查文件后缀的那个功能会把空字节后面的东西抛弃,所以识别为jpg)
像这样的都是老版本有的,在真实环境中,我们一般都是信息搜集到发现他使用的老版本,漏洞早就爆出来了,我们都可以拿来利用的,当然,遇到新版本就没啥办法了,除非你拿源代码一个个去代码审计·找一个0day出来利用
这种都是找齐过滤不严格的点,ctf题目经常出,但是有时候他用的就是很偏,有时候就是想不到用什么符号字母啥的怎么绕过
defend
加强过滤,使用上正则匹配,,,,,,,,,,
attack
ok,这就到了我们./htaccess文件出场的时候了,有时候在做防护的时候经常会忘了这个文件,这个文件非常牛逼,我们可以通过这个配置文件,吧任意后缀的文件改成用php来执行,完美绕过有没有,当然,前提是吧.htaccess文件上传上去
<FilesMatch "evil.gif">
SetHandler application/x-httpd-php #在当前目录下,如果匹配到evil.gif文件,则被解析成PHP代码执行
AddHandler php5-script .gif #在当前目录下,如果匹配到evil.gif文件,则被解析成PHP代码执行
</FilesMatch>
这样我们上传gif也是可以来当php执行的。
defend
恒显然,我们在过滤代码方面基本上没啥做的了,现在我们可以从数据包层面出发来拦截,不管他咋绕过,hacker在上传时总会法宝,在他没有修改的时候,数据包是会显示文件类型的我们在这里检查一下好了
HTTP协议规定了上传资源的时候在Header中加上一项文件的MIMETYPE,来识别文件类型
Content-Type
attack
bp抓包修改ct头使其符合,,,,,,,
defend
恒显然啊恒显然,居然被这么轻易的绕过了,,,,(迅速跑到另一侧
文件上传时总是有数据流的,我们检查文件具体内容就行了,检查一下文件头,(文件头知识在misc中经常出现,最好网上搜集一下
利用的是每一个特定类型的文件都会有不太一样的开头或者标志位。
格式 文件头
TIFF (tif) 49492A00
Windows Bitmap (bmp) 424D
CAD (dwg) 41433130
Adobe Photoshop (psd) 38425053
JPEG (jpg) FFD8FF
PNG (png) 89504E47
GIF (gif) 47494638
XML (xml) 3C3F786D6C
HTML (html) 68746D6C3E
MS Word/Excel (xls.or.doc) D0CF11E0
MS Access (mdb) 5374616E64617264204A
ZIP Archive (zip), 504B0304
RAR Archive (rar), 52617221
Wave (wav), 57415645
AVI (avi), 41564920
Adobe Acrobat (pdf), 255044462D312E
attack
绕过方法其实也就那样了,伪造就行了,伪造一个文件头就是了
给上传脚本加上相应的幻数头字节就可以,php引擎会将 <?之前的内容当作html文本,不解释而跳过
或者我们干最就是上传一个图片码一绝后患
直接修改二进制文件,在里面添加上一句话木马,图片可能会被破坏,但是图片是否完好我们又不需要,,,,,,,
defend
我们可以对上传的图片直接修改其位置,让攻击者访问不到这个地方,
首先是验证上传的文件是否为图片格式,如果上传了正确的图片,imagecreatefromjpeg()返回图像资源,文件名更换为新的时间戳,用新的文件路径n e w r o o t p a t h 输 出 图 片 , 最 后 删 除 原 文 件 u n l i n k ( new_rootpath输出图片,最后删除原文件unlink(new
r
ootpath输出图片,最后删除原文件unlink(rootpath);如果上传了不正确的图片,不会更换新的文件路径,最后还要删除源文件unlink($rootpath);
attack
有些时候里面可能还有延时函数sleep(5),啥的,我们可以弄一个一直访问的脚本,只要存在一秒,我们就可以执行获取到我们想要的东西,就是有点麻烦
这个文件上传可以组合其他效果发挥出逆天的效果,这里分享一下一个最近看到的比较牛的
就是通过任意文件读取,读取到访问日志,如果日志访问到了,并且发现带有某个参数头,我们就可以在这个参数头下包修改参数为一句话木马,然后通过任意文件读取的路径链接(虽然,但是,都任意文件读取了,直接拿flag不好吗?。。。。。。。。。。
评论0
暂时没有评论