Decryptify (THM)

Use your exploitation skills to uncover encrypted keys and get RCE.

Into

Hello everyone yet again wonderful machine hopefully let's dive right into it.

Enumeration.

PORT     STATE SERVICE REASON         VERSION
22/tcp   open  ssh     syn-ack ttl 63 OpenSSH 8.2p1 Ubuntu 4ubuntu0.11 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   3072 ac:da:59:62:97:38:0f:05:be:1f:17:da:33:dc:6a:e4 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDWr5CYs2rQ4+KaoZ7IxpR1eMCXp959NcdkOTxV/on8TYD2rsisu/Ic4gZho1gHu8WI0VPPlsPJgmKftpfONFXCRI6YJY3Mp3rvfIQHVw/khOVvS00ItnLWdFqY6pgTtPO1yc7BjCFR9/+wWfiFO13AmqI4sKU/4RzQa4ZbuL5jXHIVpeOxYad3TJ9OOSLUFC+NL2vPXwZywscNisZMmZq9HGkscILd6C6o6dgX77gTV9/yCoTAFd9G8uFKE4K6Xr3/O8ONSBmzq+Klhsat8HLxFgJAYIUIJ1N4UqhBmxjrBxMJNtA6Ig/13yAa5X9HtgBnO+lTGbD9+aSorLBWlMxBhk9BB3eHflXnWFTmgz5cEPKD9gM2KoRuqeuIQgz6kADv6vi57CQEnorOHtpbGvERlgLQ2M5bUccH2W7WutwUx6brKZB1UxRUAxzdcYBBM9Si3RdO+3HuYZKY1fWFIIBTJEmzp6Oxt1sBoA8qGgqUGiAw5kcIHp7ZNqoedJILzVM=
|   256 17:b3:26:5d:cf:37:1a:27:cb:ab:49:35:7a:53:f2:69 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPue04Dvo5S0dKU1ecOzNnk84RR3QbcwAWxKW2aVrb4iYj7MvDFrjB4z7/zeHvp+YTPYR3wF4Ge9Sb2d7yHnkNs=
|   256 a1:98:d5:c8:cc:05:28:98:d7:b4:aa:43:d0:96:40:ea (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIP0Sdd2f4RCAJP6wx3XkcNu1prfQMgcoPmapVmgjWdz5
1337/tcp open  http    syn-ack ttl 63 Apache httpd 2.4.41 ((Ubuntu))
| http-cookie-flags:
|   /:
|     PHPSESSID:
|_      httponly flag not set
| http-methods:
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-title: Login - Decryptify
|_http-server-header: Apache/2.4.41 (Ubuntu)
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: general purpose
Running: Linux 4.X

So we have website on 1337 let's check what it has.

We have this login page am gonna use feroxbrute to find more about the website.

301      GET        9l       28w      316c http://10.10.46.118:1337/js => http://10.10.46.118:1337/js/
200      GET        1l       15w      723c http://10.10.46.118:1337/js/api.js
200      GET       28l       66w     1043c http://10.10.46.118:1337/api.php
200      GET        7l     1031w    78129c http://10.10.46.118:1337/js/bootstrap.bundle.min.js
200      GET        6l     2272w   220780c http://10.10.46.118:1337/css/bootstrap.min.css
200      GET       76l      184w     3220c http://10.10.46.118:1337/
301      GET        9l       28w      324c http://10.10.46.118:1337/javascript => http://10.10.46.118:1337/javascript/
301      GET        9l       28w      317c http://10.10.46.118:1337/css => http://10.10.46.118:1337/css/
301      GET        9l       28w      324c http://10.10.46.118:1337/phpmyadmin => http://10.10.46.118:1337/phpmyadmin/
301      GET        9l       28w      318c http://10.10.46.118:1337/logs => http://10.10.46.118:1337/logs/
200      GET        9l       88w      644c http://10.10.46.118:1337/logs/app.log

So we have some interesting files the first one that attract my attention was api.php let's check it.

hmm so it ask for a password so let's look more into the files we have file with the same name under the js/api.js.

so obsfecuted code am gonna use GPT to trying to understand what is this code doing.

const array = [
  '16OTYqOr', 
  '861cPVRNJ', 
  '474AnPRwy', 
  'H7gY2tJ9wQzD4rS1', 
  '5228dijopu', 
  '29131EDUYqd', 
  '8756315tjjUKB', 
  '1232020YOKSiQ', 
  '7042671GTNtXE', 
  '1593688UqvBWv', 
  '90209ggCpyY'
];

function getValue(index) {
  return array[index - 0x165];  // Offset to match obfuscated indexes
}

const c = getValue(0x169); // Resolves to 'H7gY2tJ9wQzD4rS1'

console.log(c); // Output: 'H7gY2tJ9wQzD4rS1'

using GPT we can see that this always return the same results H7gY2tJ9wQzD4rS1 i think this is the password for the api.php let see.

and indeed it was the password but before i go more into this there is a log file let's check it out.

Hmm interesting but gonna put this away for now and am gonna check the api.php.

Flag 1

so after something i came up with the following requirement.

1

Decode the old invite code

We need to do this in order to find the random value

2

we need some way to get feeling of the seed value

if we are able to find the seed value we can reverse the operation.

3

finding the seed will require finding the constant value

we need to find the constant value in order to find the seed

So after spending more time i found that its not practical to use mt_rand for cryptographic operation as it not secure. I also found that the relation between the seed value and the resulted random value is one to one relationship.

With that i start searching for some way to get feeling of the seed and i found this.

i used this C code to find the seed and i got this.

so i tested these but they not work now that i realized i maybe did something stupied and that's way it did not work but we gonna continue on the path i found and i will be returning to this to test me.

After that i take the lower range and upper range and make a PHP code that brute-force the range trying to find the constant value not the seed.

Because if we are able to find the constant value are then are able to find the seed easily.


<?php
// Our token generation function.
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;
}

$email = "alpha@fake.thm";
// The target random value 
$target = 1348337122;

$lower_bound = 1324931;      // smallest sample constant
$upper_bound = 2232092689;    // largest sample constant

echo "Starting brute-force search for a constant that produces random value: $target\n";
echo "Searching between $lower_bound and $upper_bound...\n";

$found = false;
$progressStep = 1000000; 

for ($constant = $lower_bound; $constant <= $upper_bound; $constant++) {
    $seed_value = calculate_seed_value($email, $constant);
    mt_srand($seed_value);
    $random = mt_rand();

    if ($random === $target) {
        echo "Found matching constant: $constant\n";
        $found = true;
        break;
    }
    
    if ($constant % $progressStep === 0) {
        echo "Checked constant: $constant\n";
    }
}

if (!$found) {
    echo "No constant found in the range $lower_bound to $upper_bound that produces the target value.\n";
}
?>

after 2 min i was able to find it.

now that i have the constant i can generate using the same formula but with the email we found in the log file.

Flag 2.

After we get access i spend sometime digging into the role and trying to crack it but that was not the why

I notice something odd in the source code of the web page.

this form was doing something but i do not know what it doing so i change the type.

When i modified it i get the following results.

Few things we can notice the error message tell us something about padding the first thing comes to my mind is a known vulnerability called Oracle Padding Attack.

We can find more info here

i spend sometime testing with some tools like padbuster and another tool but none of them gives results and then i tested with pader.

and then i got this. the first argument is the URL follow by the cookies and finally the encryption have from the get request we saw earlier.

This here display the date the Year.

and now let's attempt to encrypt some payload inf order to execute it on the server.

Now we just replace the old value with this and we shall get the flag.

Final thought

this machine was so much fun like really fun the crypto graphic analysis and reversing something i really like to do 👏.

Last updated