Proyecto F2-Sanitizar el Foro de PHP
-
Upload
javierasir2012 -
Category
Documents
-
view
137 -
download
4
description
Transcript of Proyecto F2-Sanitizar el Foro de PHP
SANITIZANDO FORO
2012
Javier García Cambronel SEGUNDO DE ASIR
18/01/2012
[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
[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.
[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
[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"])) {
[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>
[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>
[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.
[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.
[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.
[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.
[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.
[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
[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());
[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>
[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.
[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.
[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;
[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; ?>
[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>
[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.
[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.
[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"]."'";
[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>
[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"]))
[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));
[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;
}
}
?>
[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.
[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.
[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.
[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
[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.
[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>";
[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']);
[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>";
}
?>
[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>
[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
[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
[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…..
[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.
[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.
[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….