Disable Functions Bypass - dl Function

Tip

Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Μάθετε & εξασκηθείτε στο Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Υποστηρίξτε το HackTricks

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.

Αυτό είναι ένα real primitive, αλλά σε σύγχρονους στόχους είναι πολύ λιγότερο συνηθισμένο από ό,τι υποδεικνύουν παλαιότερα writeups.

Γιατί αυτή η bypass είναι ασυνήθιστη σήμερα

Οι κύριοι ανασταλτικοί παράγοντες είναι:

  • dl() must exist and must not be disabled
  • enable_dl must 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

Το επίσημο εγχειρίδιο του PHP είναι ο πιο σημαντικός έλεγχος πραγματικότητας εδώ: dl() is only available for CLI and embed SAPIs, and for the CGI SAPI when run from the command line. Αυτό σημαίνει ότι η τεχνική είναι usually not available in normal PHP-FPM/mod_php web requests, οπότε ελέγξτε την SAPI πριν αφιερώσετε χρόνο στο να φτιάξετε ένα payload.

Σημειώστε επίσης ότι το enable_dl είναι μια ρύθμιση INI_SYSTEM και, από την PHP 8.3.0, η PHP το τεκμηριώνει ως deprecated, οπότε συνήθως δεν μπορείτε να το αλλάξετε κατά το runtime από PHP κώδικα που ελέγχεται από επιτιθέμενο.

If dl() is not viable, go back to the broader list of module/version dependent bypasses.

Γρήγορη αξιολόγηση από ένα foothold

Πριν φτιάξετε οτιδήποτε, συλλέξτε τις ακριβείς παραμέτρους που πρέπει να ταιριάξει το module:

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

What you care about:

  • PHP_SAPI: αν αυτό είναι fpm-fcgi ή apache2handler, dl() συνήθως είναι αδιέξοδο για web exploitation
  • extension_dir: το payload πρέπει να φορτωθεί από εδώ
  • PHP Version, architecture, debug/non-debug, and ZTS/non-ZTS: το module σας πρέπει να ταιριάζει με αυτά
  • disable_functions: επιβεβαιώστε αν το dl λείπει επειδή έχει απενεργοποιηθεί ή επειδή το SAPI δεν το υποστηρίζει

Practical exploitation constraints

1. You normally need write access to extension_dir

Αυτό είναι το μεγαλύτερο εμπόδιο.

dl() παίρνει το όνομα αρχείου επέκτασης, και το PHP το φορτώνει από το extension_dir. Στην πράξη, αυτό σημαίνει ότι ένα κανονικό arbitrary file upload στο /var/www/html/uploads δεν αρκεί. Χρειάζεστε ακόμα μια διαδρομή για να τοποθετήσετε ένα .so/.dll εκεί όπου το PHP θα φορτώνει πραγματικά extensions.

Ρεαλιστικές περιπτώσεις όπου αυτό γίνεται εκμεταλλεύσιμο:

  • CTFs ή intentionally weak labs όπου το extension_dir είναι εγγράψιμο
  • shared-hosting ή λάθη σε containers που εκθέτουν μια διαδρομή extension με δυνατότητα εγγραφής
  • Ένας ξεχωριστός arbitrary file write primitive που ήδη φτάνει στο extension_dir
  • Post-exploitation scenarios όπου έχετε ήδη escalated αρκετά για να drop files εκεί

2. The module must match the target build

Το να ταιριάζει μόνο το PHP_VERSION δεν αρκεί. Η επέκταση επίσης πρέπει να ταιριάζει με:

  • OS and CPU architecture
  • libc/toolchain expectations
  • ZEND_MODULE_API_NO
  • debug vs non-debug build
  • ZTS vs NTS

Αν αυτά δεν ταιριάζουν, το dl() θα αποτύχει ή θα καταρρεύσει η διεργασία.

3. open_basedir is not the main defense here

Μόλις μπορέσετε να τοποθετήσετε το module στο extension_dir και να καλέσετε το dl(), ο κώδικας της επέκτασης εκτελείται μέσα στη διεργασία PHP. Σε εκείνο το σημείο το σχετικό εμπόδιο δεν ήταν το open_basedir, αλλά η ικανότητα να προσγειώσετε ένα έγκυρο shared object στη διαδρομή φόρτωσης επεκτάσεων.

Building the malicious extension

Η κλασική μέθοδος παραμένει έγκυρη:

  1. Αναπαράγετε το victim build όσο το δυνατόν πιο πιστά
  2. Χρησιμοποιήστε phpize, ./configure, και make για να χτίσετε μια shared extension
  3. Εξάγετε μια PHP function όπως bypass_exec($cmd) που τυλίγει την εγγενή εκτέλεση εντολών
  4. Ανεβάστε το compiled module στο extension_dir
  5. Φορτώστε το με dl() και καλέστε την εξαγόμενη function

Η επίθεση είναι παλιά, αλλά εξακολουθεί να είναι σχετική επειδή τα changelogs του PHP 8.x συνεχίζουν να περιλαμβάνουν διορθώσεις ειδικά για dl()-related crashes. Το primitive εξακολουθεί να υπάρχει· το δύσκολο είναι να βρείτε μια εγκατάσταση όπου είναι προσβάσιμο και όπου μπορείτε να τοποθετήσετε ένα matching module.

Minimal workflow

On the attacker box

mkdir bypass && cd bypass
phpize
./configure
make

Το παραγόμενο shared object θα βρίσκεται συνήθως στο modules/.

Εάν χτίζετε σε διαφορετικό περιβάλλον από τον στόχο, θεωρήστε το παραγόμενο αρχείο ως προσχέδιο μέχρι να επαληθεύσετε ότι το ABI ταιριάζει με το θύμα.

Φόρτωση και χρήση της επέκτασης

Αν ο στόχος υποστηρίζει πραγματικά την dl() και το module είναι μέσα στο extension_dir, το runtime μέρος είναι απλό:

<?php
if (!extension_loaded('bypass')) {
dl('bypass.so'); // use the correct filename for the target platform
}
echo bypass_exec($_GET['cmd']);
?>

Στα Windows, το όνομα αρχείου θα είναι συνήθως .dll, ενώ σε συστήματα τύπου Unix θα είναι συνήθως .so.

Σημειώσεις επιτιθέμενου

  • Μην υποθέτετε ότι αυτό λειτουργεί απομακρυσμένα μόνο και μόνο επειδή function_exists("dl") επιστρέφει true σε κάποια τεκμηρίωση ή παλιό writeup· επιβεβαιώστε το ζωντανό SAPI
  • Μια αποτυχημένη προσπάθεια dl() μπορεί να τερματίσει τον PHP worker αν το module είναι ασύμβατο
  • Από την PHP 8 και μετά, οι απενεργοποιημένες συναρτήσεις αφαιρούνται από τον πίνακα συναρτήσεων, οπότε η userland enumeration μπορεί να διαφέρει από παλαιότερα posts
  • Αν δεν μπορείτε να γράψετε στο extension_dir, αυτή η τεχνική συνήθως είναι λιγότερο πρακτική από FPM/FastCGI, LD_PRELOAD, ή module-specific bypasses που έχουν ήδη καλυφθεί σε αυτήν την ενότητα

References

Tip

Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Μάθετε & εξασκηθείτε στο Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Υποστηρίξτε το HackTricks