解析提速+语义深耕!解锁JS/TS规模化审计新能力

admin 2026-03-09 02:35:18 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 该文档介绍了YakProject的IRify引擎更新,重点展示了SyntaxFlow在JS/TS静态分析中的深度语义能力。通过CWE-22ZipSlip和CWE-178Express中间件绕过两个案例,详细解析了规则如何利用数据流分析精准识别漏洞并降低误报。文章强调了跨过程分析与闭包建模的突破,提出未来将扩展规则覆盖现代前端框架与Serverless环境,旨在为安全工程师提供高性能、高保真的规模化审计利器。 综合评分: 85 文章分类: 代码审计,漏洞分析,安全工具,应用安全


cover_image

解析提速+语义深耕!解锁 JS/TS 规模化审计新能力

原创

YAK YAK

Yak Project

2026年3月6日 17:53 北京

#

CWE-22 Zip Slip(压缩包解压目录穿越)

这条 SyntaxFlow 规则用于检测 Zip Slip 类风险:当应用在解压 ZIP/TAR 等压缩包时,将压缩包条目中的路径(例如 ../../evil.sh)直接或间接拼接到本地文件写入 API(如 fs.createWriteStream()、fs.writeFile()、fs.open() 等)上,导致解压结果突破预期目录边界,进而引发任意文件写入、覆盖配置、甚至 RCE 链路。

该问题在 Node.js 生态中非常常见,尤其是“上传压缩包 → 后端解压导入”的业务场景,攻击面清晰、危害上限高,因此规则默认按高风险漏洞处理。

规则的覆盖面针对实际工程做了库级适配,优先抓取常见压缩处理链路中的“条目路径来源”,包括 unzip/unzipper/tar-stream 的 on(‘entry’, …) 回调参数、adm-zip 的 entry.entryName、以及 jszip 的 forEach(relativePath, …) / loadAsync().then(…) 形态。

针对上图不安全代码,内置规则会使用如下 SyntaxFlow 规则匹配 source 点,也就是是 zip 中的 entry 名。

.on('entry', *&nbsp;as&nbsp;$onEntryCallbackAll)$onEntryCallbackAll?{<self><getCall><getCallee><getObject>?{have: /(?i)(unzip|unzipper|tar)/}}&nbsp;as&nbsp;$onEntryCallback$onEntryCallback<getFormalParams>&nbsp;as&nbsp;$entryParam$entryParam.path&nbsp;as&nbsp;$source$entryParam.name&nbsp;as&nbsp;$source$entryParam.linkname&nbsp;as&nbsp;$source

再匹配 sink 点,也就是文件写入函数的路径参数:

// fs.createWriteStream(path) - path is first argumentfs.createWriteStream(*&nbsp;as&nbsp;$fsSink,)// fs.writeFile(path, data, ...) - capture the path argument (first arg)fs.writeFile(*&nbsp;as&nbsp;$fsSink,)fs.writeFileSync(*&nbsp;as&nbsp;$fsSink,)// fs.appendFile(path, data, ...) - capture the path argument (first arg)fs.appendFile(*&nbsp;as&nbsp;$fsSink,)fs.appendFileSync(*&nbsp;as&nbsp;$fsSink,)// fs.open(path, flags, ...) / fs.openSync - capture the path argumentfs.open(*&nbsp;as&nbsp;$fsSink,)fs.openSync(*&nbsp;as&nbsp;$fsSink,)

为了减少误报和提升检测效果,我们这里还定义了 filter 和 guard 用来区分存在过滤和潜在可利用的场景。当 entry 的名称被 basename 处理则不构成 zip-slip,我们把存在 basename 过滤的情况划分为 filter。

但当使用不完全的过滤方式或者使用 if-else 结合 startsWith 和 endsWith 函数判断时则存在利用可能,我们把这类情况归类为存在 guard 条件。

path.basename()&nbsp;as&nbsp;$filter$source?{<self>.indexOf(*)}&nbsp;as&nbsp;$guardedSources$source?{<self>.includes(*)}&nbsp;as&nbsp;$guardedSources$source?{<self>.startsWith(*)}&nbsp;as&nbsp;$guardedSources$source?{<self>.endsWith(*)}&nbsp;as&nbsp;$guardedSources

最后进行检测。检测上采用“来源 → 文件写入”的数据流联通来定位风险,并对结果做了分级:当条目路径几乎“原样”进入文件写入点、且缺少明显校验且不存在PHI 节点时归为 HIGH。

若中间经过 path.join/path.resolve 等路径处理但未能确认形成有效防护,则归为 MID,提示需要进一步人工复核(因为仅做路径拼接/规范化并不等价于安全)。

