在APK静态分析中,硬编码密码可能出现在以下位置:
# 使用apktool解包APK
apktool d target.apk -o output_dir
# 使用jadx反编译为Java代码
jadx -d output_dir target.apk
# 在解包目录中搜索关键词
grep -r "password" output_dir/
grep -r "pwd" output_dir/
grep -r "secret" output_dir/
grep -r "key" output_dir/
# 使用MobSF进行自动化扫描
docker run -it opensecurity/mobile-security-framework-mobsf
// 反编译发现的漏洞代码示例
public class DatabaseHelper {
private static final String DB_PASSWORD = "Admin@123"; // 硬编码密码
public Connection getConnection() {
return DriverManager.getConnection(
"jdbc:mysql://localhost:3306/mydb",
"root",
DB_PASSWORD
);
}
}
风险:数据库凭证直接暴露在代码中,攻击者可轻易获取。
<!-- res/values/strings.xml -->
<string name="api_password">P@ssw0rd2023!</string>
风险:资源文件通常不加密,容易被提取。
# 在lib/armeabi-v7a/libnative.so中搜索字符串
strings libnative.so | grep -i "password"
发现:可能输出类似default_password=123456
的内容。
移除硬编码凭证:
代码层面改进:
// 改为从安全存储获取
public String getDbPassword() {
return KeyStore.get("db_password_key");
}
加固措施:
安全测试:
import os
import re
from pathlib import Path
SENSITIVE_KEYWORDS = [
"password", "pwd", "secret",
"key", "credential", "token"
]
def scan_for_hardcoded_creds(apk_path):
print(f"Scanning {apk_path} for hardcoded credentials...")
# 1. 使用apktool解包
os.system(f"apktool d {apk_path} -o temp_apk")
# 2. 递归搜索敏感字符串
vuln_files = []
for root, _, files in os.walk("temp_apk"):
for file in files:
if file.endswith((".smali", ".xml", ".properties")):
file_path = Path(root) / file
try:
content = file_path.read_text()
for keyword in SENSITIVE_KEYWORDS:
if re.search(f"{keyword}[=:].*[\"']", content, re.I):
vuln_files.append(str(file_path))
break
except:
continue
# 3. 清理临时文件
os.system("rm -rf temp_apk")
return vuln_files
硬编码密码是移动应用常见的高危漏洞,通过静态分析可以有效地发现这类问题。开发团队应当建立安全编码规范,避免在应用中直接存储敏感凭证,并定期进行安全审计以降低风险。