una sqli reales pagina inyeccion injection hacer ejemplos con como atacar excel vba ms-access access-vba sql-injection

excel - sqli - sql injection ejemplos reales



Inyección SQL no web (15)

Si estoy creando una macro en Excel que se conecta a una base de datos de Access, ¿realmente tengo que preocuparme por la inyección de SQL?

Tal vez. Depende, realmente. Personalmente, no me preocuparía, pero ¿qué tipo de datos está tratando de almacenar y cuál es su sensibilidad?

Si son lo suficientemente inteligentes como para hacer una inyección SQL, ¿no son lo suficientemente inteligentes como para descifrar mi contraseña de complemento y simplemente cambiar el código?

Tal vez. El hecho de que alguien pueda hacer una inyección sql no significa que sea lo suficientemente inteligente como para descifrar su contraseña de complemento. Por otro lado, podrían serlo.

Parece haber algo de histeria sobre los ataques de inyección de SQL. Más recientemente, aquí

Cómo devolver el valor en un campo basado en el valor de búsqueda en otro campo

Si estoy creando una macro en Excel que se conecta a una base de datos de Access, ¿realmente tengo que preocuparme por la inyección de SQL? No está en la web, se usa en mi oficina (recuerdan los escritorios, ¿verdad?). No me preocupa que mis compañeros de trabajo me saboteen. Si son lo suficientemente inteligentes como para hacer una inyección SQL, ¿no son lo suficientemente inteligentes como para descifrar mi contraseña de complemento y simplemente cambiar el código?


¿Alguien podría publicar el código de Excel VBA de prueba de contexto para la inyección SQL utilizando una base de datos Jet como back-end? ¿O demostrar exactamente qué parámetros se podrían pasar al código en Cómo devolver el valor en un campo basado en el valor de búsqueda en otro campo que sería dañino (en lugar de simplemente romper el código)?

Dado que Jet no puede ejecutar múltiples sentencias de SQL separadas por ";", estoy teniendo dificultades para concebir cualquier amenaza de inyección SQL con un back-end de Jet. Pero tal vez sea porque no soy tan imaginativo como los hackers.

Ah, una pista gratuita (sobre el tema de peligros distintos a la inyección SQL tradicional):

  1. el servicio de expresión de Access no está disponible a través de ODBC.

  2. está disponible a través de DDE, pero no sé si puede pasar SQL a Access a través de DDE (no he usado DDE con Access en aproximadamente 10 años).

  3. si no sabe nada sobre los servicios de expresión de Access y Jet, probablemente no esté calificado para responder una pregunta sobre Jet (y Access).


Aunque a todos nos gustaría aplicaciones que son invulnerables a todos y cada uno de los ataques, el tiempo necesario para desarrollar toda la protección antibalas debe sopesarse junto con el beneficio adicional. Si razonablemente puede esperar que los requisitos de seguridad no sean muy altos, esto podría ser algo que le gustaría transmitir. Si crees que es algo de lo que potencialmente debes preocuparte, tal vez deberías seguir los pasos para evitar la posibilidad ahora y no tener que preocuparte más.


Como desarrollador, usted es responsable, si no totalmente, al menos en parte, por la seguridad de los datos que posee su aplicación.

Esto es así ya sea que su aplicación esté en línea o solo se use en su oficina. Haga todo lo posible para garantizar que su almacén de datos sea hermético.

Al final del día, no querrás ser el que tenga que explicarle al jefe dónde se han ido las cifras de ventas del año pasado.


Dick, depende de cómo manejes los parámetros. Aquí hay un ejemplo de VBA de cómo no hacer cosas:

Friend Function DeleteAnAccount() As Boolean Const SQL_DELETE_AN_ACCOUNT As String * 50 = _ "DELETE FROM Accounts WHERE account_owner_ID = ''?'';" Dim sql As String sql = Replace$(SQL_DELETE_AN_ACCOUNT, "?", txtAccountOwnerID.Text) m_Connection.Execute sql End Function

Tenga en cuenta que si algunos menean, en lugar de escribir su ID de cuenta en el cuadro de texto (txtAccountOwnerID), realmente escribieron esto:

dummy'' OR ''a'' = ''a

entonces la cadena SQL resultante sería esta:

DELETE FROM Accounts WHERE account_owner_ID = ''dummy'' OR ''a'' = ''a'';

No es bueno porque el predicado ''a'' = ''a'' se resolvería como TRUE y todas las cuentas se eliminarían.

