42
SANITIZANDO FORO 2012 Javier García Cambronel SEGUNDO DE ASIR 18/01/2012

Proyecto F2-Sanitizar el Foro de PHP

Embed Size (px)

DESCRIPTION

2012SANITIZANDO FOROJavier García Cambronel SEGUNDO DE ASIR 18/01/2012[SANITIZANDO FORO] 18 de enero de 2012IMPLEMENTANDO SEGURIDAD EN NUESTRO FORO PHPCÓDIGO REGISTRO PHP SANITIZADOEXPLICACIÓN BLOQUE 1 COMPROBACIÓN DE EMAIL EXPLICACION BLOQUE 2 SANITIZANDO CONTRA ATAQUES SQLI, XSS EXPLICACIÓN BLOQUE TRES COMPROBANDO LA SEGURIDAD DE LA CONTRASEÑA EXPLICACIÓN BLOQUE 5 ENCRIPTANDO CONTRASEÑASCÓDIGO INICIO DE SESION PHP SANITIZADOEXPLICACION BLOQUE 1 SANITIZANDO CONTRA ATAQUES SQLI, XS

Citation preview

Page 1: Proyecto F2-Sanitizar el Foro de PHP

SANITIZANDO FORO

2012

Javier García Cambronel SEGUNDO DE ASIR

18/01/2012

Page 2: Proyecto F2-Sanitizar el Foro de PHP

[SANITIZANDO FORO] 18 de enero de 2012

SEGUNDO DE ASIR Página 1

IMPLEMENTANDO SEGURIDAD EN NUESTRO FORO PHP

CÓDIGO REGISTRO PHP SANITIZADO

EXPLICACIÓN BLOQUE 1 COMPROBACIÓN DE EMAIL

EXPLICACION BLOQUE 2 SANITIZANDO CONTRA ATAQUES SQLI, XSS

EXPLICACIÓN BLOQUE TRES COMPROBANDO LA SEGURIDAD DE LA CONTRASEÑA

EXPLICACIÓN BLOQUE 5 ENCRIPTANDO CONTRASEÑAS

CÓDIGO INICIO DE SESION PHP SANITIZADO

EXPLICACION BLOQUE 1 SANITIZANDO CONTRA ATAQUES SQLI, XSS

EXPLICACION BLOQUE 2 LLAMANDO A LAS FUNCIONES DESENCRIPTANDO CONTRASEÑA

CÓDIGO NUEVO TEMA PHP SANITIZADO

EXPLICACION BLOQUE 1 SANITIZANDO CONTRA ATAQUES SQLI, XSS

CÓDIGO SANITIZADO CONTESTAR POST PHP

EXPLICACION BLOQUE 1 SANITIZANDO CONTRA ATAQUES SQLI, XSS

EXPLICACION BLOQUE 2 LIMPIANDO LA URL EVITANDO ATAQUES XSS Y SQL

EXPLICACION BLOQUE 4 LIMITANDO LA SUBIDA DE TIPOS DE FICHERO

CÓDIGO MOSTRAR TEMA PHP SANITIZADO

EXPLICACION BLOQUE 1 LIMPIANDO LA URL EVITANDO ATAQUES XSS Y SQL

HERRAMIENTAS AUTOMÁTICAS DESPUES DE LA SANITIZACIÓN

Page 3: Proyecto F2-Sanitizar el Foro de PHP

[SANITIZANDO FORO] 18 de enero de 2012

SEGUNDO DE ASIR Página 2

IMPLEMENTANDO SEGURIDAD EN NUESTRO FORO PHP

La programación segura de PHP es esencial para no comprometer la seguridad de su servidor

donde este alojada nuestra aplicación web. Una aplicación con mal diseño de seguridad es

vulnerable usualmente

XSS: Cross-site scripting es un tipo de inseguridad informática o agujero de seguridad basado

en la explotación de vulnerabilidades del sistema de validación de HTML incrustado. Esta

falla suele producirse por varias razones : Variables no inicializadas correctamente, Ausencia

de control de datos, entre otras.

SQL-injection: Es una vulnerabilidad informática en el nivel de la validación de las entradas a

la base de datos de una aplicación. El origen es el filtrado incorrecto de las variables

utilizadas en las partes del programa con código SQL. Es, de hecho, un error de una clase más

general de vulnerabilidades que puede ocurrir en cualquier lenguaje de programación o de

script que esté incrustado dentro de otro. Esta falla suele producirse por razones como:

Ausencia de control de datos.

Para tener un código seguro hay que tener en cuenta básicamente 2 cosas:

SANITIZAR Y VALIDAR

Sanitizar y Validar los datos, son los puntos de más importancia a la hora de programar una

aplicación segura, y las que más impacto tienen a la hora de la analizar la seguridad, debido

que estos datos pueden ser manipulados por cualquier usuario, en muchos casos

malintencionados.

¿Que es Sanitizar? Es el proceso de aplicar una limpieza exhaustiva a un dato o grupos de

datos para su uso.

¿Que es Validar? Es el proceso utilizado para validar o comprobar si los datos cumplen con

ciertos requisitos predefinidos.

