2009-03-25 10 views
25

He creado una pequeña página web de encuestas en la Intranet de nuestra compañía. Esta página web no es accesible desde el exterior.Inyección SQL en INSERT

El formulario es simplemente un par de botones de opción y un cuadro de comentarios.

Me gustaría mantener buenas prácticas de codificación y me gustaría protegerme contra las inyecciones de SQL.

¿Pueden ocurrir inyecciones de SQL en una instrucción de inserción con comentarios del cuadro de texto? En caso afirmativo, ¿cómo puedo evitarlo utilizando .NET 2.0?

+0

Información adicional: Cuando construya una página web, no se concentre solamente en la inyección sql. Compruebe también el peligro XSS del texto antes de insertarlo en su base de datos. ¿Están protegidos todos los códigos de salida a través de Server.HtmlEncode (...)? –

Respuesta

54

La inyección puede ocurrir en cualquier instrucción SQL que no se ejecute correctamente.

Por ejemplo, imaginemos que su tabla de comentarios tiene dos campos, una ID de entero y la cadena de comentario. Quizás INSERT de la siguiente manera:

INSERT INTO COMMENTS VALUES(122,'I like this website'); 

considerar a alguien entrar en el siguiente comentario:

'); DELETE FROM users; -- 

Si usted acaba de poner la cadena de comentario en el SQL sin ningún processesing esto podría dar vuelta a su sola INSERT a las siguientes dos declaraciones seguidas de un comentario:

INSERT INTO COMMENTS VALUES(123,''); DELETE FROM users; -- '); 

esto sería eliminar todo, desde su mesa users. Y hay personas dispuestas a pasar todo el día encontrando el nombre de tabla correcto para vaciar usando prueba y error y varios trucos. Here's a description of how you could perform an SQL Injection attack.

Necesita evitar el parameterized SQL statements para evitar esto.

Y esto no es solo por razones de seguridad. Por ejemplo, si va a crear las sentencias SQL ingenuamente el siguiente comentario:

I'm just loving this website 

podría causar un error de sintaxis SQL debido a la apóstrofe ser interpretada por SQL como una cotización de cierre.

+2

buen punto en el apóstrofo - He estado usando el método string.replace - pero puedo ver que esto es mucho más fácil. – Brad

+0

Muy bien explicado. Bien hecho. –

+1

Incluso un nombre podría causar un problema si no se hace como un parámetro, por ejemplo, O'Tool, O'Rourke. – Martin

27

Utilice las consultas parametrizadas para que el texto se escriba automáticamente.

SqlCommand command = connection.CreateCommand(); 
command.CommandText = "insert into dbo.Table (val1,val2,txt) values (@val1,@val2,@txt)"; 
command.AddParameterWithValue("val1", value1); 
command.AddParameterWithValue("val2", value2); 
command.AddParameterWithValue("txt", text); 

... 
-4

La manera más fácil de protegerse contra esa forma de inyección de SQL es usar parámetros y procedimientos almacenados en lugar de construir sentencias SQL para ejecutar. (En C# o internamente en SQL Server).

Sin embargo, no estoy del todo seguro de que deba dedicar tiempo a esto, a menos que sea su política corporativa, ya que las posibilidades de que ocurra internamente son mínimas en el mejor de los casos, y si ocurriera, le esperaría sabría de inmediato quién es.

+0

Por supuesto, un empleado disgustado nunca trataría de manguera la base de datos de su compañía. SIEMPRE necesita preocuparse por la seguridad y seguir las mejores prácticas. – tvanfosson

+0

No estoy de acuerdo. Esta es una página web interna a la que ningún ex empleado debería poder acceder. También supongo (o ciertamente espero) que todo el tráfico interno se registra. Las necesidades de seguridad se deben evaluar junto con otras críticas, y no se pueden justificar en una serie de situaciones. – Bravax

+0

¿Quién dice que tienes que ser un ex empleado para estar descontento? La buena seguridad evita el daño y no culpa después. En este caso, el costo de usar consultas parametrizadas no es muy alto. Debería ser la norma al construir consultas a mano. – tvanfosson

0

Sí, puede.Digamos que el cliente envía esto:

OR 1 = 1 

que puede ser muy doloroso para su

SELECT * FROM admin WHERE name = @name AND password = @password 

Esto se puede evitar con

+0

La pregunta era explícita sobre las instrucciones INSERT. –

+0

cierto. pero tal vez la lista ayude – boj

0

Sí, pueden suceder. La forma más fácil de evitar esto es usar declaraciones preparadas en lugar de construir el SQL manualmente.

Así, en lugar de esto:

String sql = 
String.Format("INSERT INTO mytable (text_column) VALUES ('{0}')", 
    myTextBox.Text); // Unsafe! 

deberías hacer algo como esto:

String sql = "INSERT INTO mytable (text_column) VALUES (?)"; // Much safer 

A continuación, añada el texto del cuadro de texto como un parámetro a su DbCommand cual hará que se escaparse automáticamente y reemplazar el "?" en el SQL.

0

Además de utilizar los estados y parámetros preparadas en lugar de la concatenación de cadenas en su SQL también debe hacer lo siguiente:

  1. Validar y formato de entrada de usuario en el servidor. La validación y los límites del lado del cliente pueden pasarse fácilmente por alto con herramientas como WebScarab, o al suplantar su formulario.

  2. Configure los permisos apropiados para la cuenta de usuario de la base de datos. La aplicación web debe usar una cuenta o función separada en su base de datos con permisos restringidos solo a las tablas, vistas y procedimientos necesarios para ejecutar su aplicación. Asegúrese de que el usuario no tenga derechos selectos en las tablas del sistema

  3. Oculte los mensajes de error detallados de los usuarios y utilice nombres menos comunes para sus objetos. Me sorprende la frecuencia con la que puede determinar el tipo de servidor (oracle, mysql, sqlserver) y encontrar información básica del esquema en un mensaje de error y luego obtener información de tablas llamadas 'usuario (s)', 'empleado (s)'. Si no ha establecido sus permisos como en (2) y que puede determinar el tipo de servidor que está abierto a declaraciones como esta para SQL Server

    nombre_tabla SELECT information_schema.table

    EJECUTAR sp_help foundTableName

3

La inyección SQL puede ocurrir cada vez que pasa una consulta a la base de datos. He aquí una simple demostración:

SQL Injection Explained

La clave, dentro de .NET, es hacer como Dave Webb ha dado. Evitará el intento de inyección al abarcar toda la cadena como un parámetro a enviar, manejando todos los caracteres que puedan ser interpretados por SQL Server para cambiar la consulta o anexar comandos adicionales.

Y debe señalarse que la inyección SQL puede ocurrir en cualquier aplicación, no solo en aplicaciones web. Y que un ataque interno suele ser el más costoso para una organización. Uno no puede asumir con seguridad que un ataque no se originará desde adentro.

0

Prevenga la inyección de SQL utilizando la instrucción preparada. El uso de placehoder (?) Elimina por completo la vulnerabilidad de inyección de sql. ejemplo Cadena sql = Seleccionar * de la tabla de usuario donde nombre de usuario = '+ request.getparameter ("username") +'; statement.executeQuery (sql);

la declaración anterior es vulnerable a la inyección sql.

Para que sea seguro contra la inyección sql. Usar siguiendo el fragmento

Cadena sql = Seleccionar * de user_table donde username = ?; statement.setString (1, nombre de usuario);

+0

La sintaxis '?' no funciona para todos los proveedores/bases de datos. –