Sería mejor utilizar una declaración preparada utilizando objetos Parameter, por ejemplo, el objeto ADODB.Command.

Jamie.

-


Honestamente, si esta es una aplicación existente de la que estás hablando, no iría a reescribirla. Sin embargo, si lo está desarrollando mientras hablamos, no puedo ver que sea tan difícil usar consultas parametrizadas en lugar de la alternativa.


La seguridad física es siempre la primera línea de defensa en seguridad de datos. Si su aplicación solo se distribuirá dentro de una oficina y los datos a los que se accede no son lo suficientemente valiosos para que alguien se tome la molestia y el costo de robar y descifrar, puede adherirse a un estándar de seguridad inferior al que usaría en un entorno externo. frente a la aplicación web.

Pero, la seguridad real es, en última instancia, lo que puede pasar, no lo que esperamos que suceda. Si su aplicación maneja datos confiados a usted por el público (SSN, números de tarjetas de crédito, etc.) o si es el único repositorio de datos cruciales para su empresa, debe tener en cuenta lo que los usuarios potencialmente maliciosos podrían hacer con su código en el futuro. El empleado feliz de hoy es el sociópata descontento de mañana.

Una buena regla general es preguntarse: si yo, con pleno conocimiento de este producto, quisiera usarlo para dañar a mi compañía, ¿cuánto daño podría hacer? Luego, incorpore suficiente seguridad para reducir ese número a niveles tolerables.


Me gustaría ampliar el comentario que hice anteriormente en respuesta a la publicación de onedaywhen que describe cómo explotar una declaración SELECT en MS Access. Tenga en cuenta que estos no son comentarios generalizados sobre cómo protegerse de la inyección SQL, sino que se aplican específicamente a la programación en MS Access.

Nunca he visto ningún código de ejemplo para Access que permita el tipo de exploit de un SELECT que un día cuando se describe. La razón de esto es que casi nunca hay una situación en la que utilice métodos tan simples para recopilar criterios sin alguna validación de la entrada en algún punto del camino, no para evitar la inyección SQL, sino para evitar errores causados ​​por SQL no válido.

Aquí está el código implementando la versión más simple de esto:

Public Sub TestSQLExploit() Dim strSQL As String strSQL = "SELECT tblInventory.* FROM tblInventory WHERE InventoryID = " strSQL = strSQL & InputBox("Enter InventoryID") Debug.Print strSQL End Sub

Entonces, pasar "10036 o ''a'' = ''a''" produce este SQL:

SELECT tblInventory.* FROM tblInventory WHERE InventoryID=10036 Or ''a''=''a''

¡Y eso definitivamente no es bueno!

Ahora, nunca escribiría mi código de esa manera porque siempre quiero permitir múltiples valores. En cambio, si estuviera usando la función InputBox () para recopilar la entrada del usuario (que honestamente nunca hago, ya que es muy difícil de validar), usaría Application.BuildCriteria para escribir la cláusula WHERE, ya que eso me permitiría manejar valores de criterios múltiples. Eso daría como resultado este código:

Public Sub TestSQLExploit1() Dim strSQL As String Dim strWhere As String strSQL = "SELECT tblInventory.* FROM tblInventory " strWhere = "WHERE " & Application.BuildCriteria("tblInventory.InventoryID", _ dbLong, InputBox("Enter InventoryID")) strSQL = strSQL & strWhere Debug.Print strSQL End Sub

Honestamente, pensé que Application.BuildCriteria arrojaría un error sobre esto, pero no es así, y cuando pasa "10036 o ''a'' = ''a''" produce exactamente el mismo SQL. Y debido a la forma en que funciona el servicio de expresión Jet, estaría muy abierto, como dices.

Ahora, nunca escribo SQL sobre la marcha de esta manera, porque simplemente no me gusta la función InputBox (), precisamente porque tienes que escribir un montón de código para validar la entrada. Y si lo utilizó como el código anterior, tendría que hacer mucho para asegurarse de que fuera válido.

Nunca he visto ejemplos de código de acceso para este tipo de operación que no recomiende el uso de SQL parametrizado (que, por supuesto, evitaría el problema) o una interfaz de consulta por formulario. Por lo general, no uso consultas de parámetros guardados en Access, porque me gusta escribir mis consultas guardadas para que se puedan usar en cualquier lugar. Esto significa que en su mayoría no tienen cláusulas WHERE que tengan criterios que cambien en tiempo de ejecución. Cuando uso estas consultas guardadas, proporciono la cláusula WHERE para la situación adecuada, ya sea como un origen de registro en un formulario o un origen de filas para un cuadro de lista o una lista desplegable.

