Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   La Taberna (https://www.clubdelphi.com/foros/forumdisplay.php?f=40)
-   -   Aprendiendo de los errores de otros en BDs (https://www.clubdelphi.com/foros/showthread.php?t=78374)

AzidRain 12-04-2012 22:14:32

Aprendiendo de los errores de otros en BDs
 
Me econtre este sitio muy bueno que trata sobre diferentes estrategias para prevenir la inyección de código SQL en nuestras aplicaciones y me puse a pensar en varios ejemplos que he visto de desarrollos de mis colegas cordobeses en donde tal vez por comodidad practicamente se puede hacer de todo. He visto muchos casos donde por ejemplo en un soft de gestión, para buscar un producto por nombre le piden al usuario que escriba un "%" como comodín si no se sabe el nombre completo. En otros casos me encontré con una Forma que tenia un TMemoEdit para escribir supuestamente "comandos" definidos por el desarrollador del software quien coloco unos botones que al presionarlos simplemente escribian el código a ejecutar. De manera que tranquilamente podiamos ponernos a escribir cualquier comando SQL válido y su programa lo ejecutaba!!

Pero bueno, a todos en algún momento nos ha pasado.

Casimiro Notevi 13-04-2012 00:01:41

Conozco más de un programa que hace eso, pero claro, lo han pedido los clientes :)

roman 13-04-2012 00:18:50

Cita:

Empezado por AzidRain (Mensaje 429909)
para buscar un producto por nombre le piden al usuario que escriba un "%" como comodín si no se sabe el nombre completo.

A ver, quiero aprender. Yo hago esto que dices en una aplicación Delphi con MySQL. ¿Cuál sería el problema?.

Estrictamente hablando, esta es la consulta:

Código SQL [-]
select * from tabla where nombre like :valor

y sustituyo el parámetro con lo que escriba el usuario.

// Saludos

AzidRain 13-04-2012 01:57:19

la consulta es válida, pero si ya sabes que te pueden poner eso que mencionas simplemente quitas los % de la entrada del usuario y no haces un like asi tan directo.

roman 13-04-2012 02:39:21

¡Pero no me has explicado nada! ¿Cuál es el peligro de esa consulta así de directa? Y, se lo diga o no, el usuario puede poner sus %.

// Saludos

AzidRain 13-04-2012 02:45:24

El "%" le funcionara solo si tu consulta es un LIKE como pusiste, si es una igualdad (al menos en MySQL que es lo que trabajo todos los días) simplemente no hará nada.

roman 13-04-2012 16:15:31

Bueno, eso lo entiendo. Lo que no entiendo es qué tiene que ver con inyección de código SQL, que es el tema que pusiste sobe la mesa. Si hay algún peligro potencial, sería bueno saberlo.

// Saludos

mamcx 13-04-2012 17:54:45

EL usar parámetros elimina la inyección de sql roman. Es una de las medidas a tomar.

roman 13-04-2012 18:11:15

De acuerdo Mario, de hecho, siempre uso parámetros tan sólo por legibilidad y organización del código. Pero, vamos a suponer que no los uso. Sigue sin quedarme claro cuál es el peligro potencial del comodín. Entiendo otro tipo de peligros como el de aceptar que el usuario escriba apóstrofos, pero no veo qué sucede con el %.

// Saludos

mamcx 13-04-2012 18:18:49

El problema del comodin es solo si el codigo es vulnerable a injeccion.

Al usar parametros, este se "escapa". Es como con las URL. Si envias "un/ejemplo" directo, se entiende como una subcarpeta. Pero si se escapa es "un%2Fejemplo". Es el mismo principio: Al usar parametros, la BD "escapa" los caracteres potencialmente peligrosos, ergo, no hay peligro de injeccion.

AzidRain 13-04-2012 18:22:26

Yo creo que este sitio puede servir también como referencia, habla de la inyección de código y de parametrización pero trae mas ejemplos

roman 13-04-2012 18:24:41

Cita:

Empezado por mamcx
El problema del comodin es solo si el codigo es vulnerable a injeccion.

Al usar parametros, este se "escapa". Es como con las URL. Si envias "un/ejemplo" directo, se entiende como una subcarpeta. Pero si se escapa es "un%2Fejemplo". Es el mismo principio: Al usar parametros, la BD "escapa" los caracteres potencialmente peligrosos, ergo, no hay peligro de injeccion.

¡Ah! Pero eso no es así. No al menos en el caso de MySQL. Me refiero a que el caracter % pasa tal cual, sin escaparse, al momento de sustituir el parámetro. De lo contrario no serviría realmente como comodín. Y juraría que es igual con otras bases de datos.

// Saludos

gmontes 13-04-2012 20:35:03

me quede con las ganas de ver los ejemplos de AzidRain con lo que ha visto en los desarrollos de sus colegas cordobeses. para ver si caigo en alguno de esos casos

AzidRain 13-04-2012 22:26:07

gmontes, Todos hemos caído en algún momento en alguna mala práctica o error de diseño, lo imporante es darse cuenta y no repetirlos. Aunque claro, siempre hay quien mantiene sus prácticas por comodidad pues muchas veces es más fácil hacer las cosas como caiga que buscarle patas por todos lados con tal de entregar algo bien. De ahi que son tan importantes las pruebas y que quien las realice vaya con toda la intención de hacer fallar tu programa.

roman 13-04-2012 22:32:00

Pues yo sigo sin ver cuál es el problema con el comodín. ¿De verdad tienes alguna idea al respecto o lo soltaste así nada más?

// Saludos

mamcx 14-04-2012 18:21:23

Cita:

Empezado por roman (Mensaje 429966)
¡Ah! Pero eso no es así. No al menos en el caso de MySQL. Me refiero a que el caracter % pasa tal cual, sin escaparse, al momento de sustituir el parámetro. De lo contrario no serviría realmente como comodín. Y juraría que es igual con otras bases de datos.

// Saludos

El caracter % hace parte del estandar SQL para consultas LIKE. No tiene nada de malo en general, excepto que se puede usar pa una injeccion, pero NUNCA en el caso de usar parametros.

Tener "%algo" no es ningun problema.

Delphius 14-04-2012 19:19:27

Hola,
¿Azidrain podrías no ser tan esquivo y secote al explicar? A como se ha venido dando el hilo me da la impresión de que tiraste un tema muy de forma airosa, y ahora no le sabes como escapartele. Te agradecería que destines tiempo en elaborar una respuesta lo más clara, en lo técnica y operativamente posible que ilustre los peligros de esos tipos de consultas, y brindando información más objetiva de donde podamos aprender.
Creo que de ese modo los demás podríamos aprender más.

Yo algo de injección SQL he escuchado, leído e investigado pero no he dedicado tiempo como para ponerlo en análisis y pruebas. En lo que hace a aplicaciones de escritorio, si el usuario no tiene demasiadas posibilidades de meter dedo ¿nos libra de algún ataque? :rolleyes:
Se escucha mucho hablar de injección SQL en el entorno web, es más las fuentes que estuve viendo de tu enlace se centra esto, pero hasta el momento no he visto algún artículo que hable de esto para aplicaciones de escritorio ¿Vale lo mismo?

Saludos,

ecfisa 14-04-2012 20:47:27

Hola.

Con seguridad todos los que participaron en este hilo conoce de forma clara la inyección sql, pero pensando en los que puedan
leer el tema y no sepan de él o tengan una idea muy vaga, agrego un enlace donde se explica de forma sencilla la [Inyección SQL]

Saludos.

roman 15-04-2012 18:45:23

Cita:

Empezado por mamcx (Mensaje 430021)
El caracter % hace parte del estandar SQL para consultas LIKE. No tiene nada de malo en general, excepto que se puede usar pa una injeccion, pero NUNCA en el caso de usar parametros.

Tener "%algo" no es ningun problema.

¡Vaya! Parece que seguimos esquivos. El caso es que no dan un sólo ejemplo de inyección de código debido al uso de % sin parámetros. He visto algunos ejemplos pero se deben en realidad al uso de apóstrofos. Creo que soy de la opinión de Delphius.

Eso, o simplemente no les parece adecuado compartir sus conocimientos.

// Saludos

marcoszorrilla 15-04-2012 19:04:52

He encontrado esto en unos foros:

Delphi - prevent against SQL injection



up vote 16 down vote favorite 1
share [g+] share [fb] share [tw]
I need to protect an application from SQL injection. Application is connecting to Oracle, using ADO, and search for the username and password to make the authentication.
From what I've read until now, the best approach is by using parameters, not assigning the entire SQL as string. Something like this:
query.SQL.Text := 'select * from table_name where name=:Name and id=:ID';
query.Prepare;
query.ParamByName( 'Name' ).AsString := name;
query.ParamByName( 'ID' ).AsInteger := id;
query.Open;
Also, I'm thinking to verify the input from user, and to delete SQL keywords like delete,insert,select,etc...Any input character different than normal ASCII letters and numbers will be deleted.
This will assure me a minimum of security level?
I do not want to use any other components than Delphi 7 standard and Jedi.

sql oracle delphi sql-injection delphi-7





feedback

3 Answers

active oldest votes


up vote 26 down vote accepted
Safe
query.SQL.Text := 'select * from table_name where name=:Name';
This code is safe because you are using parameters.
Parameters are always safe from SQL-injection.
Unsafe
var Username: string;
...
query.SQL.Text := 'select * from table_name where name='+ UserName;
Is unsafe because Username could be name; Drop table_name; Resulting in the following query being executed.
select * from table_name where name=name; Drop table_name;
Also Unsafe
var Username: string;
...
query.SQL.Text := 'select * from table_name where name='''+ UserName+'''';
Because it if username is ' or (1=1); Drop Table_name; -- It will result in the following query:
select * from table_name where name='' or (1=1); Drop Table_name; -- '
But this code is safe
var id: integer;
...
query.SQL.Text := 'select * from table_name where id='+IntToStr(id);
Because IntToStr() will only accept integers so no SQL code can be injected into the query string this way, only numbers (which is exactly what you want and thus allowed)
But I want to do stuff that can't be done with parameters
Parameters can only be used for values. They cannot replace field names or table names. So if you want to execute this query
query:= 'SELECT * FROM :dynamic_table '; {doesn't work}
query:= 'SELECT * FROM '+tableName; {works, but is unsafe}
The first query fails because you cannot use parameters for table or field names.
The second query is unsafe but is the only way this this can be done.
How to you stay safe?
You have to check the string tablename against a list of approved names.
Const
ApprovedTables: array[0..1] of string = ('table1','table2');

procedure DoQuery(tablename: string);
var
i: integer;
Approved: boolean;
query: string;
begin
Approved:= false;
for i:= lo(ApprovedTables) to hi(ApprovedTables) do begin
Approved:= Approved or (lowercase(tablename) = ApprovedTables[i]);
end; {for i}
if not Approved then exit;
query:= 'SELECT * FROM '+tablename;
...
That's the only way to do this, that I know of.
BTW Your original code has an error:
query.SQL.Text := 'select * from table_name where name=:Name where id=:ID';
Should be
query.SQL.Text := 'select * from table_name where name=:Name and id=:ID';
Because you have an error there, you cannot have two where's in one (sub)query

Espero sirva de algo.

Un Saludo.

mamcx 15-04-2012 20:03:33

Cita:

Empezado por roman (Mensaje 430057)
¡Vaya! Parece que seguimos esquivos. El caso es que no dan un sólo ejemplo de inyección de código debido al uso de % sin parámetros. He visto algunos ejemplos pero se deben en realidad al uso de apóstrofos. Creo que soy de la opinión de Delphius.

Eso, o simplemente no les parece adecuado compartir sus conocimientos.

// Saludos

Es porque te has centrado en la parte de "rompimiento" y no en la de "extracción de información".

Hacer un
Código SQL [-]
drop table
es un daño, pero aparte de tumbar el servicio no provee una ventaja. El ejemplo de los apostrofes es para obtener acceso (login) o eliminar un filtro del SQL.

Ahora bien, una vez estas dentro, que es lo que sigue? Si no estas buscando tumbar el servicio, la opción logica es minar información. Es este punto donde entra el asunto del '%':

Extraer info de los usuarios (averiguar la info de Bob):

http://www.unixwiz.net/techtips/sql-injection.html
Cita:

We can do the query on email name or full name (or presumably other information), each time putting in the % wildcards that LIKE supports:
Código SQL [-]
SELECT email, passwd, login_id, full_name
  FROM members
 WHERE email = 'x' OR full_name LIKE '%Bob%';

Injectando el sql desde un query de pagina & deduciendo la tabla que tiene los logins de usuarios:

http://www.securiteam.com/securityre...DP0N1P76E.html
Cita:

We also can search for data using LIKE keyword:
Código SQL [-]
http://duck/index.asp?id=10 UNION SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME LIKE '%25login%25'--

Osea, lo que falto aclarar antes es que el ejemplo clásico de inyección es de rompimiento (acceso), pero una vez dentro, es uso mas "tradicional" del sql, el conocimiento del lenguaje, el tipo de motor, entorno, etc. Hay se usa el rango completo, como acceso a tablas de sistemas, funciones, comandos de búsqueda (donde entra el %!!!), etc...

El error mio fue presumir que era obvio que se puede usar cualquier comando del SQL con una inyección, sin ser claro en el porque..

Es por eso que se puede usar el '%' para una inyección, es cosa de darse cuenta que la inyección no solo rompe, sino que tambien extrae información.

roman 16-04-2012 16:08:05

No hombre, no. Para que tú puedas poner una consulta como las de arriba, necesitas inyectarla. Y para eso es necesario que puedas poner apóstrofos sin restricciones. Una vez que puedes hacer esto entonces claro que puedes hacer uso del comodín para averiguar información. Pero el mal no está en el comodín en sí.

Es por eso que molesta ver este tipo de mensajes en donde se hace una afirmación que asusta y que no necesariamente es correcta.

Digámoslo de otra manera. Un código como este:

Código Delphi [-]
Query1.SQL.Add('select * from tabla where nombre like ' + Edit1.Text );

deja abierta la puerta a la inyección SQL. Pero si escapamos los apóstrofos:

Código Delphi [-]
Query1.SQL.Add('select * from tabla where nombre like ' + Escape(Edit1.Text ));

sigo sin ver dónde está el problema con que el usuario escriba un comodín. Los ejemplos que pones se basan en poder inyectar una sentencia con comodín pero gracias a que se deja abierta la puerta del apóstrofo.

Es decir, no es que no entienda cómo usar el comodín para extraer información, una vez rota la entrada (usando tus términos). El caso es que el mensaje original dice, textualmente:

Cita:

He visto muchos casos donde por ejemplo en un soft de gestión, para buscar un producto por nombre le piden al usuario que escriba un "%" como comodín si no se sabe el nombre completo
Dando a entender que el mero uso del comodín es nocivo, sin siquiera saber si el software en cuestión usa o no parámetros, y aún no usándolos, sin saber si escapa o no los apóstrofos.

// Saludos

Chris 16-04-2012 20:46:59

Cita:

Empezado por roman (Mensaje 430104)
Dando a entender que el mero uso del comodín es nocivo, sin siquiera saber si el software en cuestión usa o no parámetros, y aún no usándolos, sin saber si escapa o no los apóstrofos.

No creo que Mario halla querido ensañarse con el comodín. Más bien debe ser un hipotético escenario en donde los desarrollares dejan al usuario ingresar código SQL arbitrariamente, confiando en la buena voluntad de los usuarios. O aveces, también confiando en la ignorancia de ellos...

Chris 16-04-2012 20:56:50

Cita:

Empezado por Delphius (Mensaje 430024)
Yo algo de injección SQL he escuchado, leído e investigado pero no he dedicado tiempo como para ponerlo en análisis y pruebas. En lo que hace a aplicaciones de escritorio, si el usuario no tiene demasiadas posibilidades de meter dedo ¿nos libra de algún ataque? :rolleyes:
Se escucha mucho hablar de injección SQL en el entorno web, es más las fuentes que estuve viendo de tu enlace se centra esto, pero hasta el momento no he visto algún artículo que hable de esto para aplicaciones de escritorio ¿Vale lo mismo?

Saludos,

Sí, vale igual.

Imagínate que tienes una ventana, en ella tienes un TEdit dónde se supone que el usuario ingresará un valor a buscar. En tu código la búsqueda la procesas así:
Código Delphi [-]
Query1.SQL.Text = ('select * from clientes where no_cliente = ' + Edit1.text);

Si el usuario ingresa "101" en el TEdit, la consulta SQL anterior quedaría así: select * from clientes where no_cliente = 102.

Pero supongamos que el usuario, en lugar de ingresar un número, ingresa en el TEdit algo cómo: "102; delete from clientes where 1=1;", la consulta anterior quedaría así: select * from clientes where no_cliente = 102; delete from clientes where 1=1;.

Es obvio lo devastador que resultaría esta consulta, no? Eso es inyección de SQL. Es hacer que tu aplicación ingenuamente ejecute código SQL arbitrario, sea cuál sea. Esta vulnerabilidad hace a tu aplicación quedar como una tonta que hace todo lo que le dicen sin poner reparo.

Saludos

roman 16-04-2012 21:10:50

Cita:

Empezado por Chris (Mensaje 430136)
No creo que Mario halla querido ensañarse con el comodín. Más bien debe ser un hipotético escenario en donde los desarrollares dejan al usuario ingresar código SQL arbitrariamente, confiando en la buena voluntad de los usuarios. O aveces, también confiando en la ignorancia de ellos...

Tienes razón. En realidad mi crítica no va tanto hacia el comentario de mamcx, sino al original de AzidRain. Vamos a ver: al leer el comentario original que abrió el hilo, de inmediato me vino a la mente un programa en el que hago precisamente eso: dejar que el usuario ponga un comodín para realizar búsquedas. Claro que yo lo hago usando parámetros. Pero al ver, así a secas, que se menciona el uso del comodín como uno de los ejemplos en donde tal vez por comodidad practicamente se puede hacer de todo, pues me alerto y por ello pregunto en qué reside el peligro del comodín. Y la única respuesta que he recibido se refiere a la no precaución de evitar los apóstrofos.

Lo que puedo concluir hasta el momento es que no tiene ningún peligro permitir que el usuario escriba un comodín en la consulta. A menos, claro, que no escape (bien directamente o bien por el uso de parámetros) el apóstrofo, pero eso es harina de otro costal.

// Saludos


La franja horaria es GMT +2. Ahora son las 17:16:49.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi