JADX安全性研究
字数 1156 2025-08-18 11:36:53
JADX安全性研究教学文档
1. JADX简介
JADX是一款强大的Android反编译工具,能够将DEX/APK文件反编译为Java源代码。它提供了GUI和命令行两种使用方式,是Android安全研究人员常用的工具之一。
2. JADX历史漏洞分析
2.1 CVE-2022-0219 - XXE漏洞
漏洞描述
JADX曾存在XML外部实体(XXE)注入漏洞,攻击者可通过构造恶意APK文件,利用JADX解析时的XML处理不当实现任意文件读取。
漏洞原理
- 早期版本虽然实现了
XmlSecurity类,但在实际XML解析时未调用 - 导致XML解析时未禁用外部实体引用,可能加载恶意DTD或外部实体
修复方案
修复提交:c6a78c0d6dc990a4a0f8962d51823aa6ca3aefd2
安全限制代码:
public static DocumentBuilderFactory getSecureDbf() throws ParserConfigurationException {
synchronized (XmlSecurity.class) {
if (secureDbf == null) {
secureDbf = DocumentBuilderFactory.newInstance();
secureDbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
secureDbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
secureDbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
secureDbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
secureDbf.setFeature("http://apache.org/xml/features/dom/create-entity-ref-nodes", false);
secureDbf.setXIncludeAware(false);
secureDbf.setExpandEntityReferences(false);
}
}
return secureDbf;
}
安全措施
- 禁用DOCTYPE声明
- 禁用外部DTD加载
- 禁用外部通用实体
- 禁用外部参数实体
- 禁用实体引用节点创建
- 禁用XInclude
- 禁用实体引用扩展
2.2 路径穿越任意文件覆盖漏洞
漏洞发现过程
- 尝试构造恶意APK文件进行测试
- 分析资源名称处理逻辑
关键代码分析
资源别名处理方法:
private String getResAlias(int resRef, String origKeyName, @Nullable FieldNode constField) {
String name;
if (constField == null || constField.getTopParentClass().isSynthetic()) {
name = origKeyName;
} else {
name = getBetterName(root.getArgs().getResourceNameSource(), origKeyName, constField.getName());
}
Matcher matcher = VALID_RES_KEY_PATTERN.matcher(name);
if (matcher.matches()) {
return name;
}
String cleanedResName = cleanName(matcher);
String newResName = String.format("res_0x%08x", resRef);
if (cleanedResName.isEmpty()) {
return newResName;
}
return newResName + "_" + cleanedResName.toLowerCase();
}
名称验证正则表达式:
private static final Pattern VALID_RES_KEY_PATTERN = Pattern.compile("[\\w\\d_]+");
- 只允许字母、数字和下划线组合
可能的绕过点分析
-
useRawResName属性- 当为true时直接返回原始名称
- 但默认初始化为false,仅在测试方法中为true
-
renamedKey重命名- 已存在的resRef会直接返回之前存储的名称
- 但存储的名称也是经过过滤的
-
style类型特殊处理
- style类型文件可能包含点(.)
- 直接返回原始名称不做过滤
实际利用尝试
-
修改resources.arsc文件结构
- 使用010 Editor分析二进制结构
- 修改资源类型为style(0x0E)
-
构造路径穿越payload
- 尝试使用
../../hfile等路径 - 但最终会被路径检查拦截
- 尝试使用
路径检查机制
private static boolean isInSubDirectoryInternal(File baseDir, File file) {
File current = file;
while (true) {
if (current == null) {
return false;
}
if (current.equals(baseDir)) {
return true;
}
current = current.getParentFile();
}
}
- 严格检查目标路径是否在基础目录下
- 无法绕过
漏洞影响
最终发现该漏洞只能覆盖resources文件夹下的文件,无法实现真正的任意文件覆盖,属于鸡肋安全问题。
修复方案
修复提交:d86449a8ea26381d0ce6fafaed7deb7542dfd70b
3. 安全开发建议
-
XML处理安全规范
- 始终使用安全的XML解析配置
- 禁用所有外部实体引用
- 使用白名单而非黑名单策略
-
文件路径处理规范
- 对用户提供的文件名进行严格验证
- 使用规范化路径进行比较
- 实施严格的目录限制
-
资源处理规范
- 对资源名称实施严格过滤
- 避免特殊类型的例外处理
- 实施多层防御机制