Disable Functions Bypass - dl Function
Tip
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)
Ucz się i ćwicz Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Wsparcie dla HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.
dl() lets PHP load a shared extension at runtime. If you can make it load an attacker-controlled module, you can register a new PHP function that internally calls execve, system, or any other native primitive and therefore bypass disable_functions.
This is a prawdziwy prymityw, but on modern targets it is far less common than older writeups suggest.
Dlaczego to obejście jest dziś rzadkie
Główne przeszkody to:
dl()must exist and must not be disabledenable_dlmust still allow dynamic loading- The target SAPI must support
dl() - The payload must be a valid PHP extension compiled for the same target ABI
- The extension must be reachable from the configured
extension_dir
The official PHP manual is the most important reality check here: dl() is only available for CLI and embed SAPIs, and for the CGI SAPI when run from the command line. That means the technique is usually not available in normal PHP-FPM/mod_php web requests, so check the SAPI before spending time building a payload.
Also note that enable_dl is an INI_SYSTEM setting and, as of PHP 8.3.0, PHP documents it as przestarzałe, so you usually cannot flip it at runtime from attacker-controlled PHP code.
If dl() is not viable, go back to the broader list of module/version dependent bypasses.
Szybkie rozpoznanie z footholda
Zanim coś zbudujesz, zbierz dokładne parametry, które moduł musi spełniać:
<?php
phpinfo();
echo "PHP_VERSION=" . PHP_VERSION . PHP_EOL;
echo "PHP_SAPI=" . php_sapi_name() . PHP_EOL;
echo "ZTS=" . (PHP_ZTS ? "yes" : "no") . PHP_EOL;
echo "INT_BITS=" . (PHP_INT_SIZE * 8) . PHP_EOL;
echo "enable_dl=" . ini_get("enable_dl") . PHP_EOL;
echo "extension_dir=" . ini_get("extension_dir") . PHP_EOL;
echo "disabled=" . ini_get("disable_functions") . PHP_EOL;
?>
Co Cię interesuje:
PHP_SAPI: jeśli tofpm-fcgilubapache2handler,dl()zwykle jest ślepszym zaułkiem dla web exploitationextension_dir: payload musi być ładowany stądPHP Version, architecture, debug/non-debug, oraz ZTS/non-ZTS: Twój moduł musi się z nimi zgadzaćdisable_functions: potwierdź, czydljest nieobecne, ponieważ jest zablokowane, czy dlatego, że SAPI tego nie obsługuje
Praktyczne ograniczenia eksploatacji
1. Zwykle potrzebujesz dostępu do zapisu w extension_dir
To największe wąskie gardło.
dl() przyjmuje nazwę pliku rozszerzenia, a PHP ładuje go z extension_dir. W praktyce oznacza to, że zwykły arbitralny upload pliku do /var/www/html/uploads nie wystarczy. Nadal potrzebujesz ścieżki, aby umieścić .so/.dll tam, skąd PHP faktycznie ładuje rozszerzenia.
Realistyczne sytuacje, w których to staje się eksploitable:
- CTFs lub celowo słabe laboratoria, gdzie
extension_dirjest zapisywalny - shared-hosting lub błędy w konfiguracji kontenera, które ujawniają zapisywalną ścieżkę rozszerzeń
- oddzielny primitive do arbitralnego zapisu plików, który już sięga
extension_dir - Post-exploitation scenariusze, gdzie już eskalowałeś wystarczająco, by upuścić pliki tam
2. Moduł musi odpowiadać buildowi celu
Dopasowanie samego PHP_VERSION nie wystarcza. Rozszerzenie musi też pasować pod kątem:
- OS i architektury CPU
- oczekiwań libc/toolchain
ZEND_MODULE_API_NO- build debug vs non-debug
- ZTS vs NTS
Jeśli to nie będzie pasować, dl() zawiedzie lub spowoduje crash procesu.
3. open_basedir nie jest tu główną obroną
Gdy już możesz umieścić moduł w extension_dir i wywołać dl(), kod rozszerzenia wykonuje się wewnątrz procesu PHP. W tym momencie istotną barierą nie było open_basedir, lecz możliwość dostarczenia poprawnego shared object do ścieżki ładowania rozszerzeń.
Budowanie złośliwego rozszerzenia
Klasyczna ścieżka nadal jest ważna:
- Odtwórz build ofiary tak dokładnie, jak to możliwe
- Użyj
phpize,./configureimake, aby zbudować shared extension - Eksportuj funkcję PHP, np.
bypass_exec($cmd), która opakuje natywne wykonanie komend - Prześlij skompilowany moduł do
extension_dir - Załaduj go za pomocą
dl()i wywołaj eksportowaną funkcję
Atak jest stary, ale wciąż istotny, ponieważ changelogi PHP 8.x wciąż zawierają poprawki crashów specyficznych dla dl(). Primitive nadal istnieje; trudna część to znalezienie deploymentu, gdzie jest osiągalna i gdzie możesz wgrać pasujący moduł.
Minimalny przepływ pracy
Na maszynie atakującego
mkdir bypass && cd bypass
phpize
./configure
make
Wynikowa biblioteka współdzielona (.so) zwykle znajduje się w modules/.
Jeśli kompilujesz na innym środowisku niż target, traktuj wygenerowany plik jako szkic, dopóki nie zweryfikujesz, że ABI pasuje do victim.
Ładowanie i użycie rozszerzenia
Jeśli target rzeczywiście obsługuje dl() i moduł znajduje się w extension_dir, po stronie runtime wszystko jest proste:
<?php
if (!extension_loaded('bypass')) {
dl('bypass.so'); // use the correct filename for the target platform
}
echo bypass_exec($_GET['cmd']);
?>
Na Windows nazwa pliku będzie zazwyczaj .dll, natomiast na systemach Unix-like zwykle .so.
Notatki atakującego
- Nie zakładaj, że to działa zdalnie tylko dlatego, że
function_exists("dl")zwraca true w jakiejś dokumentacji lub starym writeupie; zweryfikuj działający SAPI - Nieudana próba
dl()może zakończyć proces PHP (worker), jeśli moduł jest niekompatybilny - Od PHP 8 funkcje wyłączone są usuwane z tabeli funkcji, więc enumeracja z poziomu userland może różnić się od starszych wpisów
- Jeśli nie możesz zapisać do
extension_dir, ta technika zwykle jest mniej praktyczna niż FPM/FastCGI,LD_PRELOADlub omówione wcześniej obejścia specyficzne dla modułu
References
Tip
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)
Ucz się i ćwicz Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Wsparcie dla HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.


