Back to Blog
critical SEVERITY7 min read

How weak PBKDF2 key derivation happens in Frida Android server and how to fix it

The Frida Android server used PBKDF2WithHmacSHA1And8BIT with only 128 iterations to derive secret keys for device attestation. This critically weak configuration made password brute-forcing trivial, allowing attackers who obtained the derived key to recover the original password in seconds. The fix upgraded to PBKDF2WithHmacSHA256 with 600,000 iterations, meeting modern cryptographic standards.

O
By Orbis AppSec
Published July 26, 2026Reviewed July 26, 2026

Answer Summary

The Frida Android server (server.js:386) suffered from weak PBKDF2 key derivation (CWE-916: Use of Password Hash With Insufficient Computational Effort). It used PBKDF2WithHmacSHA1And8BIT with only 128 iterations instead of the recommended minimum of 600,000. The fix upgraded to PBKDF2WithHmacSHA256 with 600,000 iterations, making password brute-forcing computationally infeasible and protecting the secret keys used for device attestation.

Vulnerability at a Glance

cweCWE-916 (Use of Password Hash With Insufficient Computational Effort)
fixUpgraded to PBKDF2WithHmacSHA256 with 600,000 iterations
riskAttackers can brute-force passwords to recover secret keys used for device attestation
languageJavaScript (Frida instrumentation framework)
root causePBKDF2 configured with SHA1 and only 128 iterations instead of SHA256 with 600,000+ iterations
vulnerabilityWeak PBKDF2 key derivation with insufficient iterations

Introduction

In the Frida Android server codebase, we discovered a critical weak key derivation vulnerability in frida/android/server.js at line 386. The code used PBKDF2WithHmacSHA1And8BIT with only 128 iterations to derive a secret key for device attestation—a configuration so weak that it essentially provided no protection against password brute-forcing.

The vulnerable code appeared in the device attestation logic where the Frida server generates a secretKey from a password:

let factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1And8BIT")
let key = PBEKeySpec.$new(passwordChars, secretKeySalt, 128, 512)
let secretKey = Java.cast(factory.generateSecret(key), Key).getEncoded()

This matters because the derived secretKey is exposed via an HTTP /info endpoint and used for device attestation. Any attacker who intercepts this key, obtains it from a memory dump, or finds it in compromised storage can brute-force the original password in seconds due to the catastrophically low iteration count.

The Vulnerability Explained

PBKDF2 (Password-Based Key Derivation Function 2) is designed to make password cracking computationally expensive by applying a hash function thousands or hundreds of thousands of times. The iteration count is the critical security parameter—it determines how much computational work an attacker must perform to test each password guess.

Here's the vulnerable code from server.js:386:

let factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1And8BIT")
let key = PBEKeySpec.$new(passwordChars, secretKeySalt, 128, 512)

This configuration has two critical flaws:

  1. SHA1 is cryptographically weak: The algorithm uses PBKDF2WithHmacSHA1And8BIT, which relies on SHA1. While HMAC-SHA1 is somewhat more resilient than plain SHA1, modern cryptographic standards recommend SHA256 or SHA512.

  2. 128 iterations is catastrophically insufficient: The third parameter to PBEKeySpec.$new() specifies 128 iterations. OWASP recommends a minimum of 600,000 iterations for PBKDF2-HMAC-SHA256 as of 2023. With only 128 iterations, an attacker can test millions of password guesses per second on a modern GPU.

How This Could Be Exploited

The exploitation scenario is straightforward:

  1. Attacker obtains the derived secretKey: This could happen through:
    - Intercepting the /info HTTP endpoint where the key is exposed
    - Dumping the memory of the Frida server process
    - Accessing compromised storage where the key is cached

  2. Attacker launches brute-force attack: With the secretKey, salt, and knowledge of the PBKDF2 configuration (128 iterations, SHA1), the attacker can:
    - Test common passwords from breach databases
    - Try dictionary words and variations
    - Perform targeted guessing based on social engineering

  3. Password recovered in seconds: With 128 iterations, a modern GPU can test approximately 100 million passwords per second against PBKDF2-HMAC-SHA1. A typical 8-character password with mixed case and numbers (62^8 ≈ 218 trillion combinations) could theoretically be cracked in about 25 days, but in practice, attackers use smart dictionaries and most passwords fall within the first few million guesses.

Real-World Impact

In the Frida Android server context, this vulnerability compromises device attestation. An attacker who recovers the original password can:

  • Forge device attestation credentials
  • Impersonate legitimate devices
  • Bypass security controls that rely on the attestation mechanism
  • Potentially gain unauthorized access to protected resources or APIs

The Fix

The fix makes two critical improvements to the PBKDF2 configuration in frida/android/server.js:

Before (vulnerable code):

let factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1And8BIT")
let key = PBEKeySpec.$new(passwordChars, secretKeySalt, 128, 512)

After (secure code):

let factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256")
let key = PBEKeySpec.$new(passwordChars, secretKeySalt, 600000, 512)

What Changed

  1. Algorithm upgrade: PBKDF2WithHmacSHA1And8BITPBKDF2WithHmacSHA256
    - SHA256 is the current cryptographic standard, providing significantly better collision resistance
    - Removes the deprecated SHA1 algorithm from the security chain

  2. Iteration count increase: 128600000
    - Increases the computational work by a factor of 4,687.5×
    - Meets the OWASP 2023 recommendation for PBKDF2-HMAC-SHA256
    - Makes brute-forcing computationally infeasible with current technology

