¿Cómo es vulnerable mi sitio web para las inyecciones de SQL?

4

Estoy ejecutando un pequeño sitio web donde he publicado algunos artículos. También estoy muy interesado en temas de seguridad y probé sqlmap en mi sitio web. Encontró el nombre de la base de datos, así que mi pregunta es cómo podría encontrarlo.

El sitio web es muy básico y solo contiene una cantidad muy pequeña de archivos php y acabo de probar el archivo index.php:
sqlmap.py -u http://myurl.com/index.php?id=5 --dbs
En el index.php he usado las funciones php mysql_real_escape_string y stripslashes para limpiar la cadena antes de usarla en la pregunta de SQL y si el visitante intenta meterse con el id en la URL, entonces solo recargo index.php:

$id = $_GET['id'];
if (get_magic_quotes_gpc()) {
    $id = stripslashes($id);
}
$id = mysql_real_escape_string($id);

$sql = "SELECT * , COUNT( * ) AS amount
            FROM articles
            WHERE id = $id
            GROUP BY id";
$result = mysql_query($sql) or die(header("Location: index.php"));

Entonces, ¿cómo podría sqlmap.py obtener el nombre de la base de datos de la información anterior?

¿Podría explicar cómo es posible y también dar un ejemplo?

    
pregunta Rox 26.01.2012 - 20:16
fuente

4 respuestas

9

Siempre use consultas parametrizadas, la concatenación de cadenas deja espacio para el error, deje de salir de esa habitación (también se ven mucho mejor).

Además, como id es un int, no necesito comillas para inyectar:

$id = '0; Drop Table myTable;--';

$sql = "SELECT * , COUNT( * ) AS amount
        FROM articles
        WHERE id = 0; Drop Table myTable;--
        GROUP BY id";

Me gusta usar is_numeric para verificar si es un número y eliminarlos no es.

Editar:

PDO proporciona preparación de consultas SQL: enlace

Entonces, por ejemplo:

$sql = "SELECT * , COUNT( * ) AS amount
    FROM articles
    WHERE id = :id
    GROUP BY id";
$sth = $dbh->prepare($sql);
$sth->execute(array(':id' => $id));
    
respondido por el StrangeWill 26.01.2012 - 21:14
fuente
3

En primer lugar, está tomando los pasos correctos, no solo asumiendo que su código es seguro, sino en realidad probándolo.

En segundo lugar, Sqlmap le dará algunos niveles de detalles sobre cómo llegó exactamente a un punto SQLi. Pruebe alguno de los siguientes cuando lo ejecute:

El interruptor -v 3 hará que se imprima la carga útil exacta inyectada. También debería poder ver esto en los registros de acceso y error de su servidor web.

En tercer lugar, mirando el fragmento de código: es posible que desee probar:

  • (int) $ _ GET ['id']

Pero si puede darnos más detalles sobre lo que sqlmap dice que es el punto de inyección es, como cronometrado, ciego, de unión, booleano, etc., podríamos entrar en más detalles.

    
respondido por el neil 26.01.2012 - 20:51
fuente
2

Todas las respuestas están bien, pero en su caso particular, escapó del número como una cadena ( mysql_real_escape_string() ), pero no la incluyó entre comillas simples como una cadena.

Si, en lugar de:

$sql = "SELECT * , COUNT( * ) AS amount
        FROM articles
        WHERE id = $id
        GROUP BY id";

usaste:

$sql = "SELECT * , COUNT( * ) AS amount
        FROM articles
        WHERE id = '$id'
        GROUP BY id";

habría ninguna inyección de SQL un menor riesgo de inyección de SQL. Pero siempre es mejor:

  • usar declaraciones preparadas
  • use la validación de entrada estricta: en su caso, debería estar lanzando id a integer .
respondido por el Krzysztof Kotowicz 26.01.2012 - 22:25
fuente
2

La respuesta corta en esta situación en particular, y porque el $id siempre será un número, es como dijo Neil, para filtrar la entrada para asegurarse de que siempre va a ser un número entero, sin importar qué. / p>

Concepto de ejemplo:

$id = ( false !== ( int )$_GET[ 'id' ] >= 0 ) ?
        ( int )$_GET[ 'id' ] :
        die( header( "Location: ./index.php" ) );

Algo así aseguraría que $id solo pueda ser un número entero y no menos de 0 (es decir, no -1). Lo que haga con una identificación fallida depende de usted, en este ejemplo, la página se redirige al index.php .

En este ejemplo anterior, la siguiente solicitud de

id=55+union+select+1,2,3,4,5,6,7,8,9,10,11,12,13

Resultaría en que $sql es:

SELECT * , COUNT( * ) AS amount FROM articles
WHERE id = 55 GROUP BY id

en lugar de lo que devolvería el código actual, que es:

SELECT * , COUNT( * ) AS amount FROM articles
WHERE id = 55 union select 1,2,3,4,5,6,7,8,9,10,11,12,13 GROUP BY id
    
respondido por el Taipo 29.01.2012 - 10:45
fuente

Lea otras preguntas en las etiquetas