Ahora teniendo todo esto en cuenta vamos a hacer de nuestro foro una aplicación segura, o

al menos mucho más segura de lo que era antes, para ello hemos modificado el código en

diferentes partes para validación y sanitización de datos como veremos a continuación.

Page 4: Proyecto F2-Sanitizar el Foro de PHP

[SANITIZANDO FORO] 18 de enero de 2012

SEGUNDO DE ASIR Página 3

CÓDIGO REGISTRO PHP SANITIZADO

<?php

function comprobar_email($email){

$mail_correcto = 0;

//compruebo unas cosas primeras

if ((strlen($email) >= 6) && (substr_count($email,"@") == 1) && (substr($email,0,1) !=

"@") && (substr($email,strlen($email)-1,1) != "@")){

if ((!strstr($email,"'")) && (!strstr($email,"\"")) && (!strstr($email,"\\")) &&

(!strstr($email,"\$")) && (!strstr($email," "))) {

//miro si tiene caracter .

if (substr_count($email,".")>= 1){

//obtengo la terminacion del dominio

$term_dom = substr(strrchr ($email, '.'),1);

//compruebo que la terminación del dominio sea correcta

if (strlen($term_dom)>1 && strlen($term_dom)<5 && (!strstr($term_dom,"@")) ){

//compruebo que lo de antes del dominio sea correcto

$antes_dom = substr($email,0,strlen($email) - strlen($term_dom) - 1);

$caracter_ult = substr($antes_dom,strlen($antes_dom)-1,1);

if ($caracter_ult != "@" && $caracter_ult != "."){

$mail_correcto = 1;

}

}

}

}

}

if ($mail_correcto)

return $email;

else

Page 5: Proyecto F2-Sanitizar el Foro de PHP

[SANITIZANDO FORO] 18 de enero de 2012

SEGUNDO DE ASIR Página 4

return 0;

}

function seguridad($variable) {

$variable = strip_tags(stripslashes(mysql_real_escape_string(trim($variable))));

return $variable;

}

function contraseña($clave){

if(strlen($clave) < 8){

return false;

}

if(strlen($clave) > 16){

return false;

}

if (!preg_match('`[a-z]`',$clave)){

return false;

}

if (!preg_match('`[A-Z]`',$clave)){

return false;

}

if (!preg_match('`[0-9]`',$clave)){

return false;

}

return $clave;

}

$_POST["email"]=comprobar_email(seguridad($_POST["email"]));

$_POST["password"]=contraseña(seguridad($_POST["password"]));

if ((!$_POST["email"]) || (!$_POST["password"])) {

Page 6: Proyecto F2-Sanitizar el Foro de PHP

[SANITIZANDO FORO] 18 de enero de 2012

SEGUNDO DE ASIR Página 5

header("Location: nuevo_usuario.html");

exit;

}

