xss-labs Level17 代码审计报告
目标文件:
level17.php| 漏洞类型: Flash XSS ——<embed>将用户输入透传给第三方 SWF 的 flashvars | CWE: CWE-79 / CWE-676(使用含已知漏洞/已废弃组件) | 危害等级: 中危(历史性,现代浏览器不可利用,见备注)
风险路径:GET /level17.php?arg01=a&arg02=<payload>→xsf01.swf?arg01=..&arg02=..→ SWF flashvars 注入
一、漏洞代码定位
level17.php 第 16 行:
echo "<embed src=xsf01.swf?".htmlspecialchars($_GET["arg01"])."=".htmlspecialchars($_GET["arg02"])." width=100% heigth=100%>";
漏洞点: 整行。arg01/arg02 两个用户参数直接拼进 <embed> 的 SWF 加载 URL 的查询串,成为该 SWF 的 flashvars,全程无任何校验/白名单。
二、漏洞原理
<embed src="xsf01.swf?arg01=...&arg02=...">: 浏览器请求 SWF 时会把查询串交给 Flash 运行时,SWF 通过_root/loaderInfo.parameters读取这些 flashvars。htmlspecialchars只做 HTML 实体转义(浏览器解析时会把&还原成&),不会阻止 flashvars 传递,攻击者可:- 控制
arg01/arg02的值; - 通过把
arg02写成b&<额外参数>=<值>(URL 编码后的&进入 arg02 值),注入任意数量的自定义 flashvars(如clickTAG、ftClickThrough等)。
- 控制
- 已对
xsf01.swf反编译分析: 该 SWF 为 FlashTalking 广告 SDK(含mainClick、ftLinkMode、ftStatBaseURL、_url、customTracking_*等参数),该类广告 SDK 的 flashvars 中 URL 类参数会被其内部getURL/navigateToURL用于跳转,历史上存在通过javascript:协议执行任意 JS 的公开漏洞(CWE-79/Flash gadget)。 - 具体可利用参数名需对该 SWF 做反编译(如 FFDec/jpff 反编译 ActionScript)确认;本报告给出代表性 payload 与验证方法。
三、利用方式与 Yakit 可重放数据包
注入思路: 向 arg02 追加 &<gadget参数>=javascript:...,使其成为 SWF 的 flashvars。
代表性 Payload(URL 解码后):
?arg01=a&arg02=b&clickTAG=javascript:alert(1)
(arg02 实际取值 b&clickTAG=javascript:alert(1),其中 & 需编码为 %26 以被 PHP 当作 arg02 的值,而非拆成独立 GET 参数。)
Yakit 可重放原始请求:
GET /level17.php?arg01=a&arg02=b%26clickTAG%3Djavascript:alert(1) HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0
Accept: text/html
Connection: close
触发方式: 页面加载后嵌入的 SWF 读取到注入的 flashvar,在用户点击广告区域(或特定交互)时执行 javascript:alert(1)。是否自动触发取决于该 SDK 具体实现(通常为点击触发)。
验证建议: 用 Yakit 重放后查看响应中的
<embed src="xsf01.swf?arg01=a&arg02=b&clickTAG=javascript:alert(1)"...>;再对xsf01.swf反编译,确认其 URL 类参数的读取与getURL调用点,替换参数名后实测。
四、修复建议
// 1. 根本修复:移除 Flash 组件(Flash 已于 2020 年 EOL,不应再使用)
// 2. 若暂不能移除:绝不允许把用户参数透传给 SWF
$arg01 = preg_match('/^[a-zA-Z0-9]{1,32}$/', $_GET['arg01'] ?? '') ? $_GET['arg01'] : 'a';
$arg02 = preg_match('/^[a-zA-Z0-9]{1,32}$/', $_GET['arg02'] ?? '') ? $_GET['arg02'] : 'b';
// 仅允许字母数字,彻底阻断 flashvars 注入
echo '<embed src="xsf01.swf?arg01='.$arg01.'&arg02='.$arg02.'" width=100% height=100%>';
// 3. 输出侧:属性加引号 + 编码,避免引号逃逸
要点:
- 使用已废弃且有历史漏洞的 Flash 组件本身即安全债(CWE-676/1104);长期方案是迁移到 HTML5 视频/富媒体并移除 SWF 依赖。
- 透传给第三方可执行组件的参数必须强校验白名单(严格字符集/长度),不允许携带
&、=、:等结构字符。 - 若必须保留下发参数,由服务端按业务构造完整的、不可被客户端改写的 flashvars。
五、备注
- 可利用性说明(重要): Flash Player 已停止支持,主流浏览器(Chrome 88+、Edge 88+、Firefox 84+、Safari 14+)已彻底移除 Flash 运行时。因此本关及 level18-20 在当前浏览器中已无法直接触发,属于历史性漏洞;审计价值在于识别"透传不可信输入给第三方可执行组件 + 引入含已知漏洞组件"的架构缺陷。
- 反编译结论:
xsf01.swf为 FlashTalking 广告 SDK 压缩包(CWS 头,zlib 压缩),字符串中含mainClick/ftLinkMode/ftStatBaseURL等参数。 - 通用教训: 只要参数被交到可执行运行时(Flash/小程序/插件),就必须按"可注入面"对待,HTML 转义不能代表任何防护。