文件传输漏洞
1.前端JS漏洞
把这个HTML文件保存下来(一般表单都会存在提交的地址,这个地址应该是公开的吧,你把这个jpg/jpng这种判断的过程给改一下,让其通过就可以)。
2.文件类型绕过
使用BP进行拦截,更改文件的类型。对于服务器而言,我只认定type,不管真实是什么。所以我只用使用BP把请求类型给改一下就可以了。
3.黑名单
不让你上传php后缀的文件,那我使用Apache中间件可以将php3的文件给解析成php。就是改一下文件类型。
这些都可以当做php去解析
AddType application/x-httpd-php .php .php3 .php4 .php5 .phtml .pht4.htaccess攻击
明确说了不让上传php,php3等,但是并没有说可以上传什么类型?比如你可以上传png文件,也可以上传pdf文件。这种的话就是先上传一个htaccess文件,后面再上传一个jpg文件,这个可以把jpg文件当做php去解析。
#htaccess <FilesMatch "LouDong.jpg"> SetHandler application/x-httpd-php </FilesMatch>注意是.htaccess不是test.htaccess这种。
至于图片则是:找一张jpg的图片,用记事本的形式打开,在后面加上代码:
<?php phpinfo(); ?>执行的时候就是先上传.htaccess文件,相当于是告诉服务器等下有个“LouDong.jpg”的文件,你用php解释器解释。而这个jpg文件虽然是jpg后缀但是内容却是php类型。服务器收到后 就会执行php代码。
5.大小写绕写
现在黑名单中不让你上传php,php3,htaccess。那我们就在BP中把这个php后缀给改一下,改成PHP这种。服务器对于php文件大小写不敏感。统一当做php文件处理。
"info.PHP"6.空格绕写
"info.php "7.文件后缀加点绕写
"info.php."8.::$DATA绕写
"info.php::$DATA"9.代码逻辑绕写
这个是删除点的代码,意思是后面要是点我就一直删,知道不是点为止。那要是文件后缀名"info.php. ...."点之前有一个空格那么就错了。
<?php function deldot($s){ for($i = strlen($s)-1;$i>0;$i--){ $c = substr($s,$i,1); if($i == strlen($s)-1 and $c != '.'){ return $s; } if($c != '.'){ return substr($s,0,$i+1); } } } ?>10.文件后缀替换
这里是说要将原来违规的后缀名给进行替换为“ ”(就是删除)
例子 1:你上传 info.php
文件名:info.php
代码执行:发现php在黑名单 →删掉结果:info.
→ 文件名变成info.,不是 php,无法解析 ❌
例子 2:你上传 info.php5
文件名:info.php5
代码执行:
- 发现
php5→ 删掉 - 发现
php→ 删掉结果:info.
还是不行 ❌
双写绕过!你上传:
"info.phphpp"源码:
$is_upload = false; $msg = null; if (isset($_POST['submit'])) { if (file_exists(UPLOAD_PATH)) { $deny_ext = array("php","php5","php4","php3","php2","html","htm","phtml","pht","jsp","jspa","jspx","jsw","jsv","jspf","jtml","asp","aspx","asa","asax","ascx","ashx","asmx","cer","swf","htaccess"); $file_name = trim($_FILES['upload_file']['name']); $file_name = str_ireplace($deny_ext,"", $file_name); $temp_file = $_FILES['upload_file']['tmp_name']; $img_path = UPLOAD_PATH.'/'.$file_name; if (move_uploaded_file($temp_file, $img_path)) { $is_upload = true; } else { $msg = '上传出错!'; } } else { $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!'; } }11.GET0x00截断
首先这个是php低版本的错误,高版本已经没有了。之所有有这个BUG的原因是由于操作系统是用C/汇编语言编写的。一般对于字符串的处理是遇到\0就认为结束(%00)这种。就把这个字符串给自动截断了。
POST /Pass-11/index.php?save_path=../upload/ HTTP/1.1上面这个是使用BP进行的拦截。很好理解,这个save_path=../upload(因为在做uploads-labs靶场练习的时候,默认自己的电脑为服务器。那么可以展示一下相关存储地址)
这个题目的逻辑是:
我是属于先上传了一个文件,假设是info.php文件。使用BP进行拦截,并把filename改成info.jpg。这样就可以认为是jpg文件。后面截取后缀jpg,并且由于指明了save_path=../upload/后面又额外生成了类似于123456这种,则文件存放路径是../upload/123456.jpg。
这样一张图片就存放在服务器中了(因为主要是上传,就把这个文件放到服务器磁盘中的。后面我要是想要操作,就需要访问这台服务器。)
当save_path=../upload/1.php%00这样生成的就是../upload/1.php%00/123456.jpg。后面php要将这样的地址存放到磁盘中,但是由于php对于%00有截断,所以只能存../upload/1.php。这样磁盘中就存下来这个文件。
后面有个问题是当我这样处理完之后选择复制图片地址会出现乱码:
豆包的解释是:
网页不知道发生了截断!它还按照原始拼接字符串显示给你看,但浏览器不认识 %00 这个字符,就把它显示成乱码,所以你看到:这样的乱码。但是磁盘存的是../upload/1.php。
12.$_POST0x00截断
| 对比项 | GET 传save_path(Pass-11) | POST 传save_path(Pass-12) |
|---|---|---|
| 参数位置 | URL 里,比如?save_path=../upload/ | 请求体里,就是你截图看到的../upload/ |
| 编码方式 | 浏览器会自动 URL 编码(比如%00会被解析) | 不会自动编码,%00会被当作普通字符 |
| 截断利用 | 直接写save_path=../upload/info.php%00就行 | 必须手动把%00改成十六进制00字节 |
由于post选项是不会自动解码的,所以要设置将%00给自动解码一下
当这样设置完之后会发现这个%00没有了。
13.图片马(文件包含绕过)
使用cmd命令
copy pra.png /b +info.php /a shell.png其中/b就是说以字节的形式打开。/a的意思是说append(在尾部追加元素)效果如下:
那么对于这样的有木马的图片请问怎么显示呢?可以使用文件上传漏洞进行展示。
运行这样的代码:
http://localhost/include.php?file=upload/7120260509155556.png这个是上传的代码,由于有GET命令,获取这个file请求所以要上传这个file的位置。就是上面的这个。后面就可以展示 了。
14.二次渲染绕过
工资太高了,你只要有一点点漏洞,我就想发把工资给你就给你降下来。
14.1二次渲染
- 二次渲染:服务器收到你上传的图片后,不是直接保存,而是用 GD/ImageMagick 等库重新解码→再编码生成一张新图,把原图扔掉。
- 不是只对 GIF 有漏洞,而是GIF 最容易留后门,JPG/PNG 很难。
- 你 → 上传 1.gif → 服务器用 imagecreatefromgif() 打开(解码成像素) → 再用 imagegif() 存成新图 2.gif(重新编码) → 删除原图 1.gif,只留 2.gif
14.2安全影响
- 你在图片末尾追加的
<?php ... ?>,会被直接清掉—— 因为渲染只认 “合法图片数据”,额外的尾部数据会被丢弃。 - 所以普通 “图片马”(copy 图片 + php)在二次渲染下基本失效。
14.3为什么常说 “只有 GIF 能绕过二次渲染”
准确说法:三种图都会被渲染,但 GIF 结构特殊,更容易找到 “渲染不改的区域” 来藏代码。
1. JPG:几乎不可能
- JPG 是压缩流 + 像素矩阵,渲染时会完全重新计算、重写全部字节。
- 任何你插入的 PHP 代码,99.9% 会被覆盖或破坏,几乎没有稳定区。
2. PNG:有机会,但难
- PNG 由很多 ** 数据块(chunk)** 组成:IHDR、IDAT、tEXt 等。
- 渲染时:
- 会重写IDAT(像素数据);
- 但部分 tEXt 文本块、自定义块可能被保留。
- 可以藏代码,但格式校验严、可用空间小、成功率低。
3. GIF:最容易留后门(核心原因)
GIF89a 结构特点:
- 多块分段:文件头 → 逻辑屏幕 → 调色板 →多个图像块 / 注释块 / 扩展块→ 结尾。
- 渲染时会 “选择性保留” 部分块(取决于 GD 库版本):
- ❌ 会删:注释块、大部分扩展块;
- ✅ 可能保留:某些控制块、局部调色板、图像块头部的部分字节。
关键点:
- GIF 渲染不会改写所有字节,总有一小段原始数据原样保留。
- 攻击者可以:
- 先传一张正常 GIF,下载服务器渲染后的新 GIF;
- 用十六进制工具对比原图 vs 渲染后,找出完全没变的那段二进制;
- 把 PHP 代码精准插入到这段 “渲染不改区”;
- 再上传 → 渲染后代码还在 → 配合文件包含即可执行。
| 格式 | 渲染强度 | 能否找到稳定区 | 利用难度 |
|---|---|---|---|
| JPG | 完全重建 | 几乎不能 | 极高 |
| PNG | 重写大部分块 | 少数情况可以 | 高 |
| GIF | 部分保留原始块 | 容易找到 | 中 |
14.4一张png只改后缀可以变成gif吗?
先给你直白结论:可以改后缀,外表看成了 .gif,但本质还是 PNG 源码,不是真 GIF。
1. 改后缀能干啥?
把a.png直接改名成a.gif:
- 电脑、浏览器、相册能正常打开看图
- 但文件内部二进制头还是 PNG 头,不是 GIF 头
文件头区别(关键)
- PNG 头:
89 50 4E 47 0D 0A 1A 0A - GIF 头:
47 49 46 38 39 61(GIF89a)
你只是改了名字,里面的二进制一丁点没变。
2. 对文件上传漏洞有什么影响?
情况 1:只校验后缀的网站
你把png改后缀为gif,服务器会当成gif 文件放行,这是弱校验。
情况 2:校验文件头 / 真实文件格式的网站
一看二进制头是 PNG 头,哪怕后缀是.gif,照样拦截,绕过失败。
情况 3:二次渲染场景
- 假 GIF(PNG 改后缀)丢给 GD 库渲染
- 库识别出实际是 PNG 格式,按 PNG 逻辑解码渲染
- 根本不会走 GIF 的渲染保留逻辑,没法用来绕二次渲染漏洞
3. 真正区别
- 改后缀:只是换个名字,文件内容不变 → 假 GIF
- 格式转换:用 PS、画图、在线转换 把 PNG 转成真 GIF → 二进制头、结构全变成 GIF,才是真 GIF
14.5使用Beyond Compare进行比较
下载地址:https://www.beyondcomparepro.com/download
这个使用GIF进行二次渲染主要是因为后面改动后GIF的16进制形式仍然有大量没有更改的区域,这时我们可以进行php的插入。
可以向将没有加木马的raw.gif上传,得到一个新的图片new.gif,打开16进制比较模式,找到找到没有改变的区域,记住相应的开头。再次单独打开raw.gif,使用info.php的十六进制覆盖对应区域(不是插入)
- 点击你找到的不变区域的第一个字节,输入上面的十六进制(注意每两个字符是一个字节,直接替换原来的内容)。
- 比如原来的字节是
4E 98 20 ...,你直接把它改成3C 3F 70 ...,不要插入,只覆盖,确保文件总长度不变。
然后Ctrl+s,保存文件,会发现info.php文件已经被插入了。
效果如下:
