Prevenir código php de inyección SQL
Puede haber muchos tipos diferentes de motivaciones de ataque, pero a primera vista puede parecer que hay más. Esto es muy cierto: si un usuario malintencionado encuentra una manera de ejecutar varias consultas. Discutiremos esto con más detalle más adelante en este artículo.
Si
su secuencia de comandos está ejecutando un comando SELECT, un atacante puede forzar que se muestre cada fila de la tabla inyectando una condición como "1=1" en la cláusula WHERE. , como se muestra a continuación (con la parte inyectada en negrita):
SELECT * FROM vinos WHERE variedad = 'lagrein' OR 1=1;
Como comentamos anteriormente, esto es información útil en sí misma, ya que revela la estructura general de la tabla (lo cual no es posible con registros normales) y puede revelar registros que contienen información confidencial.
Los comandos de actualización pueden suponer una amenaza más directa. Al colocar atributos adicionales en la cláusula SET, un atacante puede modificar cualquier campo en el registro que se está actualizando actualmente, como en el siguiente ejemplo (la parte inyectada se muestra en negrita):
ACTUALIZAR vinos SET tipo=' rojo', 'vintage'='9', 'vintage'='9', 'vintage'='9', 'vintage'='9' y 'vintage'='9' . Esta modificación se puede extender a cada registro agregando una condición verdadera constante como 1=1 en la cláusula WHERE del comando de actualización, como se muestra en el siguiente ejemplo (la parte inyectada se muestra en negrita):
ACTUALIZAR vinos SET tipo='tinto', 'vintage' = '9999' WHERE variedad = 'lagrein'
ACTUALIZAR vinos SET tipo='tinto', 'vintage' = '9999' 'vintage' = '9999 WHERE variedad = 'lagrein' OR 1=1;'
La instrucción más peligrosa puede ser DELETE, lo cual no es difícil de imaginar. La técnica de inyección es la misma que ya hemos visto: modificando la cláusula WHERE para ampliar el rango de filas afectadas, como en el siguiente ejemplo (parte de la inyección en negrita):
BORRAR DE vinos WHERE variedad = 'lagrein' OR 1=1;'
II. Inyección de consultas múltiples
Al permitir que se incluyan múltiples instrucciones destructivas en una sola consulta, la inyección de consultas múltiples exacerbará el potencial que un atacante cause daños potenciales. Cuando se utiliza una base de datos MySQL, un atacante puede lograr esto fácilmente insertando un terminador inesperado en la consulta: una comilla inyectada (simple o doble) marca el final de la variable esperada y luego se usa un punto y coma para terminar la instrucción; Ahora es posible agregar instrucciones de ataque adicionales al final de la instrucción original ahora terminada. La consulta destructiva final podría verse así:
SELECCIONAR * DE vinos WHERE variedad = 'lagrein'
CONCEDER TODO EN *.* A 'BadGuy@' IDENTIFICADO POR 'gotcha '; ;'
Esta inyección crea un nuevo usuario, BadGuy, con permisos de red (todos los permisos en todas las tablas agrega una contraseña "siniestra" a esta simple instrucción SELECT);
Si siguió nuestro consejo del artículo anterior (restringir severamente los privilegios del usuario del proceso), entonces esto no debería funcionar porque el demonio del servidor de red ya no tiene los privilegios GRANT que usted revocó. Pero, en teoría, un ataque de este tipo podría darle a BadGuy la libertad de hacer lo que quiera con su base de datos.
La conclusión no es única en cuanto a si el servidor MySQL manejará consultas tan múltiples. Parte de esto puede deberse a diferentes versiones de MySQL, pero gran parte se debe a la forma en que existen las consultas, y el monitor de MySQL es totalmente capaz de permitir dichas consultas. La popular GUI de MySQL, phpMyAdmin, copia todo el contenido anterior antes de la consulta final, y sólo entonces.
Sin embargo, la mayoría de las consultas múltiples en el contexto de inyección son administradas por la extensión mysql de PHP. Afortunadamente, no se permite ejecutar varias instrucciones en una sola consulta de forma predeterminada; intentar ejecutar dos instrucciones (inyectadas como se muestra arriba) resultará en una falla directa: no se establecerá ningún error y no se generará ningún resultado. En este caso, aunque PHP sólo "excluye" su comportamiento predeterminado, lo protege de la mayoría de los ataques de inyección simples.
La nueva extensión mysqli en PHP5 (ver /mysqli), al igual que mysql, no admite inherentemente múltiples consultas, pero proporciona una función mysqli_multi_query() que le permite implementar múltiples consultas cuando realmente lo necesita.
Sin embargo, la situación es aún peor para SQLite, el motor de base de datos SQL integrable incluido en PHP5 (referencia/sqlite) que ha atraído mucha atención por su facilidad de uso. En algunos casos, SQLite permite este tipo de consultas con múltiples comandos de forma predeterminada porque la base de datos puede optimizar las consultas por lotes, especialmente el procesamiento de declaraciones INSERT por lotes, que es muy eficiente. Sin embargo, si un script utiliza los resultados de la consulta (como usar una única instrucción SELECT para recuperar registros), la función sqlite_query() no permitirá que se ejecuten múltiples consultas. El 6 de mayo de 2005, se descubrió una vulnerabilidad de inyección SQL en el código de inicio de sesión. La vulnerabilidad fue descubierta por James Bercegay de GulfTech Security Research.
La consulta de inicio de sesión tiene este aspecto:
$DB-gt;query("SELECT * FROM ibf_members WHERE id=$mid AND contraseña='$pid'"
p>
p>
Entre ellas, la variable de ID de miembro $mid y la variable de ID de contraseña $pid se obtienen de la función my_cookie() a través de las siguientes dos líneas de código:
$ mid = intval($std-gt. my_getcookie('member_id'));
$pid = $std-gt; my_getcookie('pass_hash'); ) utiliza la siguiente declaración para obtener la cookie de Recuperar las variables solicitadas:
return urldecode($_COOKIE[$ibforums-gt; vars['cookie_id'].$name]);
Tenga en cuenta que el valor devuelto por esta cookie no se procesará en absoluto. $mid se convierte en un número entero antes de usarse en la consulta, mientras que $pid permanece sin cambios. Por lo tanto, es vulnerable a los ataques de inyección que comentamos anteriormente.
Por lo tanto, esta vulnerabilidad se expone modificando la función my_cookie() de la siguiente manera:
if ( ! in_array( $name, array('topicsread', 'forum_read' , 'collapseprefs ') ) )
{)
{
return $this-gt
clean_value(urldecode($_COOKIE [ $ibforums-gt;vars['cookie_id ']. $nombre]));
else
{
return urldecode($_COOKIE[$ibforums - gt;vars['cookie_id '].$name]);
}
Después de esta corrección, se devuelve una de las variables clave "pasó" la función global clean_value(), mientras que otras variables no se verifican.
Ahora que tenemos una descripción general de qué es la inyección SQL, cómo funciona y qué tan vulnerable es, exploremos cómo prevenirla. Afortunadamente, PHP nos proporciona una gran cantidad de recursos, por lo que podemos predecir con confianza que una aplicación bien construida que utilice nuestras técnicas recomendadas esencialmente eliminará la posibilidad de inyección SQL en scripts antes de que la inyección SQL pueda causar algún daño al usuario. datos.
Cuatro: Defina cada valor de la consulta.
Le recomendamos que se asegure de definir cada valor de la consulta. Los valores de cadena son los primeros en verse afectados, así como aquellos para los que generalmente desea utilizar comillas "simples" (en lugar de "dobles"). Por un lado, facilita la escritura de consultas si usa comillas dobles para permitir que PHP reemplace las variables en la cadena, por otro lado, también reduce el esfuerzo de analizar el código PHP más adelante (por supuesto, esto es solo una pequeña parte); situación de cantidad).
A continuación, ilustraremos esto usando la misma consulta no inyectada que al principio:
SELECT * FROM vinos WHERE variedad = 'lagrein'
O Use Declaraciones PHP para expresar:
$query = "SELECT * FROM vinos WHERE variedad = '$variedad'"
Técnicamente, los valores numéricos no requieren comillas. Sin embargo, si no le importa rodear los valores en campos como vinos entre comillas, y si el usuario ingresa un valor nulo en el formulario, verá una consulta como esta:
SELECT * FROM vinos WHERE vintage =
Por supuesto, esta consulta no es sintácticamente inválida, sin embargo, la siguiente consulta no es válida; sin embargo, la siguiente sintaxis es válida:
SELECT * FROM vinos WHERE; vintage = ''
La segunda consulta (probablemente) no devolverá ninguna fruta, pero al menos no devolverá un mensaje de error.
5. Verifique el tipo de valor enviado por el usuario
De la discusión anterior, hemos visto que hasta ahora, la fuente principal de inyección SQL suele ser una entrada de formulario inesperada. Sin embargo, cuando ofrece a los usuarios la oportunidad de enviar valores específicos a través de un formulario, debería poder tener una buena idea de qué tipo de entrada espera, lo que hará que sea relativamente fácil verificar la validez de la información del usuario. aporte. Ya hemos discutido este tipo de verificación en artículos anteriores, por lo que aquí resumiremos brevemente los puntos principales discutidos en ese momento;
6?1 Utilice la función is_int() (o is_integer() o is_long()). 6?1 Utilice la función gettype(). 6?1 Utilice la función intval(). 6?1 Utilice la función settype().
Para comprobar la longitud de la entrada del usuario, puede utilizar la función strlen(). Para comprobar si la hora o fecha requerida es válida, puede utilizar la función strtotime(). Casi garantiza que la entrada del usuario no contenga caracteres de punto y coma (a menos que se pueda incluir legalmente la puntuación). Puede lograr esto fácilmente con la ayuda de la función strpos() de la siguiente manera: if( strpos( $variedad, ';' ) exit ("$variedad es un valor no válido para variedad!");
As Como se mencionó anteriormente, si analiza cuidadosamente las expectativas de entrada del usuario, debería poder detectar muchos de estos problemas fácilmente
Seis: filtre todos los caracteres sospechosos de su consulta
Aunque. Ya hemos discutido el problema de filtrar caracteres peligrosos en artículos anteriores, resaltemos brevemente y resumamos el problema nuevamente: 6?1 No use la directiva magic_quotes_gpc o su "respaldo" - -addlashes() //addslashes(); //addslashes(); //addslashes(). Función addlashes(), que es limitada en el desarrollo de aplicaciones y requiere pasos adicionales: use la función stripslashes() 6?1 Por el contrario, la función mysql_real_escape_string() se usa más comúnmente. , pero también tiene sus propias deficiencias