简介:本资源聚焦 IIS 短文件名泄露这一经典 Web 安全检测场景,面向渗透测试初学者、安全运维人员及 CTF 参赛者,用于校验目标站点是否存在短文件名枚举风险。包内同时提供 Python 与 Java 两套实现,并附带环境包下载地址,方便在不同运行环境下快速开展验证。资源共 32 个文件,压缩包约 87KB,以 class 编译文件、java 源码、xml 配置、md 说明文档为主,另含 py 脚本、jar 包、bat 与 sh 启动脚本等,兼顾源码阅读与开箱即用。Python 版基于 2.7 环境,Java 版采用 Eclipse 工程结构,含 MANIFEST.MF、build.xml 与运行脚本,便于二次编译调试。目前已有 248 人学习下载,读者可借此理解短文件名漏洞原理、掌握扫描工具的使用与排错思路,并对照源码梳理请求构造与结果判定逻辑。
1. IIS 短文件名扫描:从 8.3 命名规则到 .rar 工具包的实战拆解
在 Windows Server 上跑 IIS 的站点,很多人只盯着上传漏洞和解析漏洞,却忽略了一个从 DOS 时代遗留下来的老问题——8.3 短文件名机制。IIS_shortname_Scanner.rar这个工具包针对的就是它:利用 IIS 对短文件名请求的响应差异,把目录和文件名的前六个字符逐个猜出来。听起来像玄学,但我在一次内网评估里就是靠它从一个只开放 80 端口的 IIS 站点上,把后台备份目录backup~1给还原成了backup_2023,进而拿到了整站源码。这篇笔记不讲空泛概念,而是把短文件名扫描的原理、工具包怎么用、参数怎么调、以及我在 Win11 配 IIS 环境复现时踩过的坑,按可复现的步骤写清楚。适合做渗透测试、甲方安全巡检,或者单纯想搞明白 IIS 短文件名到底能泄露多少信息的人。
2. 短文件名机制与扫描原理:为什么一个波浪号能泄露目录结构
2.1 8.3 命名规则在 NTFS 上的残留逻辑
Windows 为了兼容早期 16 位程序,在 NTFS 卷上默认保留短文件名(Short Name)生成能力。规则很简单:取长文件名的前六个字符,去掉空格和特殊符号,转大写,后面跟~1,扩展名取前三个字符。比如administrator.aspx会生成ADMINI~1.ASP。如果前六个字符相同的文件有多个,数字递增为~2、~3。这个短名在文件系统层面是真实存在的,可以通过dir /x看到。
IIS 在处理请求时,如果收到一个不存在的长文件名,但匹配到了对应的短文件名,会返回一个特定的响应。早期 IIS 版本会直接返回 404,但响应时间或状态码有细微差别;后续版本修补后,仍然可以通过~请求的响应长度或状态码来区分“短名存在”和“短名不存在”。扫描器就是靠这个差异做暴力枚举。
注意:不是所有 IIS 都开启短名支持。NTFS 卷可以通过
fsutil behavior set disable8dot3 1全局禁用,或者在单个目录上禁用。很多运维在加固时会关掉它,但内网老服务器上默认开启的比例仍然很高。
2.2 扫描器如何把“猜”变成“枚举”
IIS_shortname_Scanner这类工具的核心逻辑分两步。第一步,枚举目录短名。发送类似http://target/AAAAAA~1/的请求,如果返回 404 以外的状态码(比如 400 或 200),说明存在以AAAAAA开头的目录短名。第二步,逐字符扩展。从A~1/开始,不断追加字符,直到找到完整短名,再根据短名反推长名前六个字符。对于文件,则用AAAAAA~1.EXT的形式探测。
这个过程本质上是暴力枚举,但因为短名只有前六个字符参与,搜索空间被大幅压缩。一个字符集为a-z0-9_的 36 字符集,六位组合是 36^6,但实际扫描器会用字典和递增策略,先猜常见前缀,再逐位扩展,把请求量降到几百次以内。
2.3 工具包 .rar 里通常有什么
拿到IIS_shortname_Scanner.rar后,解压一般会看到几个部分:一个 Python 或 C# 写的主扫描脚本、一个字典文件(常见目录名和文件名前缀)、一个说明文档。不同版本可能还带一个批量扫描的 shell 脚本。我手头这个版本主程序是 Python 3 写的,依赖requests和urllib3,字典里预置了admin、backup、upload、config等常见前缀。如果你拿到的包只有 exe,建议在虚拟机里跑,因为这类工具常被误报。
3. 在 Win11 上搭 IIS 复现环境:从安装到开启短名支持
3.1 Win11 安装 IIS 的步骤与常见卡点
Win11 家庭版默认没有 IIS 管理控制台,需要先启用 Windows 功能。打开“启用或关闭 Windows 功能”,勾选“Internet Information Services”和“IIS 管理控制台”。如果列表里没有,说明系统版本不支持,得换专业版或直接在 Server 上做。安装完成后,浏览器访问http://localhost看到 IIS 欢迎页就算成功。
常见卡点是端口 80 被占用。Win11 上World Wide Web Publishing Service可能被其他服务(比如 Skype 或某些驱动)抢占。用netstat -ano | findstr :80找到占用进程,要么停掉,要么把 IIS 站点绑定到 8080。
3.2 创建测试站点并确认短名是否生效
在C:\inetpub\wwwroot下新建一个长文件名目录,比如backup_2023_files,里面放一个administrator.aspx。然后在命令行进入该目录,执行:
dir /x如果看到类似BACKUP~1和ADMINI~1.ASP的输出,说明短名已生成。如果没有,检查注册表HKLM\SYSTEM\CurrentControlSet\Control\FileSystem\NtfsDisable8dot3NameCreation是否为 0。Win11 默认可能是 2(按卷设置),需要改成 0 并重启。
提示:改注册表前先导出备份。改完不重启的话,新创建的文件可能仍然不生成短名。
3.3 用 curl 手动验证短名请求的响应差异
在扫描之前,先用 curl 确认目标对短名请求的反应。请求一个存在的短名和一个不存在的短名,对比状态码和响应长度:
curl -I http://localhost/BACKUP~1/ curl -I http://localhost/ZZZZZZ~1/如果第一个返回 403 或 200,第二个返回 404,说明可以利用。如果两个都返回 404,可能是 IIS 版本已修补,或者短名被禁用。我在这步翻过车:Win11 自带的 IIS 10 默认对短名请求返回 404,但响应头里的Content-Length有细微差别,扫描器需要开启“模糊模式”才能识别。
4. 跑通 IIS_shortname_Scanner:命令、参数与结果解读
4.1 解压后的目录结构与依赖安装
假设解压到C:\tools\IIS_shortname_Scanner,目录里通常有:
scanner.py:主扫描脚本dict.txt:前缀字典requirements.txt:依赖列表README.md:用法说明
先装依赖:
cd C:\tools\IIS_shortname_Scanner pip install -r requirements.txt如果requirements.txt里锁定了旧版本requests,在 Python 3.11 上可能报ImportError。我一般直接pip install requests urllib3装最新版,然后手动改一下脚本里的导入语句。
4.2 最小扫描命令与参数含义
最简用法是指定目标 URL 和字典:
python scanner.py -u http://localhost -d dict.txt常用参数我整理成表:
| 参数 | 含义 | 建议值 |
|---|---|---|
-u | 目标 URL | 带协议和端口 |
-d | 字典文件 | 先用内置 dict.txt |
-t | 线程数 | 内网 10,公网 3 |
--delay | 请求间隔(秒) | 0.1 到 0.5,避免触发 WAF |
--fuzzy | 模糊模式 | IIS 10 上建议开启 |
-o | 输出文件 | 保存扫描结果 |
线程数别开太高。我有一次在客户内网用 50 线程扫,直接把 IIS 应用池打挂,日志里全是 503。后来改成 5 线程加 0.2 秒延迟,稳定跑完。
4.3 扫描结果怎么读:短名到长名的还原
扫描器输出通常是一行一个短名,比如:
BACKUP~1 -> backup ADMINI~1.ASP -> admini注意它只能还原前六个字符,后面的部分需要结合其他信息猜。比如BACKUP~1可能是backup_2023、backup_files、backupdb。我一般会把短名丢进一个自定义字典,用dirb或ffuf再跑一轮,把完整路径拼出来。
如果扫描器支持--expand参数,它会自动尝试常见后缀组合。但别指望它全自动,短名扫描只是信息收集的起点,不是终点。
4.4 用 Python 脚本批量验证短名是否存在
有时候扫描器输出太多,需要自己写个小脚本过滤。下面这段代码检查一批短名是否返回非 404:
import requests base = "http://localhost/" shortnames = ["BACKUP~1/", "ADMINI~1.ASP", "UPLOAD~1/"] for sn in shortnames: url = base + sn try: r = requests.get(url, timeout=5, allow_redirects=False) # 404 表示不存在,其他状态码都值得关注 if r.status_code != 404: print(f"[+] {sn} -> {r.status_code} (len={len(r.content)})") except requests.RequestException as e: print(f"[-] {sn} 请求失败: {e}")逻辑说明:allow_redirects=False防止 302 跳转干扰判断;len(r.content)用于区分 IIS 返回的“短名存在但无权访问”和“短名不存在”两种 404 变体。参数timeout=5避免卡死,内网可以设 2 秒。
5. 避坑与排查:短名扫描翻车实录
5.1 扫描器报 404 但目录明明存在
现象:手动dir /x能看到短名,但扫描器全部返回 404。 原因:IIS 10 默认启用了requestFiltering里的denyUrlSequences,其中包含~字符。或者短名请求被 URL 重写规则拦截。 解决:在 IIS 管理器中检查请求筛选->拒绝序列,移除~。如果是重写规则,加一条排除*~*的条件。
5.2 扫描速度极慢,几分钟才出一个结果
现象:线程调到 20,但每秒请求数不到 1。 原因:DNS 解析慢,或者requests没有复用连接。另外,如果目标开启了keep-alive但脚本每次新建会话,握手开销会拖慢速度。 解决:在脚本里用requests.Session(),并设置session.mount('http://', HTTPAdapter(max_retries=3))。线程数别超过目标 IIS 的应用池队列长度。
5.3 扫出来的短名拼不出完整路径
现象:得到BACKUP~1,但尝试backup_2023、backup_files都 404。 原因:短名只保留前六个字符,且去掉了空格和特殊符号。backup 2023的短名也是BACKUP~1,但实际 URL 里空格要编码成%20。 解决:把短名对应的可能长名列表扩大,包含空格、下划线、连字符的组合。用ffuf配合字典跑:
ffuf -u http://localhost/FUZZ -w candidates.txt -mc 200,301,302,4035.4 Win11 上 IIS 短名功能被系统更新重置
现象:昨天还能扫,今天全部 404。 原因:Windows 更新可能重置了NtfsDisable8dot3NameCreation注册表值,或者 IIS 的requestFiltering被组策略覆盖。 解决:把注册表修改和 IIS 配置导出成.reg和.config备份,每次更新后对比恢复。我习惯在测试环境写个 PowerShell 脚本,一键检查并修复。
5.5 工具包被杀软直接删除
现象:解压后scanner.py或 exe 文件消失。 原因:短名扫描行为被 Defender 标记为HackTool。 解决:在虚拟机里关掉实时防护,或者把工具目录加入排除项。别在物理机主系统上跑,血泪经验。
6. 进阶:把短名扫描接进自动化信息收集流水线
短名扫描单独用价值有限,但接进自动化流程后,它能补上目录爆破扫不到的死角。我现在的做法是:用httpx批量探活,对存活 IIS 目标自动跑短名扫描,把结果喂给ffuf做二次扩展,最后用nuclei匹配已知的短名泄露模板。
具体技巧是写一个 Python 包装脚本,调用scanner.py的--json输出(如果没有就自己解析文本),把短名转成候选长名列表。下面是一个简化的流水线片段:
import subprocess import json def run_shortname_scan(target): # 调用扫描器,假设支持 --json 输出 result = subprocess.run( ["python", "scanner.py", "-u", target, "-d", "dict.txt", "--fuzzy", "--json"], capture_output=True, text=True, timeout=300 ) try: data = json.loads(result.stdout) except json.JSONDecodeError: return [] # 提取短名并生成候选长名 candidates = [] for item in data.get("found", []): short = item["shortname"].rstrip("/") prefix = short.split("~")[0].lower() for suffix in ["", "_backup", "_files", "_2023", "_old", ".bak", ".zip"]: candidates.append(prefix + suffix) return candidates # 对多个目标批量执行 targets = ["http://192.168.1.10", "http://192.168.1.11"] for t in targets: cands = run_shortname_scan(t) with open(f"cands_{t.replace('://','_')}.txt", "w") as f: f.write("\n".join(cands))这段代码的关键在于--fuzzy参数必须开,否则 IIS 10 上漏报严重。timeout=300是给慢速目标留余量。生成的候选列表直接丢给ffuf,通常能把短名还原成可访问的完整路径。
验证方法很简单:拿一个已知的短名,手动构造完整路径,看是否返回 200。如果ffuf跑出来一堆 403,说明路径对了但权限不够,这时候可以尝试HEAD请求或者换GET带Range头,有时候能绕过部分权限检查。
我自己的习惯是,每次做完短名扫描,不管结果多少,都把目标 IIS 的web.config和applicationHost.config里的requestFiltering段导出来看一眼。很多运维以为关了短名,其实只关了dir /x的显示,文件系统层面还在生成。这个习惯帮我省过好几次后悔药——有一次客户坚称短名已禁用,结果配置文件里NtfsDisable8dot3NameCreation是 2,按卷设置,而数据卷恰好没关。
希望帮到你。
本文还有配套的精品资源,点击获取