Ahora, el punto aquí es que no le estoy pidiendo al usuario información en estos casos, sino que extrae los valores de los criterios de los objetos de Access, como un control en un formulario. Ahora, en la mayoría de los casos, esto sería un control en un formulario que tiene un solo propósito: recopilar criterios para alguna forma de filtrado. No habría campos de texto libre no validados en ese formulario: los campos de fecha tendrían máscaras de entrada (lo que restringiría la entrada a fechas válidas) y los campos que tienen un número limitado de valores válidos tendrían tipos de control que restringen las opciones a válidas datos. Por lo general, eso sería algo así como un menú desplegable o un grupo de opciones.

El motivo de este tipo de diseño no es necesariamente evitar la inyección de SQL (aunque lo evitará), sino asegurarse de que el usuario no se sienta frustrado al ingresar criterios que no son válidos y no producirán ningún resultado.

Ahora, la otra consideración es que algunas veces querrá usar algunos campos de texto plano para que el usuario pueda ingresar cierto tipo de datos que no están restringidos (como buscar nombres). Solo mirando algunas de mis aplicaciones que tienen rutinas de búsqueda de nombres con campos de texto no validados, me parece que estoy bien, porque no uso BuildCriteria en esos casos, ya que está diseñado para recopilar solo un criterio a la vez (aunque el el usuario puede ingresar "*" para recuperar múltiples registros).

Si tengo un cuadro de texto donde el usuario ingresa "fent * or ''a'' = ''a''", y lo uso en una cláusula WHERE:

WHERE tblDonor.LName Like "fent* or ''a'' = ''a''"

El resultado es que no se encuentra nada. Si el usuario ingresó "fent * or a = a", aún no funcionará, porque es un campo de texto y estoy usando comillas dobles alrededor de él. Si el usuario ingresó:

fent* or "a" = "a"

eso también se romperá, porque cuando mi código ponga comillas dobles, la cláusula WHERE no será válida.

Ahora, con el caso de simplemente usar entrada y poner comillas dobles alrededor de ella, está claro que ingresando esto:

" Or "fent*" or "a" = "a" Or "

daría como resultado:

WHERE tblDonor.LName Like "" Or "fent*" or "a" = "a" Or ""

y eso sería muy malo, ya que devolvería todo. Pero en mis aplicaciones existentes, ya estoy borrando las comillas dobles de la entrada del usuario (ya que las comillas dobles son teóricamente válidas dentro del campo LName), por lo que mis aplicaciones construyen esta cláusula WHERE:

WHERE tblDonor.LName Like "? Or ?fent*? or ?a? = ?a? Or ?*"

Eso no devolverá ninguna fila.

Pero la razón por la que no es porque estaba tratando de evitar la inyección de SQL, sino porque quiero que el usuario pueda buscar nombres que tengan comillas dobles incrustadas en ellos.

======

Algunas conclusiones:

  1. nunca acepte entradas de forma libre de los usuarios al filtrar datos; en su lugar, use controles que validen previamente la entrada (por ejemplo, cuadros de texto con máscaras de entrada, listas desplegables, grupos de opciones) y limítelos a valores que sepa que son válidos.

  2. al aceptar datos de un cuadro de texto sin restricciones, evite Application.BuildCriteria, que procesará la entrada de tal forma que el usuario pueda engañar a su aplicación para que devuelva todas las filas (aunque ese es el alcance de lo que podría hacer el exploit).

Lo que esto significa en la práctica es que si desea recopilar criterios múltiples, debe hacerlo de forma que el usuario solo pueda elegir entre los valores preseleccionados. La forma más sencilla de hacerlo es con un cuadro de lista multiselect (o un par de ellos con ADD >> y << REMOVE buttons buttons between).

Por supuesto, si necesita o no preocuparse por este tipo de exploits SELECT depende de la importancia y el nivel de privacidad de los datos que se recuperan, y de lo que se devuelve exactamente al usuario. Puede no ser un problema arriesgarse a devolver todas las filas de datos no confidenciales al presentar los datos en forma no editable (por ejemplo, un informe), mientras que podría ser problemático si lo presentara en forma editable y alguien cambiara datos que no deberían t ser editado

Pero con datos no confidenciales, a menudo simplemente no importa si el usuario obtiene demasiados datos devueltos (excepto por problemas de rendimiento, por ejemplo, sobrecarga de un servidor, pero eso se maneja mejor de otras maneras).