$fsSink?{<self>&nbsp;#{include: <<<CODE* &&nbsp;$sourceCODE, exclude:&nbsp;<<<CODE*?{opcode: phi} as&nbsp;$__next__CODE}->}&nbsp;as&nbsp;$sink$highCandidates?{<self>&nbsp;#{include: <<<CODE* &&nbsp;$guardedSourcesCODE}->}&nbsp;as&nbsp;$guardedHigh$highCandidates&nbsp;-&nbsp;$guardedHigh as&nbsp;$high$sink&nbsp;-&nbsp;$source as&nbsp;$midAll$midAll&nbsp;-&nbsp;$high as&nbsp;$midCandidates$midCandidates<dataflow(include=<<<CODE* &&nbsp;$filter&nbsp;as&nbsp;$__next__CODE)>&nbsp;as&nbsp;$filteredMid$midCandidates&nbsp;-&nbsp;$filteredMid as&nbsp;$mid

在安全工程实践中,这条规则也强调了可操作的修复模式:推荐使用 path.resolve(TARGET_DIR, entryPath) 并验证结果是否仍在 TARGET_DIR 下(前缀校验),或在业务允许时用 path.basename() 丢弃目录结构,仅保留文件名。

需要注意的是,规则对“条件守卫”属于近似识别(例如 indexOf/includes/startsWith 这类检查)。

它更适合在批量扫描中快速筛出高风险点与可疑点,最终仍建议结合代码语境确认:是否存在可靠的目录边界验证、是否存在符号链接/覆盖等额外风险,以及解压目录是否具备敏感写入权限。

CWE-178 Express 中间件路径大小写绕过

(中间件路径匹配大小写敏感)

这条规则关注的是一个非常“工程化”的授权绕过问题。

在 Express.js 中,字符串路径(如 ‘/admin’)的匹配行为与 正则路径(如 /\/admin\/.*/)在大小写处理上存在差异。很多开发者习惯用 app.use() 在路由入口挂载认证/鉴权/审计等安全中间件,如果此时使用了不带 i 标志的正则表达式作为路径条件,那么该中间件默认是大小写敏感的。

攻击者只要把 URL 改成大写或混合大小写(例如把 /admin/users/45 变成 /ADMIN/users/45),就可能实现“端点仍然命中,但中间件不命中”,从而绕过权限校验,形成典型的 authorization-bypass 风险(对应 CWE-178)。

这条规则的价值在于它并不做“粗暴共现”的启发式判断,而是尽量复现真实绕过关系:先锁定 *.use(regex, handler) 且 regex 不含 i 标志的中间件,再收集同一程序内 *.get/post/… 这类字符串路径端点,最后通过 做精确验证——只有当“中间件的正则在忽略大小写时本应覆盖该端点路径,但在大小写敏感模式下却能被大写变体绕过”时才告警。

这种设计可以显著降低误报,避免出现“项目里既有正则中间件、又有字符串路由就一股脑报”的噪声,让告警更贴近真实可利用链路,也更方便研发快速理解与修复。

修复方向同样非常明确,且对业务侵入小:如果确实需要用正则来表达路径范围,优先在正则末尾添加 i 标志以统一大小写匹配;如果不需要正则的表达能力,则建议改用字符串路径(在 Express 默认未开启大小写敏感路由时为不区分大小写),或者在入口统一规范化请求路径(如转小写)来消除“匹配语义不一致”的根因。

我们先编写 SyntaxFlow 规则用于匹配使用大小写敏感正则表达式的中间件参数使用点:

*.use(*&nbsp;as&nbsp;$middlewareArg,)$middlewareArg?{<self><getCall><getCallee><getObject>?{have: /express/}}&nbsp;as&nbsp;$middlewareArg$middlewareArg?{opcode:&nbsp;const}?{have: /^\/.*\/[^i]*$/}&nbsp;as&nbsp;$caseSensitiveRegex

再匹配 GET, POST 等 API 端点的路径参数:

*.get(*&nbsp;as&nbsp;$endpointArg,)*.post(*&nbsp;as&nbsp;$endpointArg,)*.put(*&nbsp;as&nbsp;$endpointArg,)*.delete(*&nbsp;as&nbsp;$endpointArg,)*.patch(*&nbsp;as&nbsp;$endpointArg,)*.all(*&nbsp;as&nbsp;$endpointArg,)$endpointArg?{<self><getCall><getCallee><getObject>?{have:&nbsp;/express/}}&nbsp;as&nbsp;$endpointArg$endpointArg?{opcode: const}?{have:&nbsp;/^\//}?{!have:&nbsp;/^\/.*\/[gimsuy]*$/}&nbsp;as&nbsp;$stringEndpoint

最终判断是否存在绕过风险:

$caseSensitiveRegex<matchRegexpPath(target="$stringEndpoint")>&nbsp;as&nbsp;$bypassRisk

本次 IRify 引擎的更新标志着 JavaScript/TypeScript 静态分析正式进入了“深水区”。我们不仅在前端解析速度上取得了量级突破,更在跨过程分析、闭包建模等语义层面填补了诸多空白。

迭代方向:从“覆盖”到“精控”

在安全工程实践中,静态分析工具的生命力取决于其规则的生命力。后续我们将从以下两个维度持续打磨:

  • 规则集的持续扩容

目前的内置规则已覆盖了 OWASP Top 10 及 Node.js 生态中的部分高频风险(如 Zip Slip、Express 鉴权绕过)。未来,我们将针对现代前端框架(如 React/Vue 的服务端渲染安全)以及 Serverless 函数计算环境下的特有风险进行规则扩充。

  • SyntaxFlow 分析效果的打磨

跨语言调用链分析:随着 IRify 多语言能力的并进,我们将探索在混合栈(如 Java 后端 + JS 前端)场景下的全链路追踪能力。

安全审计不应是孤立的代码匹配,而应是基于对程序语义深刻理解的逻辑推演。IRify 致力于构建一个高性能、高保真、且对开发者友好的静态分析基座。随着 SyntaxFlow 语法的不断演进与内置规则集的日益丰满,我们希望让“规模化审计”不再是一句口号,而是每一位安全工程师手中的利器。

END

YAK官方资源

Yak 语言官方教程: https://yaklang.com/docs/intro/ Yakit 视频教程: https://space.bilibili.com/437503777 Github下载地址: https://github.com/yaklang/yakit Yakit官网下载地址: https://yaklang.com/ Yakit安装文档: https://yaklang.com/products/download_and_install Yakit使用文档: https://yaklang.com/products/intro/ 常见问题速查: https://yaklang.com/products/FAQ


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:Yak Project YAK YAK《解析提速+语义深耕!解锁 JS/TS 规模化审计新能力》

评论:0   参与:  0