
Análisis técnico en profundidad de PHP2Shell: encadenamiento de dos CVE del núcleo de PHP, desde un fallo por falta de memoria y un use-after-free hasta el heap grooming, las fugas de ASLR y la ejecución remota de código.

Comencé a escribir esta investigación el 26 de octubre de 2026, y no estoy del todo seguro de cuándo la terminaré.
En el momento de escribir esto, todavía hay muy poca información disponible sobre PHP2Shell, particularmente cuando se trata de análisis técnicos detallados de las vulnerabilidades y del proceso de explotación.
Honestamente, me estaba cansando de encontrar explicaciones que solo arañaban la superficie sin mostrar realmente lo que ocurría internamente. Quería hacer algo diferente: un recorrido técnico adecuado y en profundidad que explore todo el proceso, examinando cada detalle importante y explicando no solo QUÉ ocurre, sino POR QUÉ y CÓMO ocurre.
Esta investigación se basa en mi propia comprensión del código fuente de PHP, mis experimentos y las investigaciones que he realizado mientras intentaba entender estas vulnerabilidades. Quería reunir todas estas piezas, compartir mis hallazgos y, con suerte, hacer que algunos de los conceptos subyacentes sean más fáciles de entender para los demás.
Uno de mis principales objetivos era hacer esto accesible sin sacrificar la profundidad técnica. Quiero que alguien con conocimientos básicos de C y experiencia general en programación pueda seguir el hilo, incluso sin ninguna experiencia previa en explotación de memoria de bajo nivel.
También espero que esta investigación pueda ayudar a aclarar algunas de las cosas que actualmente están mal explicadas o mal entendidas. Sin embargo, quiero ser transparente: esta es mi propia comprensión técnica de las vulnerabilidades, no un análisis oficial ni una referencia infalible. Sigo aprendiendo, investigando y conectando los puntos por mí mismo. Puede haber errores, imprecisiones o cosas que he malinterpretado en el camino.
Si notas algo incorrecto, tienes una interpretación diferente o crees que algo merece una mayor investigación, por favor no dudes en contactarme. Agradecería genuinamente correcciones, debates y contribuciones que puedan ayudar a hacer esta investigación más precisa y útil para todos.
Después de todo, el objetivo de compartir esto es aprender juntos y ayudar a más personas a entender lo que realmente ocurre bajo el capó.
¿Ya estás familiarizado con lo básico? Salta directamente a la parte que te interesa:
Si eres nuevo en la explotación del heap o quieres la experiencia completa, simplemente sigue desplazándote. Escribí esto para que se lea de principio a fin.
Hay algunas cosas que todos deberíamos tener en cuenta antes de sumergirnos. Serán particularmente útiles a medida que avancemos en la investigación. Como mencioné antes, quiero que este recorrido sea accesible para todos, así que me tomaré el tiempo de explicar incluso los conceptos más fundamentales. Si ya estás familiarizado con ellos, ¡siéntete libre de saltar hacia adelante!
En un programa típico, la memoria se organiza en diferentes regiones, incluyendo el stack y el heap.
Por ejemplo, en C++:
int main() {
int a = 30; // Typically stored on the stack
int* b = new int(30); // b is typically on the stack,
// but the integer it points to is on the heap
}
Aquí, a es una variable local que contiene el valor 30. El puntero b también es una variable local, pero contiene la dirección de un entero asignado en el heap.
PHP está escrito principalmente en C, por lo que tenemos que entender cómo funciona la asignación de memoria.
El sistema operativo proporciona a un proceso su propio espacio de direcciones virtuales. El asignador de memoria del proceso gestiona entonces las asignaciones dentro de la memoria disponible para él.
Por ejemplo, en C++, tenemos new, malloc() y otras formas de asignar memoria.
Los asignadores a menudo intentan reutilizar la memoria liberada en lugar de solicitar nueva memoria al sistema operativo cada vez.
Además, cuando finaliza el tiempo de vida de un objeto, los datos que se almacenaban en su memoria no necesariamente se borran de inmediato. Esa memoria simplemente puede marcarse como disponible para su reutilización.