if ($_POST["password"] !=($_POST["password2"]) {

header("Location: nuevo_usuario.html");

exit;

}

$mysqli = mysqli_connect("localhost", "root", "", "foro");

$nuevo_usuario_sql = "SELECT email FROM usuarios

WHERE email='".$_POST["email"]."'";

$nuevo_usuario_res = mysqli_query($mysqli, $nuevo_usuario_sql)

or die(mysqli_error($mysqli));

if (mysqli_num_rows($nuevo_usuario_res) < 1) {

$nuevo_usuario_2_sql="INSERT INTO usuarios (email,password)

VALUES('".$_POST["email"]."','".md5($_POST["password"])."')";

$nuevo_usuario_2_res=mysqli_query($mysqli,

$nuevo_usuario_2_sql) or die(mysqli_error($mysqli));

$display_block = "<p><em>Registro completado con exito</em></p>";

} else {

$display_block = "<p><em>Ese e-mail ya esta existe</em></p>";

}

mysqli_close($mysqli);

?>

<html>

<head>

<title>Nuevo usuario</title>

Page 7: Proyecto F2-Sanitizar el Foro de PHP

[SANITIZANDO FORO] 18 de enero de 2012

SEGUNDO DE ASIR Página 6

</head>

<body>

<h1>Nuevo usuario</h1>

<?php echo $display_block; ?>

<p>Volver a la pagina principal. <a href="foro.html">Pulsa aqui</a>

</body>

</html>

Page 8: Proyecto F2-Sanitizar el Foro de PHP

[SANITIZANDO FORO] 18 de enero de 2012

SEGUNDO DE ASIR Página 7

EXPLICACIÓN BLOQUE 1 COMPROBACIÓN DE EMAIL

Vamos a ver una función muy útil en PHP que sirve para comprobar la validez de un correo.

En realidad comprueba si una dirección de correo electrónico está bien escrita

sintácticamente, dejando de lado las comprobaciones de si ese mail existe o no realmente,

que no se pueden hacer tan fácilmente.

La función en si da por hecho inicialmente que el email es erróneo y realiza una serie de

comprobaciones que, si todas responden correctamente, dan por conclusión que el email sí

estaba bien escrito. Si alguna de esas comprobaciones no era correcta, no se llegaría al final

de las comprobaciones y quedaría el resultado como se ha supuesto en un principio, es decir,

como incorrecto.

Las comprobaciones

En el primer if compruebo que el email tiene por lo menos 6 caracteres (el mínimo), que

tiene una arroba y sólo una y que no está colocada ni al principio ni al final.

En el segundo if comprueba que no tiene algunos caracteres no permitidos. Y los restantes

hacen comprobaciones de las distintas partes de la dirección de correo: Que hay un punto en

algún lado y que la terminación del dominio es correcta y que el principio de la dirección

también es correcto.

Finalmente, se devuelve la variable local utilizada para guardar la validez o incorrección del

correo.

COMPROBACIÓN

Si insertamos un email que no cumple con todas las opciones que hemos indicado en la

función comprobar e-mail y le damos a validar.

Page 9: Proyecto F2-Sanitizar el Foro de PHP

[SANITIZANDO FORO] 18 de enero de 2012

SEGUNDO DE ASIR Página 8

Vemos que nos devuelve a la misma pantalla sin realizar ninguna acción.

ANTES

Sin embargo antes con el mismo ejemplo vemos que quedaría registrado al no tener el email

ningún tipo de validación podríamos escribir lo que quisiésemos que quedaría registrado.

Page 10: Proyecto F2-Sanitizar el Foro de PHP

[SANITIZANDO FORO] 18 de enero de 2012

SEGUNDO DE ASIR Página 9

EXPLICACION BLOQUE 2 SANITIZANDO CONTRA ATAQUES SQLI, XSS

Limpiamos de las entradas los tags HTML, Javascript, style y comentarios.

Ahora podemos sanear cualquier cadena de texto, e incluso arrays. Para usar estas funciones

simplemente hay que llamar a la función seguridad con parámetro la cadena (o array) a

sanear y nos devolverá la cadena (o array) saneado.

COMPROBACIÓN

Como vemos nos devuelve a la pantalla de nuevo, sin realizar ninguna acción

ANTES

Sin embargo sin la protección que le hemos puesto quedaría registrado y el código malicioso

estaría como vemos en nuestra base de datos, listo para ser ejecutado.

Page 11: Proyecto F2-Sanitizar el Foro de PHP

[SANITIZANDO FORO] 18 de enero de 2012

SEGUNDO DE ASIR Página 10

EXPLICACIÓN BLOQUE TRES COMPROBANDO LA SEGURIDAD DE LA CONTRASEÑA

Es una función bien sencilla, ya que simplemente tenemos que comprobar paso por paso

cada una de las características que tendría la clave que deseamos aceptar. En nuestro caso

vamos a comprobar:

Que la clave tiene al menos 8 caracteres

Que el password tiene como máximo 16 caracteres

Que tiene al menos 1 letra minúscula

Que al menos tiene 1 letra mayúscula

Que tiene al menos un carácter numérico

Para hacer la función en realidad necesitaríamos recibir solamente la clave a ser validada y

se devolvería un booleano para decir si es o no válida la contraseña.

COMPROBACIÓN

Como vemos si insertamos una contraseña para nuestro usuario que no cumpla con todos

los requisitos que hemos específicado en la función contraseña nos devuelve a la misma

pantalla.

Page 12: Proyecto F2-Sanitizar el Foro de PHP

[SANITIZANDO FORO] 18 de enero de 2012

SEGUNDO DE ASIR Página 11

ANTES

Sin embargo antes podríamos insertar la contraseña que quisiéramos al no tener ningún tipo

de validación.

Y como vemos Juanito a quedado registrado con una contraseña de tres caracteres.

Page 13: Proyecto F2-Sanitizar el Foro de PHP

[SANITIZANDO FORO] 18 de enero de 2012

SEGUNDO DE ASIR Página 12

EXPLICACIÓN BLOQUE 5 ENCRIPTANDO CONTRASEÑAS

Al que realmente no le podemos llamar ni bloque pues esta formado de una sola line como

vemos y de hecho es una pequeña modificación de lo que ya teníamos en nuestro código sin

sanitizar, lo que hemos añadido ha sido lo que vemos en rojo.

VALUES('".$_POST["email"]."','".md5($_POST["password"])."')";

Esta línea la hemos añadido para que en nuestra base de datos, la contraseña se guarde

encriptada en este formato md5, el cual ya da bastante seguridad y hace que los programas

dedicados a explotar esta vulnerabilidad tarden mucho más en adivinar la contraseña o que

directamente no la puedan desencriptar, si fuera texto plano….realmente seria muy fácil de

ver una contraseña explotando alguna vulnerabilidad, sobretodo SQL.

COMPROBACIÓN

Al introducir un usuario que cumpla todas las validaciones tanto de email como de

contraseña queda registrado.

Pero lo mas importante, vemos como queda registrado y que la contraseña se ha guardado

cifrada en md5 como le hemos indicado.

ANTES

Como vemos antes, las contraseñas se guardaban sin ningún encriptado de ninguna forma

Page 14: Proyecto F2-Sanitizar el Foro de PHP

[SANITIZANDO FORO] 18 de enero de 2012

SEGUNDO DE ASIR Página 13

CÓDIGO INICIO DE SESION PHP SANITIZADO

<?php

function seguridad($variable) {

$variable = strip_tags(stripslashes(mysql_real_escape_string(trim($variable))));

return $variable;

}

if ((!$_POST["email"]) || (!$_POST["password"])) {

header("Location: foro.html");

exit;

}

$mysqli = mysqli_connect("localhost", "root", "", "foro");

$_POST["email"]=seguridad($_POST["email"]);

$_POST["password"]=seguridad(md5($_POST["password"]));

$obtener_usuario_sql = "SELECT email, password

FROM usuarios

WHERE email='".$_POST["email"]."'

AND

password='".$_POST["password"]."'";

$obtener_usuario_res = mysqli_query($mysqli, $obtener_usuario_sql)

or die(mysqli_error($mysqli));

if (mysqli_num_rows($obtener_usuario_res) < 1) {

$display_block = "<p><em>Datos erroneos

Vuelve a probar</em></p>";

} else {

$display_block = "<p>Bienvenido</p>";

session_start();

$id_sesion=seguridad(session_id());

Page 15: Proyecto F2-Sanitizar el Foro de PHP

[SANITIZANDO FORO] 18 de enero de 2012

SEGUNDO DE ASIR Página 14

$nueva_sesion_sql = "INSERT INTO

sesiones VALUES ('".$id_sesion."','".$_POST["email"]."')";

$nueva_sesion_res =

mysqli_query($mysqli, $nueva_sesion_sql)or

die(mysqli_error($mysqli));

}

mysqli_close($mysqli);

?>

<html>

<head>

<title>Inicio de sesion</title>

</head>

<body>

<h1>Inicio de sesion</h1>

<?php echo $display_block; ?>

<a href="listatemas.php?<?php echo session_id(); ?>">Entrar al foro</a></h1>

</body>

</html>

Page 16: Proyecto F2-Sanitizar el Foro de PHP

[SANITIZANDO FORO] 18 de enero de 2012

SEGUNDO DE ASIR Página 15

EXPLICACION BLOQUE 1 SANITIZANDO CONTRA ATAQUES SQLI, XSS

Limpiamos de las entradas los tags HTML, Javascript, style y comentarios.

Ahora podemos sanear cualquier cadena de texto, e incluso arrays. Para usar estas funciones

simplemente hay que llamar a la función seguridad con parámetro la cadena (o array) a

sanear y nos devolverá la cadena (o array) saneado.

COMPROBACIÓN

No se ejecuta el código malicioso, y nos informa de que los datos son eróneos.

ANTES

Nos deja entrar, pues ya estábamos registrados con el script, con lo que cada vez que se lean

los datos de nuestro usuario tendremos un bonito HOLA.

Page 17: Proyecto F2-Sanitizar el Foro de PHP

[SANITIZANDO FORO] 18 de enero de 2012

SEGUNDO DE ASIR Página 16

EXPLICACION BLOQUE 2 LLAMANDO A LAS FUNCIONES DESENCRIPTANDO CONTRASEÑA

En este bloque declaramos las funciones para que tengan efecto sobre los elementos que le

indicamos en este caso email y password y no nos olvidemos de que para que el inicio de

sesión tenga efecto con nuestra contraseña tenemos que hacer que se desencripte y para

ello también lo indicamos aquí, de nuevo con md5.

$_POST["email"]=seguridad($_POST["email"]);

$_POST["password"]=seguridad(md5($_POST["password"]));

COMPROBACIÓN

Como vemos la desencriptación se lleva a cabo de forma correcta y escribiendo nuestra

contraseña de forma normal, accedemos sin ningún problema al foro.

ANTES

No era necesario desencriptar la contraseña pues viajaba sin codificar, con el peligro que eso

conlleva.

Page 18: Proyecto F2-Sanitizar el Foro de PHP

[SANITIZANDO FORO] 18 de enero de 2012

SEGUNDO DE ASIR Página 17

CÓDIGO NUEVO TEMA PHP SANITIZADO

<?php

function seguridad($variable) {

$variable = strip_tags(stripslashes(mysql_real_escape_string(trim($variable))));

return $variable;

}

$_POST["titulo_tema"]=seguridad($_POST["titulo_tema"]);

$_POST["texto_post"]=seguridad($_POST["texto_post"]);

session_start();

//Comprobar campos obligatorios

if ((!$_POST["titulo_tema"]) || (!$_POST["texto_post"])) {

header("Location: nuevo_tema.html");

exit;

}

//conexion a la base de datos

$mysqli = mysqli_connect("localhost", "root", "", "foro");

//obtener email

$obtener_email_sql="SELECT email FROM sesiones WHERE id_sesion='".session_id()."'";

$obtener_email_res = mysqli_query($mysqli, $obtener_email_sql)

or die(mysqli_error($mysqli));

$ret=mysqli_fetch_array($obtener_email_res);

$email=$ret['email'];

if ($email=="") {

//intentar crear un tema un usuario no registrado:

header("Location: listatemas.php");

exit;

Page 19: Proyecto F2-Sanitizar el Foro de PHP

[SANITIZANDO FORO] 18 de enero de 2012

SEGUNDO DE ASIR Página 18

} else{

//insertamos tema en la tabla temas_foro:

$add_topic_sql = "INSERT INTO temas_foro (titulo_tema, fecha_creacion, email) VALUES

('".$_POST["titulo_tema"]."',now(), '".$email."')";

$add_topic_res = mysqli_query($mysqli, $add_topic_sql)

or die(mysqli_error($mysqli));

//obtener id de la ultima consulta

$id_tema = mysqli_insert_id($mysqli);

//creamos el post de creacion

$add_post_sql = "INSERT INTO posts_foro

(id_tema,texto_post,fecha_creacion, email,creacion)

VALUES ('".$id_tema."','".$_POST["texto_post"]."', now(),'".$email."','SI')";

$add_post_res = mysqli_query($mysqli, $add_post_sql)

or die(mysqli_error($mysqli));

}

//cerramos conexion

mysqli_close($mysqli);

//mensaje para el usuario

$display_block = "<P>The <strong>".$_POST["titulo_tema"]."</strong> ha sido

creado.</p>";

?>

<html>

<head>

<title>Tema añadido</title>

</head>

<body>

<h1>Tema añadido</h1>

<?php echo $display_block; ?>

Page 20: Proyecto F2-Sanitizar el Foro de PHP

[SANITIZANDO FORO] 18 de enero de 2012

SEGUNDO DE ASIR Página 19

<p>volver a la lista de temas<a href="listatemas.php">Pulsa aqui</a></p>

</body>

</html>

Page 21: Proyecto F2-Sanitizar el Foro de PHP

[SANITIZANDO FORO] 18 de enero de 2012

SEGUNDO DE ASIR Página 20

EXPLICACION BLOQUE 1 SANITIZANDO CONTRA ATAQUES SQLI, XSS

COMPROBACIÓN

Como vemos, al intentar el ataque las cadenas se limpian de forma correcta, no ejecutando

el script que habíamos insertado.

Page 22: Proyecto F2-Sanitizar el Foro de PHP

[SANITIZANDO FORO] 18 de enero de 2012

SEGUNDO DE ASIR Página 21

ANTES

Como era de imaginar, anteriormente el script se ejecutaba en nuestro navegador cuando

creamos el tema.

Y de nuevo cuando accedemos a la lista de temas

Tema en el cual no podríamos entrar, pues el hipervínculo del título donde tendríamos que

pulsar para entrar no se nos muestra, pese a que el código malicioso como hemos

comprobado si que se encuentra bien metido en nuestra base de datos MYSQL.

Page 23: Proyecto F2-Sanitizar el Foro de PHP

[SANITIZANDO FORO] 18 de enero de 2012

SEGUNDO DE ASIR Página 22

CÓDIGO SANITIZADO CONTESTAR POST PHP

<?php

function seguridad($variable) {

$variable = strip_tags(stripslashes(mysql_real_escape_string(trim($variable))));

return $variable;

}

function url ($entrada)

{

$var1=mysql_real_escape_string($entrada);

$var2=htmlspecialchars($var1);

return $var2;

}

session_start();

//conexión al servidor

$mysqli = mysqli_connect("localhost", "root", "", "foro");

//comprobar si estamos mostrando el formulario o añadiendo el post

if (!$_POST) {

// mostrar el formulario; comprobar requisitos

if (!isset($_GET["id_post"])) {

header("Location: listatemas.php");

exit;

}

$_GET["id_post"]=url($_GET["id_post"]);

//comprobamos tema y post

$verify_sql = "SELECT ft.id_tema, ft.titulo_tema FROM posts_foro

AS fp LEFT JOIN temas_foro AS ft ON fp.id_tema =

ft.id_tema WHERE fp.id_post = '".$_GET["id_post"]."'";

Page 24: Proyecto F2-Sanitizar el Foro de PHP

[SANITIZANDO FORO] 18 de enero de 2012

SEGUNDO DE ASIR Página 23

$verify_res = mysqli_query($mysqli, $verify_sql) or die(mysqli_error($mysqli));

if (mysqli_num_rows($verify_res) < 1) {

//no existe el tema o el post

header("Location: listatemas.php");

exit;

} else {

//obtener id_topic y titulo

while($topic_info = mysqli_fetch_array($verify_res)) {

$id_tema = $topic_info['id_tema'];

$titulo_tema = stripslashes($topic_info['titulo_tema']);

}

echo "

<html>

<head>

<title>Escribe una respuesta en ".$titulo_tema."</title>

</head>

<body>

<h1>Escribe una respuesta en $titulo_tema</h1>

<form method=\"post\" enctype=\"multipart/form-data\"

action=\"".$_SERVER["PHP_SELF"]."\">

<p><strong>Mensaje:</strong><br/>

<textarea name=\"texto_post\" rows=\"8\" cols=\"40\" wrap=\"virtual\"></textarea>

<input type=\"hidden\" name=\"id_tema\" value=\"$id_tema\">

<p><input type=\"hidden\" name=\"MAX_FILE_SIZE\" value=\"512000\" />

<p><b>Fichero a subir:</b>

<input type=\"file\" name=\"file\" /></p>

Page 25: Proyecto F2-Sanitizar el Foro de PHP

[SANITIZANDO FORO] 18 de enero de 2012

SEGUNDO DE ASIR Página 24

<p><input type=\"submit\" name=\"submit\" value=\"Subir y responder\"></p>

</form>

</body>

</html>";

}

//liberamos result

mysqli_free_result($verify_res);

} else if ($_POST) {

//comprobamos requisitos

if ((!$_POST["id_tema"]) || (!$_POST["texto_post"])) {

header("Location: listatemas.php");

exit;

}

//obtener email

$obtener_email_sql="SELECT email FROM sesiones WHERE id_sesion='".session_id()."'";

$obtener_email_res = mysqli_query($mysqli, $obtener_email_sql) or

die(mysqli_error($mysqli));

$ret=mysqli_fetch_array($obtener_email_res);

$email=$ret['email'];

//subir archivos

foreach($_FILES as $file_name => $file_array){

$file_dir = "C:\\xampp\\htdocs\\ejer\\foro\\".$file_array["name"];

$filename=trim($_FILES['file']['name']);

$filename=substr($filename, -20);

$filename=preg_replace("/ /", "", $filename);

if((preg_match("/.zip/", $filename)) || (preg_match("/.ZIP/", $filename)))

if (is_uploaded_file($file_array["tmp_name"]))

Page 26: Proyecto F2-Sanitizar el Foro de PHP

[SANITIZANDO FORO] 18 de enero de 2012

SEGUNDO DE ASIR Página 25

{

move_uploaded_file($file_array["tmp_name"], $file_dir) or die ("No se ha podido copiar");

$_POST["texto_post"]=seguridad($_POST["texto_post"]);

$add_post_sql = "INSERT INTO posts_foro (id_tema,texto_post,

fecha_creacion,email,creacion,

file) VALUES

('".$_POST["id_tema"]."', '".$_POST["texto_post"]."', now(),'".$email."','NO',

'".$file_array["name"]."')";

$add_post_res = mysqli_query($mysqli, $add_post_sql) or die(mysqli_error($mysqli));

//redireccionamos

header("Location: mostrartema.php?id_tema=".$_POST["id_tema"]);

exit;

}

}

//Incluimos el post

if(!$_FILES["file"]["name"]){

if ($email=="") {

//intenta crear un tema un usuario no registrado: le redireccionamos a la lista de temas

header("Location: listatemas.php");

exit;

}

//añadir post sin info del archivo adjunto

$_POST["texto_post"]=seguridad($_POST["texto_post"]);

$add_post_sql = "INSERT INTO posts_foro (id_tema,texto_post,

fecha_creacion,email,creacion)

VALUES

('".$_POST["id_tema"]."', '".$_POST["texto_post"]."', now(),'".$email."','NO')";

$add_post_res = mysqli_query($mysqli, $add_post_sql) or die(mysqli_error($mysqli));

Page 27: Proyecto F2-Sanitizar el Foro de PHP

[SANITIZANDO FORO] 18 de enero de 2012

SEGUNDO DE ASIR Página 26

//cerrar conexión

mysqli_close($mysqli);

//redireccionar usuario al tema

header("Location: mostrartema.php?id_tema=".$_POST["id_tema"]);

exit;

}

}

