¿Cómo descubrir vulnerabilidades de un servidor con un script tipo "fuzzer"?
No publicar fuera
[break= 1.-Introducción]
1.-Introducción
Los "Fuzzers" son herramientas que nos permiten auditar código y probar vulnerabilidades generales en sistemas informáticos.
Escribiremos varias funciones para un script PHPque nos poermitirá obtener los parámetros GET de cierta dirección (URL) para disparar códigos de error y asÃ# poder descubrir vulnerabilidades potenciales.
Es entonces cuando exploraremos las posibilidades de ampliar la funcionalidad para hacernos un más amplio instrumento de revisión de vulnerabilidades del servidor.
Código:
// malicious web requests
$vulnchars[0] = array("%00","%2527%252esasdf","%u0000", "%u5c00%u2700","/","../","./..././","/%2e/", "%2e","%5C","%s", "'","'''''","\"", "%%%%%%","!!!!!!!!!!!!!!!!!!","#", "%5C27","%%5C%56" , "\'", "\\",';',";a", "|", "\?>", "%a0");
// malicious sql requests
$vulnchars[1] = array(" OR 1=1", "' OR '!'='!");
// malicious xss requests
$vulnchars[2] = array("javascript:alert(String.fromCharCode(65,66,67))", "<script>alert('cookies, yo: ' + document.cookie);</script>");
[break= 2.-Funcionamiento]
2.-Funcionamiento
EL fuzzer en cuestión trabaja tomando una URL y manipulando cada variable GET para hacer todas las posibles combinaciones de solicitudes con un array de caracteres maliciosos diseñados especÃ#ficamente para generar errores.
Consideremos los siguientes arrays, éstos contienen una amplia selección de solicitudes comunes que a menudo generan errores y que podrÃ#an abrir scripts asÃ# como agujeros de seguridad.
Entonces harÃ#amos todas las posibles combinaciones de solicitudes al servidor para analizar su salida. Una vez obtenida la salida, asignamos para los códigos de salida (de error) un conjunto de URL marcadas, para más tarde ser revisadas para auditar el servidor en sÃ#. Pondremos lso arrays que contienen una lista de errores comunes como lo son para: php, web y xss.
Código:
$flags[0] = array("<b>warning</b>:", "warning:", "<b>fatal error</b>", "failed to open stream:", "internal server error", "there was an error when processing this directive.", "http/1.1 400", "http/1.1 403", "http/1.1 500", "gateway error", "command not found", "file not found");
$flags[1] = array("[obdc", "mysql error", "you have an error in your sql syntax", "odbc drivers error", "[microsoft sql", );
$flags[2] = array("javascript:alert(string.fromcharcode(65,66,67))", "<script>alert('cookies, yo: ' + document.cookie);</script>");
Ahora que sabemos para qué tipo de solicitudes podemos obtener salidas de error, entonces podremos escribir código PHP que consultará al servidor HTTP cada una de nuestras solicitudes. En este ejemplo, tan sólo haremos solicitudes del tipo GET, pero podrÃ#a ser modificado para otro tipo del estilo.
Código:
function MakeRequest($url, $method="GET") {
$url = str_replace(" ", "%20", $url);
if ($method=="GET") {
$host = substr($url, strpos($url, "://") + 3);$host=substr($host, 0,strpos($host, "/"));
$request = substr($url, strpos($host, "/"));
$fp = @fsockopen($host, 80, $errno, $errstr, 10);
if (!$fp) {
echo " ERROR . $url $errstr ($errno)$newline";
} else {
$out = "GET $request HTTP/1.1\r\n";
$out .= "Host: $host\r\n";
$out .= "Connection: Close\r\n\r\n";
fwrite($fp, $out);
while (!feof($fp)) {
$buf.= fgets($fp);
}
fclose($fp);
}
}
return $buf;
}
Ahora podemos tomar los resultados del servidor HTTP para las solucitudes maliciosas en cuestión, necesitamos ejecutarlo en una función para asÃ# poder escanear los códigos de error listados anteriormente. La siguiente función devuelve true si "$result" obtiene algún resultado del array "$flags".
Código:
function TestResult ($result) {
global $flags;
$result = strtolower($result);
for ($i=0;$i < count($flags);$i++) {
for ($o=0;$o < count($flags);$o++) {
if (!(strpos($result, $flags[$i][$o]) === false)) {
return 1;
}
}
}
return 0;
}
[break= 3.-El script PHP completo]
3.-El script PHP completo
Ahora que tenemos todas las piezas que necesitamos, es el momento de escribir código para tenerlo todo junto. El siguiente código usa el array "$lists" para contener todas las URLs a probar. En primer lugar analiza la URL para cada uno de los parámetros GET, y empieza a iterar probando con todas las posibles combinaciones de URL. Pasa por cada variable GET e intenta con cada uno de los caracteres malicioso mientras está usando el valor por defecto de todos los demás parámetros GET. EL número total de solicitudas podrÃ#a ser alrededor de (N elevado a N) para cada URL que se encuentra en $list donde N es el número de parámetros GET para cada URL. Es estonces cuando "MakesRequest" ("hace_solicitud") para cada una de las URL y manda los resultados a "TestResult" ("resultado_del_test"), anunciando (si se diera el caso) para cada resultado con el código de error de "$flag".
Código:
for ($inc=0;$inc<count($list);$inc++) {
if ($localonly == true AND (substr($list[$inc], 0, 17) != "http://localhost/" AND substr($list[$inc], 0, 17) != "http://127.0.0.1/")) die("This script can only be tested against localhost.");
// SetUpParameters parses and stores each GET paramater from a URL into the array $get and $getvalues
$url = SetUpParameters($list[$inc]);
if (trim($url) != "") {
echo "$newline$url$newline";
// go through each kind of vulnerability we are testing
for ($vulni=0;$vulni<count($vulnchars);$vulni++) {
switch ($vulni) {
case 0: echo " * General web vulnerabilities$newline"; break;
case 1: echo " * SQL vulnerabilities$newline"; break;
case 2: echo " * XSS vulnerabilities$newline"; break;
}
// go through each GET parameter in the URL
for ($o=0;$o < count($get);$o++) {
for ($i=0;$i<count($vulnchars[$vulni]);$i++) {
// generate url from list of vulnerable characters
$whichparam = $get[$o];
$testing = $url . "?";
// put together the default values for all the other parameters in the script
for ($z=0;$z<count($get);$z++) {
if ($get[$z] != $whichparam) $testing.="&".$get[$z]."=".$getvalue[$z];
}
$testing .= "&" . $whichparam . "=" . $vulnchars[$vulni][$i];
$fun = MakeRequest($testing);
if ($parseforlinks == true) ParseForLinks($fun);
$error = TestResult($fun);
if ($error != 0)
echo " FLAG! .. $testing$newline";
if ($error == 0 and $verbose == true)
echo " OK .. $testing $newline";
}
}
}
}
}
-------------------------------------------------------------------------------------------------
Traducido a sangre por Pesst, para webhostingforo.com :o