Description
Our security team wrote a vault to protect our password. Can you defeat it? The Java source code is provided.
Setup
Download VaultDoorTraining.java from the challenge page.
Solution
Want to try it yourself first?
The guided walkthrough reveals hints one step at a time.
Step 1Read the checkPassword method
ObservationThe challenge hands you the Java source directly, so there is nothing to reverse. The method name checkPassword() says exactly where the comparison lives, and the expected password will be sitting there as a plain string.Open VaultDoorTraining.java and locate the checkPassword() method. The password is hardcoded as a plain string literal - no encryption, no obfuscation. Reading that string directly gives you the flag contents.What didn't work first
Tried: Trying to compile and run the Java file to test passwords interactively.
The file may not even compile without extra setup, and it does not matter: the flag is already a plain string in the source. Read the literal inside checkPassword() and you are done.
Tried: Scanning main() and other methods for the password instead of reading checkPassword().
Starting at main() and following the control flow drags you through layers of setup before you reach the real check. The name checkPassword() tells you where the comparison happens, so go straight there and look for the string it compares against.
Learn more
Hardcoded credentials - passwords, API keys, tokens, or secrets embedded directly in source code - are one of the most pervasive and dangerous security vulnerabilities in software. When source code is shared, leaked, decompiled from a binary, or checked into version control, every hardcoded secret in it is immediately exposed to anyone who reads it.
This is so common that major secret scanning tools exist specifically to detect it:
- GitHub Secret Scanning - automatically scans public repos for API keys and tokens
- truffleHog - scans git history for high-entropy strings and known secret patterns
- gitleaks - fast secret scanner for git repos and CI pipelines
- detect-secrets - Yelp's tool for preventing secrets from entering codebases
The correct pattern is to store secrets in environment variables or a secrets manager (like AWS Secrets Manager, HashiCorp Vault, or Doppler) and read them at runtime. The source code then contains no secrets, so reading it reveals nothing. This is CWE-798 (Use of Hard-coded Credentials) in the Common Weakness Enumeration and is included in every major security standard including OWASP and NIST.
In the context of this challenge series, the Vault Door challenges progressively introduce more sophisticated obfuscation techniques - but all of them share the same fundamental flaw: the password validation logic is visible in source code. No amount of obfuscation in application logic can substitute for proper cryptographic authentication design.
Decompiling Java makes this vulnerability especially acute. Java programs compile to bytecode (
.classfiles) that can be decompiled back to near-original source code using tools like CFR, Procyon, or Fernflower (built into IntelliJ IDEA). Unlike C/C++ compilation which loses variable names and high-level structure, Java decompilation often produces code indistinguishable from the original. This means even distributing a compiled Java JAR provides essentially no protection for hardcoded secrets - any attacker can decompile it in seconds.Obfuscation tools like ProGuard and DexGuard are commonly used for Android APKs to rename classes, methods, and fields to meaningless single-letter names (e.g., class
VaultDoorbecomes classa). This makes decompiled code harder to read but does not change its functionality. String encryption obfuscators go further by replacing string literals with calls to a decryption function - but the decryption key must be present in the binary, and the string values will still appear at runtime. Debuggers and decompilers that perform dynamic analysis or emulation recover the plaintext strings anyway.The correct authentication pattern: instead of comparing the user's input against a stored plaintext password, a secure system stores a salted cryptographic hash of the password (using bcrypt, Argon2, or scrypt). The input is hashed with the same salt and the hash values are compared - the original password is never stored. Even with full access to source code and the stored hash, an attacker cannot directly reverse the hash to get the password. This is the fundamental design principle behind password storage in every serious authentication system.
Interactive tools
- Strings ExtractorPull printable text from any binary, library, or image. ASCII and UTF-16 detection, configurable minimum length, flag-like highlight, no command line needed.
- Hex ViewerView text or raw hex bytes as a xxd-style hex dump with byte offset, hex columns, and ASCII sidebar. Highlights printable characters and null bytes.
Flag
Reveal flag
picoCTF{w4rm1ng_Up_w1tH_jAv4_...}
Hardcoded plaintext string literal in VaultDoorTraining.java checkPassword()