?>

Page 28: Proyecto F2-Sanitizar el Foro de PHP

[SANITIZANDO FORO] 18 de enero de 2012

SEGUNDO DE ASIR Página 27

EXPLICACION BLOQUE 1 SANITIZANDO CONTRA ATAQUES SQLI, XSS

Limpiamos de las entradas los tags HTML, Javascript, style y comentarios.

Ahora podemos sanear cualquier cadena de texto, e incluso arrays. Para usar estas funciones

simplemente hay que llamar a la función seguridad con parámetro la cadena (o array) a

sanear y nos devolverá la cadena (o array) saneado.

COMPROBACIÓN

Como podemos observar la cadena se devuelve limpia cono o que evitamos la ejecución del

script

ANTES

Antes sin embargo…..Claramente el script se ejecutaría sin ningún inconveniente.

Page 29: Proyecto F2-Sanitizar el Foro de PHP

[SANITIZANDO FORO] 18 de enero de 2012

SEGUNDO DE ASIR Página 28

EXPLICACION BLOQUE 2 LIMPIANDO LA URL EVITANDO ATAQUES XSS Y SQL

Limpiamos de las entradas en nuestra URL de tags HTML, Javascript, style y comentarios.

COMPROBACIÓN

Como podemos ver al intentar un ataque SQL con una comilla simple delante del número de

