¿Qué es la inyección SQL y cómo implementarla?
Encontré uno, espero que pueda ayudarte.
Con el desarrollo del desarrollo de aplicaciones en modo B/S, cada vez más programadores utilizan este modo para escribir aplicaciones. Sin embargo, debido al bajo umbral de entrada para esta industria y al nivel y experiencia desiguales de los programadores, un número considerable de programadores no juzgan la legalidad de los datos ingresados por el usuario al escribir código, lo que genera riesgos de seguridad en las aplicaciones. El usuario puede enviar un código de consulta a la base de datos y obtener algunos datos que desea conocer en función de los resultados devueltos por el programa. Esta es la llamada inyección SQL, es decir, inyección SQL.
Se accede a la inyección SQL desde el puerto WWW normal y, en la superficie, no se ve diferente del acceso a una página web normal, por lo que actualmente los cortafuegos del mercado no emitirán una alerta por inyección SQL.
, si el administrador no tiene la costumbre de comprobar los registros de IIS, es posible que la intrusión no se note durante mucho tiempo.
Sin embargo, el método de inyección SQL es bastante flexible y se encontrarán muchas situaciones inesperadas durante la inyección. La diferencia fundamental entre un experto y un "novato" es si puede analizar la situación específica y construir declaraciones SQL inteligentes para obtener con éxito los datos deseados.
Según las condiciones nacionales, más del 70% de los sitios web nacionales utilizan ASP+Access o SQLServer, PHP+MySQ representa el 20% y otros utilizan menos del 10%. En este artículo, explicaremos los métodos y técnicas de inyección de ASP desde básico hasta avanzado y avanzado. El artículo sobre inyección de PHP fue escrito por zwell, otro amigo de NB Alliance. Espero que sea útil tanto para los trabajadores de seguridad como para los programadores. . Amigos que entienden la inyección de ASP, no se salten el capítulo introductorio, porque algunas personas todavía tienen malentendidos sobre el método básico de inyección. ¿Estás listo? Vamos...
Comenzando
Si nunca antes ha probado la inyección SQL, entonces el primer paso es configurar el menú IE => Herramientas => Opciones de Internet => Avanzado = >Desmarque la casilla frente a Mostrar 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 se podrá obtener más información rápida.
Sección 1, Principios de inyección SQL
A continuación partimos de un sitio web www.mytest.com (Nota: Se obtuvo el consentimiento del webmaster del sitio web antes de publicar este artículo. La mayoría son datos reales).
En la página de inicio del sitio web, hay un enlace llamado "Muchas soluciones al problema de que IE no puede abrir una nueva ventana". La dirección es: /showdetail.asp?id=49. comillas simples después de esta 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 consulta. expresión 'ID=49''.
/showdetail.asp, línea 8
Podemos ver los siguientes puntos en este mensaje de error:
1. El sitio web utiliza una base de datos de Access. El motor se conecta a la base de datos en lugar de a través de ODBC.
2. El programa no determina si los datos enviados por el cliente cumplen con los requisitos del programa.
3. La tabla consultada por esta declaración SQL tiene un campo llamado ID.
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 y obtener la información que desea.
Sección 2: Determinar si se puede realizar la inyección SQL
Después de leer la primera sección, algunas personas pensarán: A menudo pruebo si la inyección SQL se puede realizar de esta manera. no muy simple?
En realidad, este no es el mejor método. ¿Por qué?
En primer lugar, no todos los IIS del servidor devolverán 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 se informará un error y la información del mensaje específico es que hubo un error en el servidor al procesar la URL. Comuníquese con el administrador de su sistema.
En segundo lugar, algunos programadores que tienen un poco de conocimiento sobre inyección SQL piensan que es seguro siempre que
filtre las comillas simples. Este no es el caso de la minoría. usas comillas simples La prueba de comillas no puede 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=49 ;y 1=2
Este es el método de prueba clásico 1=1, 1=2 ¿Cómo juzgar? Simplemente mire los resultados devueltos por las tres URL anteriores:
Síntomas que se pueden inyectar:
① Visualización normal (esto es inevitable; de lo contrario, habrá un error en el programa)
p>
② Visualización normal, el contenido es básicamente el mismo que ①
③ Solicitar BOF o EOF (cuando el programa no hace ningún juicio), o solicitar que el no se puede encontrar el registro (cuando se juzga rs.eof), o el contenido de la pantalla está vacío (el programa lo agregó en el resumen de error a continuación)
Es más fácil juzgar si se puede inyectar ①. También se muestran normalmente, ② y ③ generalmente tienen mensajes de error definidos por el programa o tipos de mensajes. Se produjo un error durante la conversión.
Por supuesto, este es solo un método de juicio que se utiliza cuando el parámetro entrante es de tipo numérico. En la aplicación real, habrá parámetros de tipo de carácter y de tipo de búsqueda. Explicaré esto en los "Pasos generales de". Inyección SQL" en el capítulo intermedio. Hacer análisis.
Sección 3, Determinación del tipo de base de datos y método de inyección
Las diferentes bases de datos tienen diferentes funciones y métodos de inyección, por lo que antes de inyectar, debemos juzgar 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 consigues que el programa te diga qué base de datos utiliza? Echemos un vistazo:
SQLServer tiene algunas variables del sistema. Si el indicador de IIS del servidor no está cerrado y SQLServer devuelve un mensaje de error, se puede obtener directamente del mensaje de error. /p>
/ showdetail.asp?id=49 ;and user>0
Esta declaración es muy simple, pero contiene la esencia del método de inyección único de SQLServer. Yo mismo también lo encontré extremadamente eficiente. en una prueba no intencionada. Permítanme ver su significado: en primer lugar, la declaración anterior es normal, el foco es usuario>0, sabemos que el usuario es una variable incorporada de SQL Server, su valor es el nombre de usuario del actual conexión, el tipo es nvarchar . Compare un valor nvarchar con un valor int de 0. El sistema primero intentará convertir el valor nvarchar en un tipo int. Por supuesto, definitivamente ocurrirá un error durante el proceso de conversión. El mensaje de error de SQL Server es: Convertir nvarch <. /p>
Se produjo un error de sintaxis al convertir el valor ar "abc" a una columna cuyo tipo de datos es int Jaja, abc es el valor de la variable usuario. obtenido sin ningún esfuerzo. En las páginas siguientes, verá muchas declaraciones que utilizan este método.
Por cierto, como todos sabemos, el usuario sa de SQL Server tiene los mismos permisos que los Administradores. Si obtiene permisos sa, es casi seguro que podrá obtener el Administrador del host. El método anterior puede probar fácilmente si está iniciando sesión con sa. Cabe señalar que si inicia sesión con sa, el mensaje es un error al convertir "dbo" en una columna int, no "sa".
Si el servidor IIS no permite devolver mensajes de error, ¿cómo determinar el tipo de base de datos? Podemos comenzar con las diferencias entre Access y SQLServer. Ambos Access y SQLServer tienen sus propias tablas del sistema, como tablas que almacenan todos los objetos en la base de datos. Access está en la tabla del sistema [msysobjects], pero al leer esta tabla en una Web. En el entorno web, aparecerá el mensaje "Sin permiso". SQL Server está en la tabla [sysobjects] y se puede leer normalmente en el entorno web.
Después de confirmar que se puede inyectar, use la siguiente declaración:
/showdetail.asp?id=49 ;and (select count(*) from sysobjects)>0 p>
p>
/showdetail.asp?id=49 ;y (seleccione count(*) de msysobjects)>0
Si la base de datos es SQLServer, entonces la página de la primera La URL es la misma que la página original /showdetail .asp?id= 49 es aproximadamente la misma; y la segunda URL, debido a que no se puede encontrar la tabla msysobjects, generará un error. Incluso si el programa tiene un procesamiento de tolerancia a fallas, la página. es completamente diferente de la página original.
Si la base de datos usa Access, entonces la situación es diferente. La página de la primera URL es completamente diferente de la segunda URL depende de si la configuración de la base de datos permite la lectura de la tabla del sistema. Hablando, no está permitido, por lo que es completamente diferente de la URL 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 cuando se activan los mensajes de error de IIS.
Capítulo avanzado
En el capítulo introductorio, aprendimos cómo juzgar la inyección SQL, pero está lejos de ser suficiente para obtener el contenido confidencial del sitio web. A continuación, continuaremos aprendiendo cómo obtener el contenido que queremos de la base de datos. Primero, veamos los pasos generales de la inyección SQL:
Sección 1. Pasos generales de la inyección SQL
<. p> Primero, determine el entorno, encuentre el punto de inyección y determine el tipo de base de datos. Esto se discutió en el capítulo introductorio.En segundo lugar, según el tipo de parámetro de inyección, 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:
son numéricos. La declaración SQL original es aproximadamente la siguiente:
Seleccione * del nombre de la tabla donde campo=49 <. /p>
El parámetro inyectado es ID=49 Y [condición de consulta], es decir, genera una declaración:
Seleccione * del nombre de la tabla donde campo=49 Y [condición de consulta]
(B) Clase=parámetros inyectados en serie Es un tipo de carácter. La apariencia original de la declaración SQL es aproximadamente la siguiente:
Seleccione * del nombre de la tabla donde campo='Serie' <. /p>
Los parámetros inyectados son Class=Series' y [condición de consulta] y ''=' , es decir, generan una declaración:
Seleccione * del nombre de la tabla donde campo ='series' y [condición de consulta] y ''='' No hay ningún parámetro de filtro al realizar 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 donde campo como '%keyword%'
Los parámetros inyectados son palabra clave=' y [condición de consulta] y '%25'=', es decir, genera la declaración:
Seleccionar * del nombre de la tabla donde campos como '%' y [condición de consulta] y '%'='%'
Luego, reemplace las condiciones de consulta con declaraciones SQL y adivine el nombre de la tabla, por ejemplo: p>
ID=49 y (Seleccione Count(*) de Admin)>=0
Si la página es la misma que ID=49 es la misma, lo que indica que la condición adicional es verdadera, es decir, la tabla Admin existe; de lo contrario, no existe (tenga en cuenta este método). Este ciclo continúa hasta que se adivina el nombre de la tabla.
Después de adivinar el nombre de la tabla, reemplace Count(*) con Count(nombre del campo) y use el mismo principio para adivinar el nombre del campo.
Algunas personas dirán: Hay algunos elementos accidentales aquí. Si el nombre de la mesa es muy complicado e irregular, entonces no hay necesidad de jugar. Tienes razón. No existe una tecnología de piratería 100% exitosa en este mundo. La mosca no muerde el huevo sin costuras. No importa cuán hábil o avanzado sea el hacker, todo se debe a que los programas de otras personas no están escritos con rigor o la conciencia del usuario. de confidencialidad no es suficiente, sólo así podremos empezar.
Esto está un poco fuera de tema. Dicho esto, para la biblioteca de SQL Server, todavía hay una manera de permitir que el programa nos diga el nombre de la tabla y el nombre del campo. Lo presentaremos en el capítulo avanzado. .
Finalmente, después de adivinar con éxito el nombre de la tabla y el nombre de la columna, use declaraciones SQL para obtener los valores del campo. A continuación se presenta uno de los métodos más utilizados: el método de decodificación palabra por palabra en Ascii. este método es muy rápido. Lento pero seguro es el camino a seguir.
Tomemos un ejemplo. Se sabe que el campo de nombre de usuario existe en la tabla Admin. Primero, tomamos el primer registro y probamos la 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 nombre de usuario del 1 superior es mayor que 0, entonces se establece la condición, entonces >1; , >2, >3 se probarán así, hasta que no se establezca la condición, por ejemplo, >7 es verdadero, >8 no es verdadero, es decir, len(nombre de usuario)=8
Por supuesto Nadie será tan estúpido como para probar desde 0,1,2,3 uno por uno, ¿qué tal? Dependerá de cada uno ver cómo se desempeñan con relativa rapidez.
Después de obtener la longitud del nombre de usuario, use mid(username,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 (select top 1 asc(mid(username,1,1)) from Admin)>0
También utiliza el método de reducir gradualmente el rango para obtener el código ASCII del primer carácter Tenga en cuenta que el código inglés y ASCII del número está entre 1-128. Puede utilizar el método de reducción a la mitad para acelerar la adivinación. Si lo escribe como un programa de prueba, la eficiencia mejorará enormemente.
Sección 2. Funciones comúnmente utilizadas para la inyección SQL
Las personas con un conocimiento básico del lenguaje SQL tienen una tasa de éxito mucho mayor en la inyección SQL que las personas que no están familiarizadas con él. Necesitamos mejorar nuestro nivel de SQL, especialmente algunas funciones y comandos de uso común.
Acceso: asc (carácter) SQLServer: unicode (carácter)
Función: Devolver el código ASCII de un determinado carácter
Acceso: chr (número) SQLServer : nchar (Número)
Función: Al contrario de asc, devuelve caracteres según el código ASCII
Acceso: mid (string, N, L) SQLServer: substring (string, N, L) )
Función: Devuelve una subcadena de longitud L a partir de N caracteres, es decir, una cadena entre N y N+L
Acceso: abc (número) SQLServer :abc (número )
Función: Devuelve el valor absoluto del número (usado al adivinar caracteres chinos)
Acceso: A entre B y C SQLServer: A entre B y C
Función:
Juzgar si A está entre B y C
Sección 3, método de procesamiento chino
Inyección Es común encontrar caracteres chinos en Internet Algunas personas quieren retirarse tan pronto como se encuentran con caracteres chinos. De hecho, siempre que comprenda algo de codificación china, la "fobia a los chinos" se puede superar rápidamente.
Primero hablemos de algo de sentido común:
En Access, el código ASCII chino puede tener un número negativo. Después de eliminar el número negativo, use abs() para obtener el absoluto. valor 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, no puede usar la función ascii() para obtener el código ASCII. Debe usar la función unicode. () para devolver el valor Unicode y luego usar nchar La función obtiene los caracteres chinos correspondientes.
Después de comprender los dos puntos anteriores, ¿crees que las adivinanzas en chino son realmente similares a las del inglés? Excepto que debe prestar atención a las funciones utilizadas y el rango de conjetura es mayor, los métodos no son diferentes.
Capítulo avanzado
Después de leer los capítulos introductorio y avanzado, con un poco de práctica, no será un problema descifrar sitios web comunes. Pero si no se pueden adivinar el nombre de la tabla y el nombre de la columna, o si el autor del programa filtra 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 de SQL Server
SQL Server es un sistema de base de datos poderoso y está estrechamente relacionado con el sistema operativo, lo que trae muchos problemas a los desarrolladores. Gran comodidad, pero por otro lado, también proporciona un trampolín para los inyectores. Echemos un vistazo a algunos ejemplos específicos:
① nombre de usuario contraseña /add” --
② administradores de nombres de grupo local /add”--
Agregue el nombre de la cuenta recién creada al grupo de administradores. ¡En menos de dos minutos, ha obtenido 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 hay permiso para llamar a xp_cmdshell.
③ pub\wwwroot\1.db';--
Este es un truco muy cruel El nombre de la base de datos obtenido de ③ y algunos errores de IIS expuestos La ruta absoluta, copia de seguridad. la base de datos al directorio web y luego use HTTP para descargar toda la base de datos por completo. ¡Todos los administradores y contraseñas de usuario se pueden ver 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://Site/url.asp?id=1 ;y (Seleccione el nombre principal 1 de sysobjects donde xtype='U' y status>0)>0
Como se mencionó anteriormente, sysobjects es la tabla del sistema de SQL Server, que almacena todos los nombres de tablas, vistas, restricciones y otros objetos. xtype = 'U' y status>0 indican el nombre de la tabla creada por el usuario. la primera tabla Saque el nombre, compare el tamaño con 0 y deje que el mensaje de error exponga el nombre de la tabla. ¿Cómo obtener los nombres de la segunda y tercera tabla? Pensemos en ello los lectores inteligentes.
⑥ http://Site/url.asp?id=1 ;y (Seleccione los 1 principales col_name(object_id('nombre de tabla'),1) de sysobjects)>0
Después de obtener el nombre de la tabla de ⑤, use object_id ('nombre de la tabla') para obtener el ID interno correspondiente al nombre de la tabla. col_name (ID del nombre de la tabla, 1) representa el primer nombre de campo de la tabla, reemplace 1 con 2. 3,4...Puedes obtener los nombres de los campos en la tabla adivinada uno por uno.
Los 6 puntos anteriores son el fruto de mi investigación sobre la inyección de SQL Server durante más de medio año. Se puede ver que el grado de comprensión de SQL Server afecta directamente la tasa de éxito y la velocidad de adivinación. Después de estudiar 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 capítulo introductorio, a muchas personas les gusta usar "números" para probar las vulnerabilidades de inyección, por lo que muchas personas también usan filtrado. Los métodos 'números' para "prevenir" las vulnerabilidades de inyección pueden bloquear los ataques de algunos principiantes, pero las personas que están más familiarizadas con la inyección SQL aún pueden usar funciones relacionadas para evitar las restricciones del programa.
En la sección "Pasos generales de la inyección SQL", las declaraciones que utilicé fueron optimizadas por mí para que no contengan comillas simples en "Uso de tablas del sistema para inyectar en la base de datos SQLServer". Algunas declaraciones contienen; un signo '. Tomemos un ejemplo para ver cómo transformar estas declaraciones:
Un ejemplo simple es donde xtype='U' El código ASCII correspondiente al carácter U es 85, por lo que puedes usar donde. xtype=char(85) en su lugar; si el carácter es chino, 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 y Eliminar, pero se olvidan de distinguir entre mayúsculas y minúsculas, así que puedes probarlo con seleccioneT.
2. Cuando no pueda adivinar el nombre del campo, también puede consultar el formulario de inicio de sesión en el sitio web. Generalmente, para mayor comodidad, los nombres de los campos son los mismos que los cuadros de entrada del formulario. .
3. Atención especial: el signo + en la barra de direcciones se interpreta como un espacio después de pasar 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 usando el método Get, IIS registrará todas las cadenas de envío, pero no las registrará cuando use el método Post, así que trate de no usar Get para URL que puedan usar Post.
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. Solo necesita la diferencia entre los dos. mensaje de SQLServer a Si se expone el valor, la eficiencia y precisión mejorarán enormemente.
Métodos de precaución
Se puede decir que las vulnerabilidades de inyección SQL son "un dique de miles de millas, pero colapsan en un hormiguero". Este tipo de vulnerabilidad es extremadamente común en Internet. , generalmente porque los programadores no entienden 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 que reemplaza la función Solicitar en ASP y puede inyectar Decir NO en todo SQL. La función es la siguiente:
Función SafeRequest(ParaName,ParaType)
. ' --- Parámetros entrantes ---
'ParaName: Nombre del parámetro - tipo de carácter
'ParaType: Tipo de parámetro - tipo numérico (1 significa que los parámetros anteriores son números, 0 significa Los parámetros anteriores son caracteres)
Dim ParaValue
ParaValue=Request(ParaName)
Si ParaType=1 entonces
Si no es Numeric( ParaValue ) luego
Response.write "Parámetro" & ParaName & "¡Debe ser numérico!"
Response.end
Fin si
De lo contrario
ParaValue=replace(ParaValue,"'","''")
Finalizar si
SafeRequest=ParaValue
Función final