Security Improvement

With 600,000 iterations of PBKDF2-HMAC-SHA256, the time to test passwords increases proportionally. An attacker who could previously test 100 million passwords per second can now test only about 21,000 passwords per second (100M / 4687.5). This transforms a seconds-to-minutes attack into a weeks-to-months attack, effectively neutralizing the threat for properly chosen passwords.

The fix maintains backward compatibility concerns by keeping the same key length (512 bits) and salt mechanism, changing only the algorithm and iteration count. This ensures that the security improvement doesn't break existing functionality while dramatically enhancing protection.

Key Takeaways

  • Never use PBKDF2 with fewer than 600,000 iterations for SHA256: The 128 iterations used in server.js:386 provided virtually no protection against brute-force attacks on modern hardware.

  • SHA1 is deprecated for new cryptographic implementations: Even in HMAC mode, SHA256 or SHA512 should be preferred for PBKDF2 in production code.

  • Exposing derived keys via HTTP endpoints amplifies the risk: The Frida server's /info endpoint made the secretKey accessible to attackers, turning a theoretical vulnerability into a practical exploit vector.

  • Iteration counts must scale with computing power: What was secure in 2010 (10,000 iterations) is inadequate in 2024. Build systems that can adapt to evolving standards.

  • Device attestation security depends on every component: A weak key derivation function undermines the entire attestation chain, regardless of how secure other components are.

How Orbis AppSec Detected This

  • Source: Password input to the device attestation key derivation function in frida/android/server.js
  • Sink: PBEKeySpec.$new(passwordChars, secretKeySalt, 128, 512) at line 386, which uses PBKDF2WithHmacSHA1And8BIT with only 128 iterations
  • Missing control: Insufficient iteration count (128 vs. recommended 600,000) and use of deprecated SHA1 algorithm instead of SHA256
  • CWE: CWE-916 (Use of Password Hash With Insufficient Computational Effort)
  • Fix: Upgraded to PBKDF2WithHmacSHA256 with 600,000 iterations, meeting OWASP 2023 standards

Orbis AppSec automatically detected this vulnerability and opened a pull request with the fix. Try Orbis AppSec on your repositories to find and fix issues like this automatically.

Conclusion

The weak PBKDF2 configuration in the Frida Android server demonstrates how subtle cryptographic misconfigurations can create critical vulnerabilities. By using SHA1 with only 128 iterations, the code transformed a theoretically secure key derivation function into a mechanism that provided virtually no protection against password brute-forcing.

The fix—upgrading to PBKDF2WithHmacSHA256 with 600,000 iterations—brings the implementation in line with current OWASP standards and makes password recovery computationally infeasible with current technology. This case highlights the importance of staying current with cryptographic best practices and using static analysis tools to detect configuration weaknesses that manual code review might miss.

For developers working with password-based cryptography: always verify that your iteration counts, algorithm choices, and key handling practices meet current security standards. The computational landscape changes rapidly, and yesterday's secure configuration may be today's vulnerability.

Prevention and further reading

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #22

Related Articles

high

How Denial of Service via Infinite Loop Happens in JavaScript Dependencies and How to Fix It

CVE-2026-67213 is a high-severity denial of service vulnerability in nanoid before version 5.1.6 that triggers an infinite loop during random ID generation when processing specially crafted input. We upgraded nanoid across the entire dependency tree to patch this flaw and prevent attackers from freezing application threads. This fix ensures that ID generation remains resilient even when handling adversarial input patterns.

high

How Sensitive Data Exposure happens in Zotero plugins and how to fix it

A high-severity data exposure vulnerability in `Zotero.ts` automatically transmitted complete document metadata—including private notes, attachment paths, and tags—to external LLM services without user consent. The fix replaces broad `item.toJSON()` serialization with explicit field selection, sending only essential bibliographic data.

high

How missing dependency update cooldowns happen in GitHub Dependabot configurations and how to fix it

A semgrep scan flagged `.github/dependabot.yml` for lacking a cooldown period, meaning Dependabot would immediately propose updates to brand-new package versions across npm, Bundler, and Docker ecosystems. The fix adds a `cooldown: default-days: 7` block to every `package-ecosystem` entry, forcing a one-week waiting period before newly published releases are considered — reducing exposure to malicious or unstable package drops.

high

How dependabot-missing-cooldown happens in GitHub Actions/Node.js and how to fix it

The repository's `.github/dependabot.yml` had no cooldown period configured, meaning Dependabot could immediately propose updates to newly published package versions with zero time for the community to flag malware or instability. The fix adds a `cooldown` block with `default-days: 7` to both the `npm` and `github-actions` ecosystems, forcing a 7-day waiting period before new releases are surfaced as update PRs.

high

How Path Traversal Happens in TensorFlow's Data Service and How to Fix It

TensorFlow's data service dispatcher validated dataset IDs against forward-slash traversal attacks but overlooked backslash characters on non-Windows platforms, allowing attackers to escape the root directory. A targeted fix adds explicit backslash validation across all platforms, closing a high-severity path traversal vulnerability in the snapshot management system.

critical

How Unbounded WebSocket Message Handling Causes Resource Exhaustion in Node.js and How to Fix It

The WebSocketCrossServerAdapter class in a popular Node.js WebSocket library lacked any rate limiting on inbound messages, allowing attackers to flood Redis nodes and WebSocket servers with high-volume traffic. The fix introduces a configurable `rateLimit` option that caps messages per connection per second, preventing resource exhaustion while preserving legitimate functionality.