identificación nos devuelve a la lista de temas.

ANTES

Antes como podemos ver nos saldría un error SQL y seria un parámetro inyectable donde

sacaríamos los datos con BLINDSQL sin ningún problema.

Page 30: Proyecto F2-Sanitizar el Foro de PHP

[SANITIZANDO FORO] 18 de enero de 2012

SEGUNDO DE ASIR Página 29

EXPLICACION BLOQUE 4 LIMITANDO LA SUBIDA DE TIPOS DE FICHERO

Se ha limitado la subida de ficheros a solo archivos comprimidos en formato .zip pues la

mayoría de los antivirus los analizan siempre automáticamente y no al ser ejecutados como

otro tipo de archivos, los cuales infectarían nuestro PC inmediatamente.

COMPROBACIÓN SUBIENDO UN .TXT

Si intentamos subir un tipo de archivo no permitido, el servidor no nos dejara y nos mostrara

una ventana en blanco.

ANTES

Antes sin embargo, al no tener ningún tipo de restricción podíamos subir el archivo sin

ningún problema.

Page 31: Proyecto F2-Sanitizar el Foro de PHP

[SANITIZANDO FORO] 18 de enero de 2012

SEGUNDO DE ASIR Página 30

COMPROBACIÓN SUBIENDO ARCHIVO PERMITIDO .ZIP

