¿Cómo prevenir la inyección SQL?
Se accede a la inyección SQL desde el puerto WWW normal. En la superficie, no se ve diferente del acceso normal a una página web, por lo que actualmente no existe ningún firewall en el mercado que active la alarma por inyección SQL.
Si el administrador no tiene la costumbre de comprobar los registros de IIS, puede verse comprometido durante mucho tiempo sin que se dé cuenta.
Sin embargo, el método de inyección SQL es bastante flexible y se encontrarán muchas situaciones inesperadas durante el proceso de inyección. La diferencia fundamental entre expertos y "novatos" es si pueden analizar la situación específica y construir declaraciones SQL inteligentes para obtener con éxito los datos deseados.
Desde la perspectiva de las condiciones nacionales, más del 70% de los sitios web nacionales utilizan ASP+Access o SQLServer, PHP+MySQ representa el 20% y otros menos del 10%. En este artículo, explicaremos los métodos y técnicas de inyección ASP desde principiantes hasta avanzados. El artículo sobre la inyección de PHP fue escrito por zwell, otro amigo de NB Alliance. Espero que sea útil para los trabajadores y programadores de seguridad. Los amigos que conocen la inyección de ASP no deben saltarse el artículo introductorio, porque algunas personas todavía tienen malentendidos sobre el método básico de inyección. ¿Estás listo? Vamos...
Capítulo para principiantes
Si no has probado la inyección SQL antes, el primer paso es poner IE Menu=>Tool=>Internet Options=>Advanced =>Quitar la marca marque delante de los mensajes de error HTTP amigables. De lo contrario, no importa qué error devuelva el servidor, IE solo lo mostrará como error de servidor HTTP 500 y no obtendrá más información rápida.
Sección 1, Principios de la inyección SQL
Hablemos primero de un sitio web, www.mytest.com (Nota: el webmaster del sitio web estuvo de acuerdo antes de que se publicara este artículo, y la mayor parte son datos reales).
Hay un enlace en la página de inicio del sitio web llamado "Varias soluciones para IE que no abren una nueva ventana" en la dirección:/showdetail.asp? Id=49, agregamos una comilla simple después de la dirección, el servidor devolverá el siguiente mensaje de error:
Error del motor de base de datos Microsoft JET "80040e14"
El error de sintaxis de la cadena está en la expresión de consulta "ID=49".
/showdetail.asp, línea 8
Podemos ver los siguientes puntos en este mensaje de error:
1. El sitio web utiliza la base de datos Access, a través de The JET. El motor se conecta a la base de datos en lugar de ODBC.
2. El programa no determina si los datos enviados por el cliente cumplen con los requisitos del programa.
3. Hay un campo llamado ID en la tabla consultada por esta declaración SQL.
Del ejemplo anterior, podemos saber que el principio de la inyección SQL es enviar un código especial desde el cliente para recopilar información del programa y del servidor para obtener la información que desea.
Sección 2, Determinar si la inyección SQL es posible
Después de leer la primera sección, algunas personas pueden pensar: A menudo pruebo si la inyección se puede realizar de esta manera, ¿no es así? ¿simple?
De hecho, esta no es la mejor manera. ¿Por qué?
En primer lugar, el IIS de cada servidor no necesariamente devuelve un mensaje de error específico al cliente. Si se agrega una declaración como cint (parámetro) al programa, la inyección SQL no tendrá éxito, pero el servidor también informará un error. La información del mensaje específico es un error que ocurre cuando el servidor procesa la URL. Comuníquese con el administrador de su sistema.
En segundo lugar, no es raro que algunos programadores que saben un poco sobre inyección SQL piensen que sólo es seguro
filtrar las comillas simples. Si prueba con comillas simples, no podrá detectar el punto de inyección.
Entonces, ¿qué tipo de método de prueba es más preciso? La respuesta es la siguiente:
① /showdetail.asp? id=49
②/showdetail.asp? id = 49 y 1=1
③/showdetail.asp? id = 491=2
Este es el método de prueba clásico de 1=1 y 1=2. ¿Cómo juzgar? Eche un vistazo a los resultados arrojados por los tres sitios web anteriores:
Rendimiento que se puede inyectar:
①Visualización normal (esto es inevitable, de lo contrario el programa tendrá errores)
② se muestra normalmente y el contenido es básicamente el mismo que ①.
(3) Solicitar BOF o EOF (cuando el programa no hace ningún juicio), o indicar que no se puede encontrar el registro (cuando juzga rs.eof), o mostrar contenido está vacío (el programa tiene agregado en caso de error reanudar a continuación).
Es más fácil saberlo si no puedes inyectarte. ①También se muestra normalmente. ② y ③ Generalmente, hay mensajes de error de definición de programa o errores de conversión de tipos.
Por supuesto, este es solo un método de juicio cuando el parámetro entrante es un valor numérico. En las aplicaciones reales, habrá parámetros de caracteres y parámetros de búsqueda, que analizaré en los "Pasos generales de la inyección SQL" en el capítulo intermedio.
Sección 3, Determinar el tipo de base de datos y el método de inyección
Las funciones y métodos de inyección de diferentes bases de datos son diferentes, por lo que antes de inyectar, debemos determinar el tipo de base de datos. Generalmente, las bases de datos más utilizadas para ASP son Access y SQL Server, y más del 99% de los sitios web en Internet son una de ellas.
¿Cómo puede un programa decirte qué base de datos utiliza? Veamos:
SQLServer tiene algunas variables de sistema. Si el indicador de IIS del servidor no está cerrado y SQLServer devuelve un mensaje de error, puede obtenerlo directamente desde el mensaje de error. El método es el siguiente:
/showdetail.asp? id = 49 y usuario & gt0
Esta oración es muy simple, pero contiene la esencia del método de inyección único de SQLServer. Yo mismo también descubrí este eficaz método de adivinación durante una prueba accidental. Déjame ver lo que significa: en primer lugar, la declaración anterior es normal y se centra en usuario > 0. Sabemos que usuario es una variable incorporada de SQL Server y su valor es el nombre de usuario de la conexión actual, y el tipo es nvarchar. Para comparar un valor de nvarchar con el número 0 de int, el sistema primero intenta convertir el valor de nvarchar a un int. Por supuesto, habrá errores en el proceso de conversión. El mensaje de error de SQL Server es: Convertir nvarchar a int.
Se produjo un error de sintaxis al convertir el valor ar "abc" a una columna de tipo de datos int. Jaja, abc es el valor de la variable usuario, por lo que puedes obtener fácilmente el nombre de usuario de la base de datos. En las próximas páginas verás muchas frases que utilizan este método.
Por cierto, todos sabemos que el usuario sa de SQL Server es un rol equivalente a los permisos de Administrador. Con permisos sa, es casi seguro que podrá conseguir el administrador del host. El método anterior puede probar fácilmente si inicia sesión con sa. Cabe señalar que si inicia sesión con sa, el mensaje es que hay un error al convertir "dbo" a una columna int, no "sa".
Si el servidor IIS no permite devolver un mensaje de error, ¿cómo determinar el tipo de base de datos? Podemos comenzar con la diferencia entre Access y SQL Server. Tanto Access como SQLServer tienen sus propias tablas de sistema, como las que se utilizan para almacenar todos los objetos en la base de datos. El acceso está en la tabla del sistema [objetos msy], pero al leer esta tabla en el entorno web, aparecerá "sin permiso". SQLServer está en la tabla [objetos sys] y se puede leer normalmente en el entorno web.
Al confirmar que la inyección es posible, utilice la siguiente declaración:
/showdetail.asp? id = 49 y (seleccione recuento (*) de sysobjects)>0
/showdetail.asp? id = 49 y (seleccione count(*) from msysobjects)>0
Si la base de datos es SQLServer, ¿entonces la página de la primera URL es la misma que la página original /showdetail.asp? Id=49 es más o menos lo mismo; la segunda URL generará un error porque no se puede encontrar la tabla msysobjects. Incluso si el programa es tolerante a fallos, la página será completamente diferente de la página original.
Si la base de datos utiliza Access, la situación es diferente. La página de la primera URL es completamente diferente de la página original. El segundo sitio web depende de si la configuración de la base de datos permite leer las tablas del sistema, lo que generalmente no está permitido, por lo que es completamente diferente del sitio web original. En la mayoría de los casos, puede usar la primera URL para conocer el tipo de base de datos utilizada por el sistema, y la segunda URL solo se usa para verificación al abrir el mensaje de error de IIS.
Artículo de progreso
En el capítulo introductorio, aprendimos cómo juzgar la inyección SQL, pero esto no es suficiente para obtener realmente el contenido confidencial del sitio web. A continuación, pasaremos a aprender cómo obtener lo que queremos de la base de datos. Primero, echemos un vistazo a los pasos generales de la inyección SQL:
Sección 1, Pasos generales de la inyección SQL
Primero determine el entorno, encuentre el punto de inyección y determine el tipo de base de datos. En el artículo introductorio Ya mencionado aquí.
En segundo lugar, según el tipo de parámetro inyectado, reconstruya mentalmente la apariencia original de la declaración SQL. Según el tipo de parámetro, se divide principalmente en los siguientes tres tipos:
Los números son valores numéricos. La apariencia original de la declaración SQL es aproximadamente la siguiente:
Seleccione * nombre de tabla del campo=49.
Los parámetros inyectados son ID =49 y [condición de consulta], que indican la declaración generada:
Seleccione * del nombre de la tabla, donde el campo =49 y [condición de consulta]
(B) Clase= Serie inyectada Los parámetros son de tipo carácter. La declaración SQL original se ve aproximadamente como sigue:
Seleccione * del nombre de la tabla, donde campo =' serie '
<. p>Los parámetros inyectados son Class= series ' y [Condiciones de consulta] y ' ' =' = ', es decir, la declaración generada:Seleccione * del nombre de la tabla, donde campo =' series ' y [condiciones de consulta] y ' ' ='' = ' '
Si los parámetros no se filtran durante la búsqueda, como palabra clave = palabra clave, la apariencia original de la declaración SQL es aproximadamente la siguiente:
Seleccione * del nombre de la tabla, con campos como ' % palabra clave% '
Los parámetros inyectados son palabra clave= ' y [condición de consulta] y ' % 25' = ', es decir, el declaración generada:
Seleccione * del nombre de la tabla, donde los campos son como "%", [Condiciones de consulta] y "%"="%"
Luego, reemplace las condiciones de consulta con declaraciones SQL y adivine el nombre de la tabla, por ejemplo:
ID=49 y (seleccione de Admin Count(*))>=0
Si la página es la misma que la página con ID = 49, la condición adicional es verdadera, es decir, la tabla Admin existe; de lo contrario, no existe (recuerde este método). Y así sucesivamente hasta adivinar el nombre de la tabla.
Después de adivinar el nombre de la tabla, use Count (nombre del campo) en lugar de Count (*) y use el mismo principio para adivinar el nombre del campo.
Algunas personas dirán: Aquí hay algunos elementos accidentales. Si el nombre del reloj es complicado e irregular, entonces no es necesario jugar con él en absoluto. Así es. No existe una tecnología de piratería 100% exitosa en este mundo. Las moscas no pican los huevos sin costuras. Por muy inteligente que sea un hacker, sólo atacará porque los programas de otras personas están mal escritos o porque el conocimiento de la confidencialidad del usuario es insuficiente.
Un poco fuera de tema.
Por otro lado, el programa todavía tiene una forma de decirnos los nombres de las tablas y los nombres de los campos de la biblioteca SQLServer, que presentaremos en el artículo avanzado.
Finalmente, después de adivinar con éxito el nombre de la tabla y el nombre de la columna, obtenga el valor del campo utilizando una declaración SQL. Aquí presentamos uno de los métodos más utilizados: el método de decodificación palabra por palabra en Ascii. Aunque este método es lento, ciertamente es factible.
Por ejemplo, sabemos que el campo de nombre de usuario existe en la tabla Admin. Primero, obtenemos el primer registro y probamos su longitud:
/showdetail.asp? id = 49 y (seleccione el 1 superior len (nombre de usuario) de Admin>; 0
Primero explique el principio: si la longitud del 1 nombre de usuario superior es mayor que 0, la condición es verdadera; entonces > 1, > ;2. gt;3 Pruebe de esta manera hasta que la condición no sea verdadera, como > 7 es verdadera, > 8 no es verdadera, es decir, len (nombre de usuario) = 8. Por supuesto, nadie es tan estúpido como para comenzar desde 0, 1, 2, 3. Comience a probar uno por uno. Cómo hacerlo más rápido depende de su propio rendimiento. Después de obtener la longitud del nombre de usuario, use mid(nombre de usuario, N, 1) para interceptar el enésimo carácter y luego use asc(mid(username). , N, 1)) para obtener el código ASCII, por ejemplo:
id=49 y (seleccione el 1 ASC superior (mid(username, 1, 1)) from Admin)>0
De manera similar, el código ASCII de 1 carácter se obtiene reduciendo gradualmente el rango. Tenga en cuenta que el código ASCII de inglés y números está entre 1. -128, que se puede utilizar para acelerar el proceso de adivinación. p>
Sección 2, Funciones comunes de inyección SQL
Las personas con conocimientos básicos del lenguaje SQL tienen una tasa de éxito mucho mayor. Inyección de SQL que aquellos que no están familiarizados con ella. Necesitamos mejorar nuestro nivel de SQL, especialmente algunas funciones y comandos de uso común
Access:asc(character)SQLServer:unicode(character)
<. p>Función: Devuelve el código ASCII del carácterAcceso: chr (número) SQLServer: nchar (número)
Función: opuesta a asc, devuelve caracteres según el código ASCII.
Acceso: mid (cadena, N, L N, L) SQLServer: subcadena (cadena, N, L)
Función: Devuelve una subcadena de longitud L a partir de N caracteres, que. es, una cadena entre N y N+L
Acceso: abc (número) SQLServer: abc (número)
Función: Devuelve el valor absoluto de un número (usado al adivinar chino caracteres)
Acceso: entre B y C A servidor SQL: A entre B y C
Función:
Determinar si A está entre B y c p>
Sección 3, Chino. Cómo lidiar con ello
Es común que algunas personas retrocedan cuando se encuentran con caracteres chinos. De hecho, siempre que comprendan la codificación china, se trata de "fobia a los chinos". se puede superar rápidamente
Hablemos primero de algo de sentido común:
En Access, puede haber números negativos en el código ASCII chino. Después de eliminar los números negativos, use abs(. ) para obtener el valor absoluto y los caracteres chinos no cambiarán.
En SQL Server, el ascii chino es un número positivo, pero debido a que es una codificación UNICODE de dos dígitos, la función ASCII() no se puede utilizar para obtener el código ASCII. Debe usar la función unicode () para devolver el valor Unicode y luego usar la función nchar para obtener el carácter chino correspondiente.
Después de comprender los dos puntos anteriores, ¿crees que adivinar palabras en chino es realmente similar al inglés? El método no es diferente, pero es necesario prestar atención a las funciones utilizadas y el rango de adivinanzas es mayor.
Artículos avanzados
Después de leer los artículos introductorios y avanzados, con un poco de práctica, no será un problema descifrar sitios web comunes. Pero si no puede adivinar el nombre de la columna de la tabla, o el autor del programa ha filtrado algunos caracteres especiales, ¿cómo mejorar la tasa de éxito de la inyección? ¿Cómo mejorar la eficiencia de las adivinanzas? Continúe leyendo el capítulo avanzado.
Sección 1, uso de tablas del sistema para inyectar en la base de datos SQLServer
SQL Server es un poderoso sistema de base de datos, estrechamente relacionado con el sistema operativo, que brinda una gran comodidad a los desarrolladores, pero en el Por otro lado, también proporciona un trampolín para los inyectores. Veamos primero algunos ejemplos específicos.
:
①Nombre de usuario y contraseña/agregar "-
Punto y coma; en SQL Server, significa separar las dos oraciones antes y después, es decir say La siguiente declaración es un comentario. Por lo tanto, esta declaración se dividirá en dos oraciones en SQL Server. Primero, seleccione el registro con ID = 1 y luego ejecute el procedimiento almacenado xp_cmdshell. Por lo tanto, se utilizará el comando net. una nueva cuenta de Windows con un nombre de usuario y contraseña y luego:
②Nombre del grupo local administradores /add" -
Agregue el nombre de la cuenta recién creada al grupo de Administradores. En dos minutos, ¡Obtén la máxima autoridad del sistema! Por supuesto, este método solo es aplicable cuando se usa sa para conectarse a la base de datos; de lo contrario, no tendrá derecho a llamar a xp_cmdshell.
③pub\wwwroot\1.db';-
Este es un movimiento muy malicioso. ③Se realizará una copia de seguridad del nombre de la base de datos obtenida, más algunas rutas absolutas expuestas por errores de IIS, en el directorio web, y luego toda la base de datos se descargará completamente a través de HTTP. ¡Todas las contraseñas de administradores y usuarios quedarán claras de un vistazo! Cuando no se conoce la ruta absoluta, también puede realizar una copia de seguridad en una dirección de red (como \202.96.xx.xx\Share \1.db), pero la tasa de éxito no es alta.
⑤ http://Sitio/url.asp? id = 1; y (Seleccione el nombre principal de sysobjects donde xtype = 'U' y estado >0)>0
Como se mencionó anteriormente, sysobjects es la tabla del sistema de SQL Server y almacena todas las tablas. , vista, restricción y otros objetos, xtype = 'u' y status > 0, representan el nombre de la tabla creada por el usuario. La declaración anterior toma el primer nombre de la tabla y lo compara con 0, por lo que el mensaje de error expone el nombre de la tabla. ¿Cómo obtener el nombre de la segunda y tercera tabla? Dejemos que los lectores inteligentes piensen.
⑥ http://Sitio/url.asp? id = 1; y (seleccione la 1 columna superior _ nombre (objeto _ id ('nombre de la tabla'), 1) de sysobjects)>0
Después de obtener el nombre de la tabla de ⑤, use Objeto _ ID ( 'nombre de la tabla ') obtiene el ID interno correspondiente al nombre de la tabla, col_name (ID del nombre de la tabla, 1) representa el nombre del campo 1 de la tabla, reemplace 1 con 2, 3, 4... Obtenga los nombres de los campos en el adivinado mesa uno por uno.
Los seis puntos anteriores son el resultado de más de medio año de aprendizaje de la inyección de SQL Server. Se puede ver que la comprensión de SQL Server afecta directamente la tasa de éxito y la velocidad de adivinación. Después de aprender la inyección de SQLServer, mi nivel de desarrollo también mejoró enormemente. Jaja, tal vez la seguridad y el desarrollo se complementen.
Sección 2: Eludir las restricciones del programa y continuar inyectando
Como se mencionó en el artículo introductorio, a muchas personas les gusta usar 'pruebas numéricas' para inyectar vulnerabilidades, por lo que muchas personas usan el filtrado ' Pruebas numéricas' Métodos para "prevenir" vulnerabilidades de inyección, que pueden bloquear los ataques de algunos principiantes, pero las personas familiarizadas con la inyección SQL aún pueden usar funciones relacionadas para evitar las restricciones del programa.
En la sección "Pasos generales para la inyección SQL", todas las declaraciones que utilicé han sido optimizadas por mí para que no contengan comillas simples en la sección "Inyección de la base de datos SQLServer con tablas del sistema", algunas de las cuales son: la declaración contiene signo. Pongamos un ejemplo.
Aprende cómo convertir estas declaraciones:
Simple como donde xtype='U ', el código ASCII correspondiente al carácter U es 85, entonces puedes usar donde xtype=char( 85) en su lugar, si los caracteres son chinos, como donde nombre='usuario', puedes usar donde nombre = nchar(29992)+nchar(25143) en su lugar.
Sección 3, Resumen de la experiencia
1. Algunas personas filtrarán palabras clave como seleccionar, actualizar, eliminar, etc., pero olviden distinguir entre mayúsculas y minúsculas. Puede intentar usar Seleccionar.
2. Cuando no puedas adivinar el nombre del campo, también puedes mirar el formulario de inicio de sesión en el sitio web. Generalmente, por conveniencia, el nombre del campo es el mismo que el del cuadro de entrada del formulario.
3. Nota especial: el signo + en la barra de direcciones se interpreta como un espacio después de pasarse al programa, %2B se interpreta como un signo + y %25 se interpreta como un signo %. Para obtener más información, consulte la introducción relevante de URLEncode.
4. Al inyectar utilizando el método Get, IIS registrará todas las cadenas de envío, pero no el método Post, por lo que puede intentar utilizar la URL de publicación sin Get.
5. Al adivinar Access, solo puede usar el método de decodificación palabra por palabra Ascii. SQLServer también puede usar este método, dependiendo de la diferencia entre los dos, pero si puede exponer el valor juntos. con el mensaje de error de SQLServer Salga, la eficiencia y la precisión mejorarán enormemente.
Métodos de prevención
La vulnerabilidad de la inyección SQL puede describirse como "un dique a miles de kilómetros de distancia, colapsa en un hormiguero". Este tipo de vulnerabilidad es extremadamente común en Internet, generalmente porque el programador no comprende la inyección, o el filtrado del programa no es estricto, o se olvida verificar un determinado parámetro. Aquí les doy una función, en lugar de la función Solicitar en ASP, que puede inyectar Decir NO en todo SQL. La función es la siguiente:
Función SafeRequest(ParaName, ParaType)
-Parámetros de entrada-
ParaName: Nombre del parámetro-Tipo de carácter
ParaType: Tipo de parámetro - tipo numérico (1 indica que los parámetros anteriores son números, 0 indica que los parámetros anteriores son caracteres).
Valor del parámetro difuso
ParaValue = solicitud (ParaName)
Si ParaType=1, entonces
Si no esNumeric(ParaValue), Luego
Response.write "Parameter" & ParaName & "¡debe ser un número!"
Response.End
Terminará si... p >
Otro
ParaValue=replace(ParaValue, "", "")
Terminará si...
Solicitud de seguridad=ParaValue
Finalizar función
El artículo termina aquí. Si eres un oficial de seguridad, un entusiasta de la tecnología o un programador, espero que este artículo pueda ayudarte.