Algoritmo para evitar la inyección SQL en el servidor MSSQL desde el código C #?

¿Cuál sería la mejor manera de evitar la inyección SQL en la plataforma C # .net?

Por favor, publique una implementación de C # si tiene alguna.

Las 10 mejores cosas que podemos hacer para estar seguros (ninguno de estos lo hará todo).

  1. Adopte la noción de que “Todos los datos son malvados”. Todos los datos, incluso los datos almacenados en la base de datos o en nuestro sistema de archivos son sospechosos. No solo la entrada de datos desde aplicaciones fuera de nuestro firewall como cadenas de consulta, campos de formulario, cookies, etc. Cualquier cosa puede ser utilizada para comprometer un sistema.

  2. No confíe en la validación del lado del cliente de las longitudes de los campos javascript o html o incluso las API web del lado del servidor que usan la validación del lado del cliente. Úselo para mejorar la usabilidad, pero no confíe en él como único guardián. Sepa cómo funcionan los validadores proporcionados por API como NET. No los tomes por hecho. Hay formas de evitarlos.

  3. Haga una coincidencia positiva para capturar todos los datos a medida que avanza. Si los datos coinciden con los rangos de caracteres de una expresión regular, entonces está bien. Esto no permite caracteres extraños unicode en nuestra base de datos que puedan delimitar accidentalmente algo en sql o crear otros problemas como Homographic XSS / Phishing Attacks. Por el contrario, la coincidencia negativa requiere listas de todos los caracteres incorrectos, que parecen crecer todo el tiempo. Este es un mal enfoque. La coincidencia positiva es mejor. Rechazamos los datos incorrectos, no los desinfectamos ni escapamos de ellos.

  4. Cuando sea posible, considere filtrar, marcar o capturar datos de cadena con “actualizar”, “eliminar”, “soltar”, “seleccionar”, “alterar”, etc. Esto puede no ser posible dada la naturaleza de la cadena. “1212 Lemondrop Ln”, “Waltersburg, PA” y “Table Rock, NE” son campos de dirección válidos. Ejecutar un escaneo diario de todos los datos de la tabla para los campos que coincidan con cualquiera de estos podría revelar ataques retrasados ​​o vulnerabilidades. También se puede usar el registro, la prohibición de direcciones IP, las alertas por correo electrónico, etc., ya que los datos llegan entrantes.

  5. Use procedimientos almacenados y / o consultas parametrizadas tanto como sea posible. Evite sql dynamic tanto en el código de cliente db como en sql. (¡Evite las sentencias ejecutivas con código dynamic con secciones externas en sus procedimientos almacenados!) La parametrización escapará a los terminadores de cadenas como el apóstrofo, las longitudes de campo de captura y la verificación de tipo. No siempre podemos confiar en que las API que proporcionan parametrización sean perfectas, pero están escritas por personas mucho más conscientes de las idiosincrasias de la base de datos que la mayoría de nosotros.

  6. Asegúrese de que no haya ningún código perdido en un directorio web legible / ejecutable en todo el mundo. Si no es parte del sitio activo, archívelo en algún lugar seguro y elimínelo de la vista pública. Lo mismo ocurre con los procedimientos almacenados no utilizados.

  7. Manténgase actualizado sobre las API de la base de datos. Algunas formas de ejecutar sentencias de SQL en algunas API no son tan seguras como otras.

  8. Almacene las contraseñas de forma segura con el cifrado de una vía. De esta forma, un volcado de tablas de nombres de usuario y contraseñas aún debería mantener a la gente fuera.

  9. Endurezca el servidor de todas las formas habituales. Por ejemplo, cuando sea posible, otorgue menos privilegios a las tablas de la base de datos. Limite el acceso de las cuentas de la base de datos del servidor web estrictamente a las tablas en cuestión. Utilice solo lectura tanto como sea posible. Cree varias cuentas que creen una división entre los derechos de acceso del público y el tráfico interno / de confianza.

  10. Captura errores con gracia. Esto vale para todo el código, no solo para el código que usa la base de datos. Sin embargo, los ataques de inyección Sql dependen de los mensajes de error, por lo que es deseable ocultar todo lo posible sobre la base de datos del público. Siempre escriba código que maneje excepciones o conjuntos de datos vacíos de forma generalizada para revelar lo menos posible sobre qué tipo de base de datos estamos utilizando, qué campos están en nuestras tablas o qué tipo de consultas estamos ejecutando. Errores de registro en el servidor. Incluso en el código que no es de base de datos, es mejor no hablar de los componentes de terceros, las estructuras de carpetas de archivos, otros servicios que podemos estar ejecutando, etc. Darles a los malos usuarios la menor información posible es clave para que no tengan ni idea.

Y # 11, siempre revisita / revisa esta lista. Siempre al día. Ser proactivo. Convertirlo en una prioridad y requisito inicial, no en una idea posterior.

No se necesita algoritmo, simplemente no use concatenación de cadenas para construir sentencias de SQL. Use la colección SqlCommand.Parameters en su lugar. Esto hace todos los escapes de valores necesarios (como reemplazar ' con '' ) y asegura que el comando estará seguro porque alguien más (es decir, Microsoft) ha hecho todas las pruebas.

por ejemplo, llamar a un procedimiento almacenado:

 using (var connection = new SqlConnection("...")) using (var command = new SqlCommand("MySprocName", connection)) { command.CommandType = CommandType.StoredProcedure; command.Parameters.AddWithValue("@Param1", param1Value); return command.ExecuteReader(); } 

Esta técnica también funciona para declaraciones SQL en línea, por ejemplo

 var sql = "SELECT * FROM MyTable WHERE MyColumn = @Param1"; using (var connection = new SqlConnection("...")) using (var command = new SqlCommand(sql, connection)) { command.Parameters.AddWithValue("@Param1", param1Value); return command.ExecuteReader(); }