Al subir un archivo que sea ZIP y que además no supere los 0,5 MB permitidos se subirá sin

problemas a nuestro servidor.

Y lo encontraríamos en la carpeta que habíamos indicado en nuestro PHP.

ANTES

También se produciría la subida de este fichero perfectamente

Page 32: Proyecto F2-Sanitizar el Foro de PHP

[SANITIZANDO FORO] 18 de enero de 2012

SEGUNDO DE ASIR Página 31

COMPROBACIÓN EXCESO DE TAMAÑO EN ARCHIVO PERMITIDO

Sin embargo, si el archivo es un ZIP pero el tamaño excede de los 0.5 MB permitidos al subir

el archivo, mejor dicho, al intentarlo, nos devuelve a la lista de temas.

Y si nos metemos en el tema correspondiente, vemos como no se ha llevado a cabo la subida

de archivos.

ANTES

Nos mosraba la pantalla en blanco y tampoco nos dejaba subir el archivo, pues esta

característica ya estaba implementada.

Page 33: Proyecto F2-Sanitizar el Foro de PHP

[SANITIZANDO FORO] 18 de enero de 2012

SEGUNDO DE ASIR Página 32

CÓDIGO MOSTRAR TEMA PHP SANITIZADO

<?php

function url ($entrada)

{

$var1=mysql_real_escape_string($entrada);

$var2=htmlspecialchars($var1);

return $var2;

}

