Estoy tratando de realizar una pequeña aplicación para subir Imágenes(Que ya encontré el código parcialmente en Internet) pero me dado cuenta que es vulnerable a injtecciónes de SQL.
Estructura de la tabla
#
# Estructura de tabla para la tabla `archivos`
#
¡
Código MySQL :
CREATE TABLE archivos ( id int(10) unsigned NOT NULL auto_increment, archivo_binario blob NOT NULL, archivo_nombre varchar(255) NOT NULL default '', archivo_peso varchar(15) NOT NULL default '', archivo_tipo varchar(25) NOT NULL default '', PRIMARY KEY (id) ) TYPE=MyISAM;
Formulario.php:
Código HTML :
?php if (isset($_GET['proceso'])){ echo $_GET['proceso']."<br>"; } ?> <FORM enctype="multipart/form-data" method="post" action="insertar.php"> <p><b>Titulo:</b><br /> </p> <input name="titulo" type="text" size="40" class="text" id="titulo" /> </p> <p> <b>Subtitulo:</b><br /> </p> <textarea name="subtitulo" id="subtitulo" cols="60" rows="5" tabindex="4"></textarea> </p> <p><b> Detalles:</b><br /> </p> <textarea name="detalle" id="detalle" cols="60" rows="10" tabindex="4"></textarea> </p> <p> </p> </p> <p> <b>Categoria:</b><br> </p> <select name="categoria" id="categoria"> <option>Promocion</option> <option>Eventos</option> </select> </p> <b>Archivo: </b><br> </p> <INPUT type="file" size="8" name="archivo" size="30"><br> </p> <div style="margin-left:220px; margin-top:20px" ><INPUT type="submit" class="button small blue" name="submit" value="Subir archivo"></div> </FORM> </BODY> </HTML> <? } }else{ header("Location: index.php"); } ?>
insertar.php
Código PHP :
<?php //Primero, arranca el bloque PHP y checkea si el archivo tiene nombre. Si no fue asi, te remite de nuevo al formulario de inserción: // No se comprueba aqui si se ha subido correctamente. if (empty($_FILES['archivo']['name'])){ header("location: formulario.php?proceso=falta_indicar_fichero"); //o como se llame el formulario .. exit; } $conexion= mysql_connect("******","********","**********") or die ("no se ha podido conectar a la BD"); mysql_select_db("*********") or die ("no se ha podido seleccionar la BD"); function quitar($mensaje) { $nopermitidos = array("'",'\\','<','>',"\""); $mensaje = str_replace($nopermitidos, "", $mensaje); return $mensaje; } $binario_nombre_temporal=$_FILES['archivo']['tmp_name'] ; $binario_contenido = addslashes(fread(fopen($binario_nombre_temporal, "rb"), filesize($binario_nombre_temporal))); $binario_nombre=$_FILES['archivo']['name']; $binario_peso=$_FILES['archivo']['size']; $binario_tipo=$_FILES['archivo']['type']; $categoria = $_POST["categoria"]; $titulo = (ucfirst($_POST["titulo"])); $subtitulo = $_POST["subtitulo"]; $detalle = (nl2br(htmlspecialchars(urldecode($_POST["detalle"])))); //insertamos los datos en la BD. $consulta_insertar = "INSERT INTO archivos (id, archivo_binario, archivo_nombre, archivo_peso, archivo_tipo, categoria, titulo, subtitulo, detalle) VALUES ('', '$binario_contenido', '$binario_nombre', '$binario_peso', '$binario_tipo', '$categoria','$titulo', '$subtitulo','$detalle')"; mysql_query($consulta_insertar,$conexion) or die("No se pudo insertar los datos en la base de datos."); header("location: perfil.php"); // si ha ido todo bien exit; ?>
listar_imagenes.php
Código PHP :
<?php $conexion= mysql_connect("******","********","**********") or die ("no se ha podido conectar a la BD"); mysql_select_db("*********") or die ("no se ha podido seleccionar la BD"); $sql = sprintf("SELECT id,archivo_nombre,archivo_tipo,archivo_peso,titulo,subtitulo,detalle FROM archivos", addcslashes(mysql_real_escape_string($archivosl),'%_')); $consulta = mysql_query($sql) or die ("No se pudo ejecutar la consulta"); While ($registro=mysql_fetch_assoc($consulta)){ echo "<a href=ver.php?id=$registro[id]>"; echo $registro['titulo']; echo "</a><p></p>"; echo $registro['subtitulo']; echo "<p></p>"; echo "<img src=\"ver.php?id=".$registro['id']."\">"; echo "<p></p>"; echo $registro['detalle']; echo "<p></p>"; echo "<p></p>"; echo '<hr style="width:80%">'; echo "<p></p>"; echo "<p></p>"; } ?>
ver.php
Código PHP :
<?php function limpiar($contenido) { $contenido = strip_tags($contenido); $contenido = mysql_real_escape_string($contenido); return $contenido; } if(isset($_GET['id'])) { $conexion= mysql_connect("******","********","**********") or die ("no se ha podido conectar a la BD"); mysql_select_db("*********") or die ("no se ha podido seleccionar la BD"); include("proteccion.php") ; function limpiarcampo($dirty){ if (get_magic_quotes_gpc()) { $liberate = mysql_real_escape_string(stripslashes($dirty)); }else{ $liberate = mysql_real_escape_string($dirty); } return $liberate; } $sql = sprintf("SELECT archivo_nombre,archivo_binario,archivo_tipo,archivo_peso,titulo,subtitulo,detalle FROM archivos WHERE id='".mysql_real_escape_string($_GET['id'])."'", $id = addcslashes(mysql_real_escape_string($id),'%_')); $consulta = mysql_query($sql,$conexion); $datos = mysql_result($consulta,0,"archivo_binario"); $tipo = mysql_result($consulta,0,"archivo_tipo"); $nombre = mysql_result($consulta,0,"archivo_nombre"); $peso = mysql_result($consulta,0,"archivo_peso"); header("Content-type: $tipo"); header("Content-length: $peso"); header("Content-Disposition: inline; filename=$nombre"); echo $datos; } ?>
Detalles.php
Código PHP :
<?php $conexion= mysql_connect("******","********","**********") or die ("no se ha podido conectar a la BD"); mysql_select_db("*********") or die ("no se ha podido seleccionar la BD"); $id = (isset($_GET["id"])) ? $_GET["id"] : exit(); include("proteccion.php") ; function strip_all($string) { return addslashes(stripslashes(strip_tags(htmlentities($string)))); } $sql = sprintf("SELECT * FROM archivos WHERE id='$id' ORDER BY id DESC", $id = addcslashes(mysql_real_escape_string($id),'%_')); $consulta = mysql_query($sql) or die ("No se pudo ejecutar la consulta"); While ($registro=mysql_fetch_assoc($consulta)){ echo "<p></p>"; echo "<p></p>"; echo "<h2>"; echo $registro['titulo']; echo "</h2>"; echo "<p></p>"; echo $registro['subtitulo']; echo "<p></p>"; echo "<img align='center' width='300' height='300' src=\"ver.php?id=".$registro['id']."\">"; echo "<p></p>"; echo $registro['detalle']; echo "<p></p>"; echo "<p></p>"; echo "<p></p>"; echo '<b>Publicado:</b> '; echo $registro['fecha']; echo "<p></p>"; ?> <a href="javascript:history.back(1)">Volver Atrás</a> <?php echo "<p></p>"; echo "<p></p>"; echo "<p></p>"; }
Pero haciendo pruebas... me dado cuenta...que hay un fallo en el identificador ID=... y se puede entrar hasta el salón!
Pensé que mediante addcslashes(mysql_real_escape_string( iba a solucionarlo... pero veo que no lo debido emplear correctamente.
Código :
[20:26:00] [INFO] testing 'MySQL UNION query (NULL) - 1 to 10 columns' [20:26:34] [INFO] ORDER BY technique seems to be usable. This should reduce the time needed to find the right number of query columns. Automatically extending the range for current UNION query injection technique test [20:26:35] [INFO] target url appears to have 7 columns in query [20:26:36] [INFO] GET parameter 'id' is 'MySQL UNION query (NULL) - 1 to 10 columns' injectable GET parameter 'id' is vulnerable. Do you want to keep testing the others (if any)? [y/N] y sqlmap identified the following injection points with a total of 125 HTTP(s) requests: --- [b]Place: GET Parameter: id Type: UNION query Title: MySQL UNION query (NULL) - 7 columns Payload: id=19%' LIMIT 1,1 UNION ALL SELECT CONCAT(0x3a6a73693a,0x43497141784f7373616b,0x3a7174683a), NULL, NULL, NULL, NULL, NULL, NULL#[/b]
¿Alguien me puede ayudar? Gracias por adelantado.
Un saludo.