lunes, 31 de mayo de 2010

Seguridad PHP y MySQL: la inyección SQL

Observa este código script escrito en PHP.

Su función es mostrar un formulario y pedir un dato, llamarse a sí mismo, comprobar si la variable está definida, en cuyo caso es que hemos rellenado el formulario y enviado a servidor; si es así, construimos una orden SQL, la ejecutamos, recibimos los datos y los procesamos.

Hasta aquí, nada fuera de lo normal.

<html>
<head>
<title>Ataque por SQL Injection</title>
</head>
<body>
<?
 if (isset($_REQUEST['id'])) {
  $sql = "SELECT * FROM mitabla WHERE id = " . $_REQUEST['id'];
  // ... ejecutar SQL
  // ... recuperar resultado
  // ... hacer más cosas
 }
 else {
  ?>
  <form method="POST" action="miprograma.php">
  <p>ID a consultar: <input type="text" name="id"></p>
  <p><input type="submit" value="Enviar"></p>
  </form>
  <?
 }
?>
</body>

Este pequeño script puede usarse de dos maneras, rellenando el formulario y pulsando el botón Enviar o bien con una llamada directa a la URL "miprograma.php?id=1", por ejemplo.

Pero qué pasa si bien en el formulario, o en la llamada directa vía URL pasamos algo así como "1; DELETE FROM mitabla;".

Claro, el atacante tiene que saber el nombre de la tabla, que podría averiguarlo si provoca un error y el programa está hecho para que devuelva el mensaje generado por mysql_error() vía un echo. Puede ser, es habitual que se dejen ese tipo de mensajes en los desarrollos.

Este tipo de ataques se denomina SQL injection y forma parte del ABC básico de los atacantes novatos. Como ahora mismo estoy con este asunto, recomiendo la lectura de estos artículos, aunque casi todos giran entorno a las mismas recomendaciones básicas:


(Imagen superior de ivlabs.org, encontrada en atp.com.ar.)

4 comentarios:

Suso dijo...

No veas, Ángel!!

Al llegar a la línea donde ponías "Hasta aquí, nada fuera de lo normal", ya no me estaba enterando de casi nada!!!!

Menos mal que no me tengo que ganar la vida escribiendo códigos!!

Un saludo

Angel Cabrera dijo...

Hola Suso,

:)

Ya sabes, este blog es un poco de todo lo que me pasa. Como decía un twittero, a quien el piropo, yo y mis circunstancias.

;)

dayer dijo...

Lo malo de mysql_real_escape_string es que tienes que tener una conexión abierta a la BBDD y puede no ser interesante por tema de recursos si la comprobación no se hace en el mismo script que tiene previsto conectarse y hacer la consulta.
Por cierto, aunque no sea tema de inyección, yo también usaría la función esta que quita las etiquetas HTML, que imagina que un chulito se registra con «<\h1>pepito<\/h1>» jajajaja. Pero eso ya son manías.

Un saludo ¡y gracias por los consejos! :)

Angel Cabrera dijo...

hola dayer,

¿manías? no creas. en los artículos que leí aconsejan hacer también ese filtrado de etiquetas HTML

:)