//comprobamos requisitos

if (!isset($_GET["id_tema"])) {

header("Location: listatemas.php");

exit;

}

//conexión al servidor

$mysqli = mysqli_connect("localhost", "root", "", "foro");

$_GET["id_post"]=url($_GET["id_post"]);

//comprobamos que existe e tema

$verify_topic_sql = "SELECT titulo_tema FROM temas_foro

WHERE id_tema = '".$_GET["id_tema"]."'";

$verify_topic_res = mysqli_query($mysqli, $verify_topic_sql)

or die(mysqli_error($mysqli));

if (mysqli_num_rows($verify_topic_res) < 1) {

//este tema no existe

$display_block = "<p><em>Has seleccionado un tema

incorrecto.<br/>

Por favor, <a href=\"listatemas.php\">inténtalo otra

vez</a>.</em></p>";

Page 34: Proyecto F2-Sanitizar el Foro de PHP

[SANITIZANDO FORO] 18 de enero de 2012

SEGUNDO DE ASIR Página 33

} else {

//obtener título del tema

while ($topic_info = mysqli_fetch_array($verify_topic_res)) {

$titulo_tema = stripslashes($topic_info['titulo_tema']);

}

//obtener los posts

$get_posts_sql = "SELECT id_post, texto_post, file,

DATE_FORMAT(fecha_creacion, '%b %e %Y at %r') AS fmt_post_create_time, email

FROM posts_foro

WHERE id_tema = '".$_GET["id_tema"]."'

ORDER BY fecha_creacion ASC";

$get_posts_res = mysqli_query($mysqli, $get_posts_sql)

or die(mysqli_error($mysqli));

//creamos cadena para mostrar

$display_block = "

<p>Mostrar posts del tema <strong>".$titulo_tema."</strong>:</p>

<table width=\"100%\" cellpadding=\"3\" cellspacing=\"1\" border=\"1\">

<tr>

<th>AUTOR</th>

<th>POST</th>

<th>FILE</th>

</tr>";

while ($posts_info = mysqli_fetch_array($get_posts_res)) {

$id_post = $posts_info['id_post'];

$texto_post = nl2br(stripslashes($posts_info['texto_post']));

$fecha_creacion = $posts_info['fmt_post_create_time'];

$email = stripslashes($posts_info['email']);

Page 35: Proyecto F2-Sanitizar el Foro de PHP

[SANITIZANDO FORO] 18 de enero de 2012

SEGUNDO DE ASIR Página 34

$file= $posts_info['file'];

//añadimos para mostrar...

$display_block .= "

<tr>

<td width=\"35%\" valign=\"top\">".$email."<br/>

[".$fecha_creacion."]</td>

<td width=\"65%\" valign=\"top\">".$texto_post."<br/><br/>

<a href=\"contestarpost.php?id_post=".$id_post."\">

<strong>RESPONDER AL POST</strong></a>

<a href=\"borrarpost.php?id_post=".$id_post."\">

<strong>BORRAR POST</strong></a>

</td>

<td>

<a href= ".$file.">$file</a>

</td>

</tr>";

}

//liberamos result

mysqli_free_result($get_posts_res);

mysqli_free_result($verify_topic_res);

//cerramos conexión

mysqli_close($mysqli);

//cerramos la tabla

$display_block .= "</table>";

}

