En el artículo anterior, ya hablamos sobre la esencia de las vulnerabilidades de ataque de inyección SQL causadas por una codificación incorrecta por parte de los programadores. Ahora continuaremos hablando sobre cómo codificar correctamente para no ser atacados por la inyección SQL. problema Primero echemos un vistazo a un fragmento de código:
Copie el código de código de la siguiente manera:
tenue sql_injdata,SQL_inj,SQL_Get,SQL_Data,Sql_Post
SQL_injdata = '|y|exec|insertar|seleccionar|eliminar|actualizar|recuento|*|%|chr|mid|master|truncar|char|declarar
SQL_inj = dividir(SQL_Injdata,|)
Si Request.QueryString<> Entonces
Para cada SQL_Get In Request.QueryString
Para SQL_Data=0 a Ubound(SQL_inj)
si instr(Request.QueryString(SQL_Get),Sql_Inj(Sql_DATA))>0 Entonces
Response.Write <Script Language=javascript>alert('Solicitudes del sistema anti-inyección SQL, ¡no intente inyectar nuevamente!');
Respuesta.fin
terminar si
próximo
Próximo
Terminar si
Si Solicitud.Form<> Entonces
Para cada Sql_Post en Request.Form
Para SQL_Data=0 a Ubound(SQL_inj)
si instr(Request.Form(Sql_Post),Sql_Inj(Sql_DATA))>0 Entonces
Response.Write <Script Language=javascript>alert('Solicitudes del sistema anti-inyección SQL, ¡no intente inyectar nuevamente!');
Respuesta.fin
terminar si
próximo
próximo
terminar si
Este es un fragmento de código anti-inyección ASP que es muy popular en Internet. La idea es verificar los datos enviados por el método Post y el método Get, y evitar la inyección SQL filtrando caracteres confidenciales como Insertar, Actualizar y. , etc. En teoría, si filtramos suficientes caracteres, definitivamente podemos garantizar que no seremos atacados por inyección SQL, pero tenga cuidado. Lea este código y preste atención a cómo se juzga a través de la función instr. Es decir, si quiero filtrar el carácter y, no solo se filtra la palabra Y, sino también todas las palabras. que contiene y. Se han filtrado todas las palabras con las siguientes combinaciones de caracteres, como isla, continente, mano... Si estos caracteres se filtraran, ¿alguien todavía estaría dispuesto a usarlos? Por lo tanto, este método de filtrar caracteres sensibles no tiene ningún sentido. Lo que me sorprende es que una basura así se publique en Internet como un clásico.
Algunas personas dicen que los ataques de inyección SQL son causados por el empalme de cadenas de consulta SQL, por lo que el uso de procedimientos almacenados sin empalmar cadenas de consulta SQL puede protegerlo de los ataques de inyección SQL. No necesariamente, veamos un ejemplo de un ataque de inyección de procedimiento almacenado.
El código del procedimiento almacenado dt_GetNews es el siguiente:
CREAR PROCEDIMIENTO dt_GetNews
@tipo de noticia int
COMO
seleccione * de noticias donde tipo de noticia=@tipo de noticia
IR
Código de llamada:
<%
adoconexión tenue
establecer adoconnection=servidor.createobject(adodb.conexión)
'.........Aquí se omite el código relevante para establecer una conexión a la base de datos.
adoconnection.execute exec dt_GetNews +solicitud(tipo de noticia)
adoconexión.cerrar
%>
Si el valor de solicitud (tipo de noticia) es igual a 1, el resultado de la operación es devolver todos los registros cuyo campo tipo de noticia en la tabla de noticias sea 1. Sin embargo, si el valor de solicitud (tipo de noticia) es 1, elimine las noticias de la tabla; , el resultado devuelto es que se elimina la tabla de noticias.
Se puede ver en este ejemplo que incluso el uso de procedimientos almacenados seguirá siendo atacado. Además, seleccione * de las noticias donde newstype=@newstype no está empalmado, por lo que no existe una conexión inevitable entre el empalme de cadenas de consulta SQL y los ataques de inyección SQL. Es posible que los procedimientos almacenados no puedan proteger contra ataques de inyección.
Entonces, ¿cómo se escribe sin ser atacado por la inyección SQL? A continuación, presentaré un método definitivo, para decirlo sin rodeos, que es muy simple y primitivo, que es la verificación del tipo de datos y el reemplazo de comillas simples. Ya sea Oracle, Sql Server, mySql, Access u otras bases de datos relacionales, los tipos de campos se pueden dividir aproximadamente en dos categorías: tipos numéricos (como int, float, etc.) y tipos de caracteres (como char, varchar, etc. ). Las declaraciones SQL correspondientes son ligeramente diferentes según el tipo de campo, como por ejemplo:
El campo tipo de noticia en Seleccionar * de noticias donde tipo de noticia=1 debe ser un campo numérico.
seleccione * de noticias donde tipo de noticia = 'noticias sociales' el campo de tipo de noticia debe ser un campo de caracteres.
Para campos numéricos, lo que debemos hacer es verificar el tipo de datos del parámetro. Por ejemplo, cuando construimos una declaración de consulta usando select * from news donde newstype=+v_newstype, debemos verificar el tipo de datos de la variable v_newstype. es al menos Debe ser un número, que puede ser un número entero o de punto flotante. Si se realiza dicha verificación, seleccione * de noticias donde tipo_noticias=+v_tipo_noticias nunca construirá algo similar a seleccionar * de noticias donde tipo_noticias=1. ;gota Declaraciones como noticias de mesa. La razón por la que ASP es más vulnerable a ataques que ASP.Net, JSP, etc. es porque no es necesario declarar las variables en ASP y el tipo de variable no está claro.
Para los campos de caracteres, lo que debemos hacer es procesar comillas simples ('). El método de procesamiento es reemplazar una comilla simple con dos comillas simples (''). Cuando se usa newstype = '+v_newstype +' para construir la declaración de consulta, la comilla simple en v_newstype debe reemplazarse con dos comillas simples, porque en SQL la parte encerrada por dos comillas simples representa una cadena y dos consecutivas Una sola quote representa un carácter de comilla simple. Después de dicho procesamiento, veremos el método de construcción de select * from news donde newstype='+v_newstype+' Cuando el valor de v_newstype es:
Noticias sociales; soltar noticias de mesa--
Después de reemplazar una comilla simple por dos comillas simples, el valor de v_newstype se convierte en:
Noticias sociales'';noticias de mesa desplegable--
La declaración SQL construida se convierte en:
seleccione * de noticias donde newstype='noticias sociales'';soltar noticias de la tabla—'
El resultado de la consulta es devolver registros cuyo valor del campo tipo de noticia en la tabla de noticias es noticias sociales';eliminar noticias de la tabla--, sin provocar que la tabla de noticias se elimine como antes.
Además, no es solo la instrucción Select la que debe procesarse, incluidas Insertar, Actualizar, Eliminar, Ejecutar, etc., puede echar un vistazo a los siguientes métodos de inyección:
En la estructura inserte en news(title) valores('+v_title+'),
Cuando v_title=123';eliminar noticias de la tabla--';
Cuando actualice el conjunto de noticias /> cuando v_title = 123'-- o v_id = 1; elimine las noticias de la tabla--, por lo que no es solo un problema con la declaración Select, sino que otras declaraciones pueden tener problemas, no se concentre solo en Select
En resumen, después de verificar el tipo de datos y procesar las comillas simples, incluso si tiene todas las habilidades, no podrá salir volando de la palma de mi Tathagata.