Entiendo que NUNCA debe confiar en la entrada del usuario desde un formulario, principalmente debido a la posibilidad de inyección SQL.
Sin embargo, ¿esto también se aplica a un formulario en el que la única entrada proviene de un menú desplegable (ver más abajo)?
Estoy guardando el $_POST['size']
en una sesión que luego se usa en todo el sitio para consultar las diversas bases de datos (con una mysqli
consulta de selección) y cualquier inyección de SQL definitivamente las dañaría (posiblemente las eliminaría).
No hay un área para que el usuario ingrese la información para consultar las bases de datos, solo menús desplegables.
<form action="welcome.php" method="post">
<select name="size">
<option value="All">Select Size</option>
<option value="Large">Large</option>
<option value="Medium">Medium</option>
<option value="Small">Small</option>
</select>
<input type="submit">
</form>
php
mysql
mysqli
sql-injection
Andrajos
fuente
fuente
<select>
entrada. De hecho, incluso un usuario ligeramente técnico podría agregar opciones adicionales utilizando la consola del navegador. si mantiene una lista blanca de matriz de valores disponibles y compara la entrada con ella, puede mitigar eso (y debería hacerlo porque evita valores no deseados)Respuestas:
Puede hacer algo tan simple como el siguiente ejemplo para asegurarse de que el tamaño de publicación sea el esperado.
Luego use mysqli_ * si está usando una versión de php> = 5.3.0 que debería ser, para guardar su resultado. Si se usa correctamente, esto ayudará con la inyección de SQL.
fuente
mysqli_real_escape_string
. También escape correctamente los valores al generarlos (por ejemplo, use htmlspecialchars () en un documento HTML).in_array
atrue
para una comparación estricta. No estoy seguro de qué podría salir mal, pero las comparaciones sueltas son bastante extravagantes.Sí, necesitas protegerte contra esto.
Déjame mostrarte por qué, usando la consola de desarrollador de Firefox:
Si no limpia estos datos, su base de datos será destruida. (Puede que esta no sea una declaración SQL totalmente válida, pero espero haber entendido mi punto).
El hecho de que haya limitado las opciones disponibles en su menú desplegable no significa que haya limitado los datos que puedo enviar a su servidor.
Si trató de restringir aún más este comportamiento de uso en su página, mis opciones incluyen deshabilitar ese comportamiento o simplemente escribir una solicitud HTTP personalizada en su servidor que imita el envío de este formulario de todos modos. Hay una herramienta llamada curl que se usa exactamente para eso, y creo que el comando para enviar esta inyección SQL de todos modos se vería así:
(Puede que este no sea un comando curl totalmente válido, pero nuevamente, espero haber entendido mi punto).
Entonces, reiteraré:
NUNCA confíe en la entrada del usuario. SIEMPRE protéjase.
No asuma que cualquier entrada del usuario es segura. Es potencialmente inseguro incluso si llega a través de algún medio que no sea un formulario. Ninguno de ellos es lo suficientemente confiable como para renunciar a protegerse de la inyección SQL.
fuente
curl
. ¡SIEMPRE desinfecte la entrada del lado del servidor !curl
. La gente no entiende que puede enviar una solicitud HTTP desde cualquier lugar a cualquier lugar utilizando cualquier formato y pasando cualquier valor, depende del servidor asegurarse de que la solicitud sea válida antes de procesarla.Como esta pregunta fue etiquetada con inyección SQL, aquí hay una respuesta con respecto a este tipo de ataque en particular:
Como le han dicho en los comentarios, debe usar declaraciones preparadas para cada consulta que involucre datos variables, sin excepciones .
¡Independientemente de cualquier material HTML!
Es esencial comprender que las consultas SQL deben formatearse correctamente independientemente de cualquier factor externo, ya sea entrada HTML o cualquier otra cosa.
Aunque puede usar la lista blanca sugerida en otras respuestas para el propósito de validación de entrada, no debería afectar ninguna acción relacionada con SQL ; deben permanecer igual, sin importar si validó la entrada HTML o no. Significa que aún debe usar declaraciones preparadas al agregar cualquier variable a la consulta.
Aquí puede encontrar una explicación completa, por qué las declaraciones preparadas son imprescindibles y cómo usarlas correctamente y dónde no son aplicables y qué hacer en tal caso: La guía del autoestopista para la protección de inyección SQL
Además, esta pregunta fue etiquetada con mysqli. Sobre todo por accidente, supongo, pero de todos modos, tengo que advertirle que mysqli en bruto no es una sustitución adecuada para las antiguas funciones mysq_ * . Simplemente porque si se usa en el estilo antiguo, no agregará seguridad en absoluto. Si bien su soporte para las declaraciones preparadas es doloroso y problemático, hasta el punto de que el usuario promedio de PHP simplemente no puede intentarlo en absoluto. Por lo tanto, si no hay ORM o algún tipo de biblioteca de abstracción es una opción, entonces PDO es su única opción.
fuente
random
?Si.
Cualquiera puede falsificar cualquier cosa por los valores que realmente se envían:
Entonces, para validar los menús desplegables, puede verificar para asegurarse de que el valor con el que está trabajando estaba en el menú desplegable; algo como esto sería la mejor manera (más sanamente paranoica):
fuente
Una forma de protegerse contra los usuarios que cambian sus menús desplegables usando la consola es usar solo valores enteros en ellos. Luego, puede validar que el valor POST contiene un número entero y usar una matriz para convertirlo en texto cuando sea necesario. P.ej:
Luego, puede usarlo
$size
en su consulta sabiendo que solo contendráFALSE
un número entero.fuente
filter_input
si no es un cheque en el lado del servidor? Nadie puede publicar nada excepto un número entero.filter_input
parte también para la validación, de lo contrario, es tan útil como una tetera de chocolate por seguridad.Las otras respuestas ya cubren lo que necesita saber. Pero quizás ayude aclarar un poco más:
Hay DOS COSAS que debe hacer:
1. Valide los datos del formulario.
Como muestra muy claramente la respuesta de Jonathan Hobbs , la elección del elemento html para la entrada del formulario no realiza ningún filtrado confiable por usted.
La validación generalmente se realiza de una manera que no altera los datos, pero que muestra el formulario nuevamente, con los campos marcados como "Corrija esto".
La mayoría de los frameworks y CMS tienen constructores de formularios que le ayudan con esta tarea. Y no solo eso, también ayudan contra CSRF (o "XSRF"), que es otra forma de ataque.
2. Desinfectar / escapar variables en sentencias SQL.
.. o deje que las declaraciones preparadas hagan el trabajo por usted.
Si crea una declaración (Mi) SQL con cualquier variable, proporcionada por el usuario o no, debe escapar y citar estas variables.
En general, cualquier variable que inserte en una declaración de MySQL debe ser una cadena o algo que PHP pueda convertir de manera confiable en una cadena que MySQL pueda digerir. Como números.
Para las cadenas, debe elegir uno de varios métodos para escapar de la cadena, es decir, reemplazar cualquier carácter que pueda tener efectos secundarios en MySQL.
Si se trata de un número, puede omitir el escape y las comillas (es por eso que las declaraciones preparadas permiten especificar un tipo).
Es importante señalar que se escapan las variables para la declaración SQL y NO para la base de datos en sí . La base de datos almacenará la cadena original, pero la declaración necesita una versión de escape.
¿Qué sucede si omite uno de estos?
Si no usa la validación de formularios , pero desinfecta su entrada SQL, es posible que vea todo tipo de cosas malas, ¡pero no verá la inyección SQL! (*)
Primero, puede llevar su solicitud a un estado que no planeó. Por ejemplo, si desea calcular la edad promedio de todos los usuarios, pero un usuario dio "aljkdfaqer" para la edad, su cálculo fallará.
En segundo lugar, puede haber todo tipo de otros ataques de inyección que debe considerar: por ejemplo, la entrada del usuario podría contener javascript u otras cosas.
Aún puede haber problemas con la base de datos: por ejemplo, si un campo (columna de la tabla de la base de datos) tiene un límite de 255 caracteres y la cadena es más larga. O si el campo solo acepta números y, en su lugar, intenta guardar una cadena no numérica. Pero esto no es una "inyección", es simplemente "bloquear la aplicación".
Pero, incluso si tiene un campo de texto libre donde permite cualquier entrada sin validación en absoluto, aún puede guardar esto en la base de datos así, si lo escapa correctamente cuando va a una declaración de base de datos. El problema surge cuando quieres usar esta cadena en alguna parte.
(*) o esto sería algo realmente exótico.
Si no escapa de las variables para las declaraciones SQL , pero sí validó la entrada del formulario, aún puede ver que suceden cosas malas.
En primer lugar, corre el riesgo de que cuando guarde datos en la base de datos y los vuelva a cargar, ya no sean los mismos datos, "perdidos en la traducción".
En segundo lugar, puede generar declaraciones SQL no válidas y, por lo tanto, bloquear su aplicación. Por ejemplo, si alguna variable contiene una comilla o un carácter de comilla doble, según el tipo de cita que utilice, obtendrá una declaración MySQL no válida.
En tercer lugar, todavía puede provocar una inyección SQL.
Si la entrada de usuario de los formularios ya está filtrada / validada, la inyección intencional de SQl puede volverse menos probable, SI su entrada se reduce a una lista codificada de opciones o si está restringida a números. Pero cualquier entrada de texto libre se puede utilizar para la inyección de SQL, si no se escapan correctamente las variables en las declaraciones de SQL.
E incluso si no tiene ninguna entrada de formulario, aún podría tener cadenas de todo tipo de fuentes: leídas del sistema de archivos, extraídas de Internet, etc. Nadie puede garantizar que estas cadenas sean seguras.
fuente
Su navegador web no "sabe" que está recibiendo una página de php, todo lo que ve es html. Y la capa http sabe incluso menos que eso. Debe poder manejar casi cualquier tipo de entrada que pueda cruzar la capa http (afortunadamente, para la mayoría de las entradas php ya dará un error). Si está tratando de evitar que las solicitudes maliciosas estropeen su base de datos, debe asumir que el tipo del otro extremo sabe lo que está haciendo y que no está limitado a lo que puede ver en su navegador en circunstancias normales ( sin mencionar lo que puedes jugar con las herramientas de desarrollo de un navegador). Entonces, sí, debe atender cualquier entrada de su menú desplegable, pero para la mayoría de las entradas puede dar un error.
fuente
El hecho de que haya restringido al usuario para que solo use valores de una determinada lista desplegable es irrelevante. Un usuario técnico puede capturar la solicitud http enviada a su servidor antes de que salga de su red, modificarla usando una herramienta como un servidor proxy local y luego continuar en su camino. Usando la solicitud alterada, pueden enviar valores de parámetros que no son los que usted especificó en la lista desplegable. Los desarrolladores deben tener la mentalidad de que las restricciones del cliente a menudo no tienen sentido, ya que cualquier cosa en un cliente puede modificarse. Se requiere la validación del servidor en cada punto en el que ingresan los datos del cliente. Los atacantes confían en la ingenuidad de los desarrolladores en este único aspecto.
fuente
Es mejor utilizar una consulta parametrizada para asegurarse contra la inyección de SQL. En ese caso, el aspecto de la consulta sería este:
Cuando proporciona una consulta como la anterior con texto sin verificar su integridad (la entrada no está validada en el servidor) y contiene código de inyección SQL, se manejará correctamente. En otras palabras, la solicitud dará como resultado que suceda algo como esto en la capa de la base de datos:
Esto simplemente seleccionará 0 resultados a medida que regrese, lo que hará que la consulta sea ineficaz para causar daño a la base de datos sin la necesidad de una lista blanca, una verificación de verificación u otras técnicas. Tenga en cuenta que un programador responsable hará la seguridad en capas y, a menudo, validará además de parametrizar consultas. Sin embargo, hay muy pocas razones para no parametrizar sus consultas desde una perspectiva de rendimiento y la seguridad agregada por esta práctica es una buena razón para familiarizarse con las consultas parametrizadas.
fuente
Todo lo que se envía desde su formulario llega a su servidor como texto a través de los cables. No hay nada que impida que alguien cree un bot para imitar al cliente o que lo escriba desde una terminal si así lo desea. Nunca asuma que debido a que programó al cliente, éste actuará como usted cree. Esto es muy fácil de falsificar.
Ejemplo de lo que puede suceder y sucederá cuando confíe en el cliente.
fuente
Un pirata informático puede omitir el navegador por completo, incluida la verificación de formularios de JavaScript, enviando una solicitud mediante Telnet. Por supuesto, mirará el código de su página html para obtener los nombres de campo que tiene que usar, pero a partir de ese momento es "todo vale" para él. Por lo tanto, debe verificar todos los valores enviados en el servidor como si no se originaran en su página html.
fuente