?>

Page 36: Proyecto F2-Sanitizar el Foro de PHP

[SANITIZANDO FORO] 18 de enero de 2012

SEGUNDO DE ASIR Página 35

<html>

<head>

<title>Posts del tema</title>

</head>

<body>

<h1>Posts del tema</h1>

<?php echo $display_block; ?>

<p>volver a la lista de temas<a href="listatemas.php?<?php echo session_id();

?>">Pulsa aqui</a></p>

</body>

</html>

Page 37: Proyecto F2-Sanitizar el Foro de PHP

[SANITIZANDO FORO] 18 de enero de 2012

SEGUNDO DE ASIR Página 36

EXPLICACION BLOQUE 1 LIMPIANDO LA URL EVITANDO ATAQUES XSS Y SQL

Limpiamos de las entradas en nuestra URL de tags HTML, Javascript, style y comentarios.

COMPROBACIÓN

Si introducimos una comilla simple, para ver si es vulnerable, nos dice que el tema es

incorrecto porque claramente ese tema no existe, pero no recibimos ningún error SQL con lo

que estaríamos protegidos.

ANTES

Sin embargo antes al no tener sanitizada la entada de datos, se nos mostraría el error SQL

Page 38: Proyecto F2-Sanitizar el Foro de PHP

[SANITIZANDO FORO] 18 de enero de 2012

SEGUNDO DE ASIR Página 37

HERRAMIENTAS AUTOMÁTICAS DESPUES DE LA

SANITIZACIÓN

Después de probar con todas las herramientas a mi mano y no encontrar nada realmente

importante en lo referente a la aplicación

DIRPBUSTER

Con este programa después de configurarlo como vemos en la imagen.

Sacamos estos resultados, todos los archivos que forman parte de la aplicación foro todas las

páginas que la componen y también todos los archivos y páginas de anteriores proyectos es

decir FUZZED PAGES páginas alojadas en el servidor que hemos dado con ella a través de

Foro.html

Page 39: Proyecto F2-Sanitizar el Foro de PHP

[SANITIZANDO FORO] 18 de enero de 2012

SEGUNDO DE ASIR Página 38

NESSUS

Con nessus, después de configurarlo como vemos en la imagen, para que haga un análisis de

una aplicación WEB Pulsamos en Scann para que el análisis de comienzo.

Una vez terminado vemos un resumen y hemos encontrado 4 de gran importancia 16 de

nivel medio y 44 de nivel bajo ¿MUCHAS VERDAD?

Una vez entramos en más detalle nos damos cuenta de que estas alertas, mas que estar

relacionadas con la aplicación FORO están relacionadas con el propio sistema, con nuestra

versión de PHP que no esta actualizada, con los puertos abiertos que como vemos tenemos

bastantes, con los cifrados de seguridad no actualizados…..

Page 40: Proyecto F2-Sanitizar el Foro de PHP

[SANITIZANDO FORO] 18 de enero de 2012

SEGUNDO DE ASIR Página 39

ACCUNETIX

Para mi una de las herramientas más potentes a mi disposición como ha demostrado en

varias ocasiones. Vemos que al analizar la aplicación encontramos estas alertas. Procedemos

a mirar con mas detalle cada una de ellas.

Vemos algo que ya sabíamos con las otras herramientas previamente utilizadas, puertos que

están abiertos y que servicio corre, que terminal services esta corriendo. que SSL está

completamente desactualizado corriendo la 2.0 estando actualmente SSL3.0 y TSL…

Y varias cosas más que podemos apreciar en la imagen y que no hace falta que las describa.

Page 41: Proyecto F2-Sanitizar el Foro de PHP

[SANITIZANDO FORO] 18 de enero de 2012

SEGUNDO DE ASIR Página 40

Y vemos lo que realmente nos interesa en lo referente a la aplicación vemos que nos da un

parámetro inyectable después de todo el trabajo, recordemos que en el anterior trabajo nos

daba seis SQL y unos pocos XSS, al menos XSS no tenemos, pero vamos a comprobar que

este parámetro realmente es inyectable y podemos sacar los datos, o es un falso positivo,

algo que por otra parte las herramientas automáticas dan bastante y es su máximo talón de

Aquiles.

Como vemos intentamos explotar la vulnerabilidad cambiando diferentes opciones de

inyección SQL, Metodos Extracción por unión por condición y lo único que logramos es

distintos tipos de mensajes de error como vemos a continuación.

Page 42: Proyecto F2-Sanitizar el Foro de PHP

[SANITIZANDO FORO] 18 de enero de 2012

SEGUNDO DE ASIR Página 41

SQLIHELPER

Hacemos lo suyo con este programa y solo obtenemos la versión de Apache.

HAVIJ 1.15

Hacemos los suyo con Havij y vemos, que no obtenemos datos de relevancia mas allá de la

versión de apache, la versión SSL, la versión dePHP….