Entonces, mi punto a seguir en todo esto:

  1. nunca use InputBox () para recopilar criterios (este ya lo evito).

  2. use siempre los tipos de control más restrictivos posibles para recopilar critiria (esto ya es algo que hago regularmente).

  3. si utiliza un cuadro de texto para recopilar datos de cadena, trátelo como un único criterio independientemente de lo que haya introducido el usuario.

Esto significa que tengo algunas aplicaciones donde un usuario puede ingresar "O ''a'' = ''a''" junto con un criterio válido y devolver todas las filas, pero en esas aplicaciones, esto simplemente no es un problema, ya que los datos no es sensible

Pero es un buen recordatorio para mí de no ser complaciente. Creí que Application.BuildCriteria me protegería, pero ahora me doy cuenta de que el servicio de expresión Jet es demasiado indulgente con lo que acepta en una cláusula WHERE.

2009/12/08 EDIT: acabo de encontrar estos enlaces en SQL Injection en MS Access. Todos estos están destinados a la inyección web, por lo que no son directamente aplicables a una discusión de inyección SQL no Web (muchos de ellos serían una pérdida de tiempo en el acceso interactivo, ya que usted tiene acceso a mucha información bruta). forzado, por ejemplo, información sobre el sistema de archivos, rutas, ejecutables, etc.), pero muchas de las técnicas también funcionarían en una aplicación de Access. Además, la ejecución desde Access abre una gran cantidad de funciones que no serían ejecutables desde ODBC / OLEDB. Comida para el pensamiento.


No. (Sí). Sí. :)

A menudo, veo a los desarrolladores desperdiciando recursos preciosos en fortificar la "puerta de entrada", solo para no notar la puerta de la pantalla que se balancea en la parte posterior. Esto suele ser algo así como fortalecer una interfaz para un backend inseguro, fortaleciendo una aplicación que está básicamente abierta a usuarios variados, etc.

Está muy bien hacer una declaración general sobre la seguridad, pero debe coincidir con los requisitos.


OMI, si su sistema estará expuesto a personas que deseen causar daños (por ejemplo, en Internet), entonces debería protegerse contra la inyección de SQL.

Por otro lado, si se trata de un sistema interno, donde cualquier usuario malintencionado que podría acceder a la inyección SQL también podría dañarlo de otras formas, entonces realmente no es tan importante.

He escrito el código yo mismo, que es vulnerable a la inyección de SQL, pero las únicas personas con ese tipo de acceso son compañeros de trabajo con acceso SQL de todos modos.


Si está creando SQL en su macro, es vulnerable a la inyección de SQL. Incluso si confía en las personas que utilizarán el dispositivo, al menos debe tener en cuenta los aspectos básicos, como las personas que intentan insertar caracteres de coma única y punto y coma en los campos de la base de datos. esto no es tanto un problema de seguridad en su caso como solo una validación de datos.


Tres puntos:

  1. El uso de consultas parametrizadas generalmente es menos trabajoso que escaparse de posibles formas de romper su SQL (Sr. O''Neill, por ejemplo) para que pueda concatenar los datos en la cadena de consulta directamente. Si la opción más robusta también es menos trabajo de implementar, entonces ¿por qué no quieres hacerlo?

  2. No he usado Jet por años, así que no sé si es compatible con las declaraciones preparadas actualmente o no, pero si va a ejecutar la declaración más de una vez, usará una consulta parametrizada y volverá a ejecutarla con diferentes parámetros será más rápido que generar nuevas consultas cada vez.

  3. Incluso si todos los usuarios son 100% confiables y nunca se ofuscan lo suficiente como para intentar causar ningún daño, siempre existe la posibilidad de errores tipográficos u otros errores genuinos. Proteger contra el error del usuario generalmente se considera una buena cosa.

Por lo tanto, debe utilizar las consultas parametrizadas, como se muestra en la respuesta de Spolsky a la otra pregunta, incluso si no por seguridad. No solo son más seguros, también son más resistentes a errores, a menudo más rápidos de escribir y tienen un mayor rendimiento para consultas repetidas.


nunca se sabe cuándo bobby tables usará su palabra macro:


> usar una consulta parametrizada y volver a ejecutarla con diferentes parámetros será más rápido que crear nuevas consultas cada vez.

En realidad, no mejorará el rendimiento en jet si habla del rendimiento de las consultas. De hecho, del documento técnico de JET "Descripción general del rendimiento y técnicas de optimización", obtenemos esta joya:

página 18

Dado que las consultas almacenadas tienen un plan de consulta precompilado, las consultas parametrizadas que contienen parámetros en columnas indexadas pueden no ejecutarse de manera eficiente. Dado que el motor de consulta no conoce los valores que se pasarán en un parámetro de antemano, solo puede adivinar el plan de consulta más eficiente. En función de los escenarios de rendimiento del cliente que hemos examinado, hemos descubierto que, en algunos casos, se pueden lograr mejoras sustanciales en el rendimiento mediante la sustitución de una consulta parametrizada almacenada por una consulta temporal. Esto significa crear la cadena SQL en el código y pasarla a los métodos DAO OpenRecordset o Execute del objeto Database

Neat-o eh? ¡Y he experimentado lo de arriba!

Tenga en cuenta que el tiempo de compilación para un plan de consulta está en los 1000 segundos de todos modos. Quiero decir, realmente, el tiempo del plan de consulta va de .01 a .0001. Claro que es 100 veces más rápido, pero eso solo nos está ahorrando una centésima de segundo en total. Estamos ejecutando un informe que demora 2 segundos para que el tiempo del plan de consulta ni siquiera sea una preocupación.

Tenemos GOBS de procesamiento hoy. Son las unidades de disco, la memoria y las velocidades de E / S de red que son los cuellos de botella. Tampoco tenemos el problema de perder el caché de consultas de sql del servidor para cada nueva cadena sql enviada a JET. Esos planes de consultas sql en línea no se almacenan en caché de todos modos. Y, MÁS importante, JET es un motor basado en el cliente, por lo que cuando tiene 10 usuarios en su oficina, tiene 10 copias de JET en ejecución local en cada máquina. La caché del plan de consulta no es un problema como para el servidor sql.

Como se muestra en el documento de referencia anterior (y en mi experiencia), los beneficios de un mejor plan de consulta al obligar a volver a compilar ese sql sin parámetros supera los beneficios de tener un plan de consulta pre-cumplido con parámetros.

Sin embargo, para mantenerse en el camino, tiene que estar de acuerdo con David. No creo que cuando usas odbc, o en este caso el modelo de objeto dao + jet, no pueda crear CUALQUIER FORMA para inyectar una declaración real de SQL.

Uno puede quizás con el ejemplo de InputBox () "cojo" anterior ingresar condiciones que pueden producir resultados inesperados. Como se señaló, las aplicaciones integradas en el acceso no funcionan de esta manera muy a menudo.

Para cosas como eliminar un registro, está viendo un formulario y tendrá una barra de menú personalizada (o ahora cinta), o simplemente un botón de eliminar ubicado en el formulario. Por lo tanto, el usuario no puede ingresar datos incorrectos para este tipo de código de eliminación.

MÁS importante cuando a menudo aceptamos la entrada de los usuarios en los formularios, tenga en cuenta que nuestros formularios tienen máscaras de datos incorporadas. Después de todo esto, es para lo que se diseñó el acceso a MS. Por lo tanto, si estamos pidiendo un número de teléfono, el usuario no puede ingresar letras o incluso ninguna carta no numérica para esa máscara de entrada. Esa máscara incluso colocará () y - en los lugares apropiados en ese número de teléfono para mostrar, pero solo los números entrarán en la entrada real del usuario.

Para la mayoría de los otros tipos de solicitudes, usamos cuadros combinados, lisbolas y otros elementos de la interfaz de usuario que nuevamente limitan la capacidad del usuario para inyectar algo diferente de lo que ese formulario permite en ese cuadro de texto.

Debido a un número tan elevado de enmascaramiento y capacidades de entrada que están más allá de la mayoría de los creadores de pantallas, la inyección es un tema poco común para las aplicaciones basadas en el acceso a MS.

Si alguien puede mostrar un ejemplo de JET en el que el usuario puede ejecutar una declaración SQL por inyección, soy todo oídos, ya que no creo que sea posible con dao + jet.

Para las aplicaciones de acceso a MS, podría ser posible, pero una vez más, en la práctica real, es muy difícil.


SQL Injection no es solo una amenaza a la seguridad, también es una fuente real de errores.

¿Estás seguro de que ninguno de tus registros tendrá un apostophe ('') en ellos?

INSERT INTO NAMES (FIRSTNAME, LASTNAME) VALUES(''Jack'', ''O''Neill'')

En este caso, tienes un error a pesar de que nadie quería descifrar tu sistema.