Página 1 de 1

Sql asesino

Publicado: Dom Jul 15, 2007 8:59 pm
por jose.luis
Hola,
Os pongo el siguiente supuesto:
Sea una tabla de clientes donde estamos modificando una ficha.
Hacemos algo parecido a esto:
@ 1,1 GET cNombre PICTURE "@!"
READ
y luego montamos la sentencia SQL para actualizar el dato (por ejemplo):
cSelect := "UPDATE CLIENTES SET Nombre = '"+cNombre+"' WHERE codigo =
'"+cCodigo+"'"
dando como resultado esta sentencia SQL:
UPDATE CLIENTES SET Nombre = 'Nombre del cliente' WHERE codigo = 'micodigo'
Y todo va bien...
Pero... ¿que pasa si en cNombre ponen lo siguiente?
'; DELETE FROM CLIENTES; UPDATE CLIENTES SET Nombre = 'A
Esto da como resultado la siguiente sentencia SQL
UPDATE CLIENTES SET Nombre = ''; DELETE FROM CLIENTES; UPDATE CLIENTES SET
Nombre = 'A' WHERE codigo = 'micodigo'
Ostras!!
Pero... si ponen esto:
'; DROP DATABASE MiBaseDatos; UPDATE CLIENTES SET Nombre = 'A
Nos quedaría una sentencia como esta:
UPDATE CLIENTES SET Nombre = ''; DROP DATABASE MiBaseDatos; UPDATE CLIENTES
SET Nombre = 'A' WHERE codigo = 'micodigo'
Más ostras!!
Saludos,
José Luis Capel
PD: os dejo estos enlaces
http://es.wikipedia.org/wiki/Inyecci%C3%B3n_SQL
http://www.programacionphp.net/recursos ... articulos- de-Vulnerabilidades/SQL-injection_0001601.html
http://www.scourdesign.com/articulos/tu ... /net/1.php
http://msdn2.microsoft.com/es-es/librar ... S.80).aspx

Sql asesino

Publicado: Dom Jul 15, 2007 9:33 pm
por jmartial
Jose,
¿Con qué motor lo has probado?
Yo he probado con Mysql y "se lo traga todo", pero con postgres ese
ejemplo que pones no tendrí­a problemas.
No admite dobles comillas en vez de simple para los literales.
Un Saludo,
Joaquí­n
José Luis Capel escribió:
> Hola,
>
> Os pongo el siguiente supuesto:
>
> Sea una tabla de clientes donde estamos modificando una ficha.
>
> Hacemos algo parecido a esto:
>
> @ 1,1 GET cNombre PICTURE "@!"
> READ
>
> y luego montamos la sentencia SQL para actualizar el dato (por ejemplo):
>
> cSelect := "UPDATE CLIENTES SET Nombre = '"+cNombre+"' WHERE codigo =
> '"+cCodigo+"'"
>
> dando como resultado esta sentencia SQL:
>
> UPDATE CLIENTES SET Nombre = 'Nombre del cliente' WHERE codigo = 'micodigo'
>
> Y todo va bien...
>
> Pero... ¿que pasa si en cNombre ponen lo siguiente?
>
> '; DELETE FROM CLIENTES; UPDATE CLIENTES SET Nombre = 'A
>
> Esto da como resultado la siguiente sentencia SQL
>
> UPDATE CLIENTES SET Nombre = ''; DELETE FROM CLIENTES; UPDATE CLIENTES SET
> Nombre = 'A' WHERE codigo = 'micodigo'
>
> Ostras!!
>
> Pero... si ponen esto:
>
> '; DROP DATABASE MiBaseDatos; UPDATE CLIENTES SET Nombre = 'A
>
> Nos quedarí­a una sentencia como esta:
>
> UPDATE CLIENTES SET Nombre = ''; DROP DATABASE MiBaseDatos; UPDATE CLIENTES
> SET Nombre = 'A' WHERE codigo = 'micodigo'
>
>
> Más ostras!!
>
> Saludos,
> José Luis Capel
> PD: os dejo estos enlaces
> http://es.wikipedia.org/wiki/Inyecci%C3%B3n_SQL
> http://www.programacionphp.net/recursos ... articulos- de-Vulnerabilidades/SQL-injection_0001601.html
> http://www.scourdesign.com/articulos/tu ... /net/1.php
> http://msdn2.microsoft.com/es-es/librar ... S.80).aspx
>
>
>

Sql asesino

Publicado: Dom Jul 15, 2007 10:37 pm
por jasm
Eso se llama SQL Injection en argot de seguridad informática.
Es uno de los ataque mas usados para fastidar bases de datos desde
páginas webs.
Saludos
Jose A. Suarez

Sql asesino

Publicado: Lun Jul 16, 2007 2:06 pm
por notelo
José Luis,
la inyección SQL se usa desde hace tiempo para "estropear" bases de datos e
incluso ganar privilegios de administrador en los hosts que las albergan.
Googlea un poco y verás qué fácil es hacerlo contra un blog con algunas
versiones de Wordpress.
Saludos,
José Lalí­n

Sql asesino

Publicado: Lun Jul 16, 2007 3:10 pm
por jose.luis
Hola Joaquí­n,
>
> ¿Con qué motor lo has probado?
>
> Yo he probado con Mysql y "se lo traga todo", pero con postgres ese
> ejemplo que pones no tendrí­a problemas.
> No admite dobles comillas en vez de simple para los literales.
>
Creo que no es exclusivo de un motor. Solo hay que cambiar los
delimitadores.
Saludos,
José Luis Capel

Sql asesino

Publicado: Lun Jul 16, 2007 3:16 pm
por jose.luis
José Alfonso,
>
> Eso se llama SQL Injection en argot de seguridad informática.
Si... si... ya se lo que es...
>
> Es uno de los ataque mas usados para fastidar bases de datos desde páginas
> webs.
Y en las aplicaciones de escritorio tambien (aunque no tenga ni mucho
sentido ni mucha repercusión).
El caso es que en el improbable caso de que alguno de nuestros clientes
quiera sabotear nuestra aplicación no podremos hacer mucho si se utiliza la
técnica del SELECT, INSERT y UPDATE para acceder, modificar e insertar
datos.
Con ADO la cosa se complica un poco. Si se utilizan los recordsets nativos
de ADO será difí­cil que eso ocurra dado que internamente ADO utiliza
cursores y procedimientos almacenados para actualiar los datos.
Saludos,
José Luis Capel

Sql asesino

Publicado: Lun Jul 16, 2007 3:18 pm
por jose.luis
José,
>
> la inyección SQL se usa desde hace tiempo para "estropear" bases de datos
> e incluso ganar privilegios de administrador en los hosts que las
> albergan.
>
> Googlea un poco y verás qué fácil es hacerlo contra un blog con algunas
> versiones de Wordpress.
>
Cierto...
Pero yo quiero trasladarlo a nuestras aplicaciones de escritorio. Se
positivamente que esta situación es altamente improblable que ocurra.
Vamos, no me imagino a un cliente nuestro intentando sabotear sus propios
datos y aplicación.
Saludos,
José Luis Capel

Sql asesino

Publicado: Lun Jul 16, 2007 4:45 pm
por Rolando
José Luis:
"José Luis Capel" <jose.luis@capelsoft.com> escribió en el mensaje
news:[email=469b7045@ozsrv2.ozlan.local...]469b7045@ozsrv2.ozlan.local...[/email]
> José,
>>
>> la inyección SQL se usa desde hace tiempo para "estropear" bases de datos
>> e incluso ganar privilegios de administrador en los hosts que las
>> albergan.
>>
>> Googlea un poco y verás qué fácil es hacerlo contra un blog con algunas
>> versiones de Wordpress.
>>
>
> Cierto...
>
> Pero yo quiero trasladarlo a nuestras aplicaciones de escritorio. Se
> positivamente que esta situación es altamente improblable que ocurra.
> Vamos, no me imagino a un cliente nuestro intentando sabotear sus propios
> datos y aplicación.
No es dificil imaginarse un empleado enojado con su patron !
Saludos.
>
> Saludos,
> José Luis Capel

Sql asesino

Publicado: Lun Jul 16, 2007 5:05 pm
por Thefull
José Luis Capel escribió:
> Hola Joaquí­n,
>>
>> ¿Con qué motor lo has probado?
>>
>> Yo he probado con Mysql y "se lo traga todo", pero con postgres ese
>> ejemplo que pones no tendrí­a problemas.
>> No admite dobles comillas en vez de simple para los literales.
>>
>
> Creo que no es exclusivo de un motor. Solo hay que cambiar los
> delimitadores.
>
¿ Y si lo pasas a texto ?
Es decir;
UPDATE CLIENTES SET Nombre = ['Nombre del cliente' ] WHERE codigo = [
'micodigo' ]
Lo has probado ?
Saludos
Rafa Carmona

Sql asesino

Publicado: Lun Jul 16, 2007 7:21 pm
por notelo
José Luis,
> Pero yo quiero trasladarlo a nuestras aplicaciones de escritorio. Se
> positivamente que esta situación es altamente improblable que ocurra.
> Vamos, no me imagino a un cliente nuestro intentando sabotear sus
> propios datos y aplicación.
Puede que te fí­es del cliente pero no sabes a quién tiene trabajando para
él o quién tiene acceso a sus datos.
Según he leí­do una de las mejores maneras de evitar esto es analizar el
texto introducido (comprobar número de comillas, si contiene mandatos que
no deberí­a como DROP, etc.) antes de montar la sentencia SQL, siempre en
caso de que permitas escribirlas desde la aplicación o las guardes en algún
archivo.
Saludos,
José Lalí­n

Sql asesino

Publicado: Lun Jul 16, 2007 8:16 pm
por jose.luis
José,
>
> Puede que te fí­es del cliente pero no sabes a quién tiene trabajando para
> él o quién tiene acceso a sus datos.
>
> Según he leí­do una de las mejores maneras de evitar esto es analizar el
> texto introducido (comprobar número de comillas, si contiene mandatos que
> no deberí­a como DROP, etc.) antes de montar la sentencia SQL, siempre en
> caso de que permitas escribirlas desde la aplicación o las guardes en
> algún archivo.
Yo estoy cambiando todos los acceso a base de datos. Actualmente estoy
utilizando ADO (con clases propias) contra un SQL Server. He visto dos
posibles situaciones:
a. Utilizar un Recordset de ADO lado servidor. En este caso ADO crea un
cursor y lo actualiza con procedimientos almacenados. Si utilizamos un
recordset de lado cliente entonces no hay cursor abierto, pero sigue
actualizando los datos con un procedimiento almacenado. Este caso es el más
favorable dado que la inyección de código malicioso nunca llegará a
ejecutarse. Como mucho ocurrirá un error en la ejecución del procedimiento.
b. Utilizar directamente el método execute del objeto connection. Este es
el peor caso. Es ahí­ donde se nos puede colar el código sql malicioso.
El primer caso ya me lo resuelve ADO. Para el segundo caso estoy cambiando
paulatinamente mis llamadas directas por llamadas a través de un
procedimiento almacenado.
Sql Server provee un procedimiento almacenado que te permite lanzar tu
sentencia SQL. El procedimiento en cuestión es el sp_executesql.
Entiendo que 'monitorizar' cada una de las sentencias sql mediante un
diccionario puede ralentizar procesos con llamadas intensivas o, si no está
bien implementado, dar falsos 'positivos'.
Saludos,
José Luis Capel

Sql asesino

Publicado: Lun Jul 16, 2007 8:17 pm
por jose.luis
Rafa,
> ¿ Y si lo pasas a texto ?
> Es decir;
> UPDATE CLIENTES SET Nombre = ['Nombre del cliente' ] WHERE codigo = [
> 'micodigo' ]
> Lo has probado ?
Si... me coloca los ' como parte de la cadena.
Saludos,
José Luis Capel

Sql asesino

Publicado: Mar Jul 17, 2007 9:41 am
por Thefull
José Luis Capel escribió:
> Rafa,
>> ¿ Y si lo pasas a texto ?
>> Es decir;
>> UPDATE CLIENTES SET Nombre = ['Nombre del cliente' ] WHERE codigo = [
>> 'micodigo' ]
>> Lo has probado ?
>
> Si... me coloca los ' como parte de la cadena.
>
Entonces, si lo montas de esta manera;
'UPDATE CLIENTES SET Nombre =" '+ cNombre + ' " WHERE codigo = "' +
cCodigo +'"'
Nombre = "DROP DATABASE;" , eso NO DEBERIA DE EJECUTARSE! simplemente
meterá el comando como nombre.
Saludos
Rafa Carmona

Sql asesino

Publicado: Mar Jul 17, 2007 5:08 pm
por notelo
José,
creo que la respuesta anterior es digna de ser elaborada un poco más y se
merece un post en tu blog.
Saludos,
José Lalí­n

Sql asesino

Publicado: Mar Jul 17, 2007 8:46 pm
por jose.luis
José,
>
> creo que la respuesta anterior es digna de ser elaborada un poco más y se
> merece un post en tu blog.
>
El blog lo tengo 'cerrado' por falta de tiempo. A ver si en los dí­as de
vacaciones puedo hacer alguna cosilla.
Saludos,
José Luis Capel

Sql asesino

Publicado: Mar Jul 17, 2007 9:25 pm
por jfgimenez
José Luis,
creo que hay una forma muy sencilla de evitar este tipo de 'SQL injection':
comprobar si hay algún carácter de punto y coma (;) en la sentencia. Si lo
hay, entonces casi seguro que se trata de un 'SQL injection'.
Eso sí, desde programa hay que renunciar a escribir varias sentencias en una
misma llamada, pero no creo que eso sea problema en la mayoría de los casos.
O simplemente se puede tener una función que detecte ese carácter, y no
llamarla cuando se quiera hacer.
Por otro lado, imagino que hay más tipos de 'SQL injection', pero supongo
que este es el principal y el más común.
Por cierto, con SQLite no funciona, ya que cuando encuentra un ; en una
sentencia, ejecuta lo que hay antes e ignora lo que sigue.
--
Un saludo,
José F. Giménez
http://www.xailer.com
http://www.xailer.info

Sql asesino

Publicado: Mar Jul 17, 2007 9:28 pm
por jasm
Jose,
> José Luis,
>
> creo que hay una forma muy sencilla de evitar este tipo de 'SQL injection':
> comprobar si hay algún carácter de punto y coma (;) en la sentencia. Si lo
> hay, entonces casi seguro que se trata de un 'SQL injection'.
Difí­cil implementación por aquello de que cada vez más incluimos campos
de texto grandes para tomar notas donde los usuarios pueden incluir
cualquier carácter, incluido el punto y coma (;).
Saludos
Jose A. Suarez

Sql asesino

Publicado: Mar Jul 17, 2007 9:43 pm
por jfgimenez
José Alfonso,
> Difícil implementación por aquello de que cada vez más incluimos campos de
> texto grandes para tomar notas donde los usuarios pueden incluir cualquier
> carácter, incluido el punto y coma (;).
Sí, por supuesto. Lo que hay que buscar es el ; fuera de cualquier cadena de
texto. El ejemplo que ha puesto José Luis termina con la sentencia:
UPDATE CLIENTES SET Nombre = ''; DELETE FROM CLIENTES; UPDATE CLIENTES SET
Nombre = 'A' WHERE codigo = 'micodigo'
Si te fijas, los ; están fuera de las cadenas, y eso es muy fácil
detectarlo.
--
Un saludo,
José F. Giménez
http://www.xailer.com
http://www.xailer.info

Sql asesino

Publicado: Mar Jul 17, 2007 10:12 pm
por jfgimenez
Hola,
aquí teneis una función en C muy sencilla para comprobar este caso:
//---------------------------------------------------------- --------------------
XA_FUNC( CHECKSQLINJECTION )
{
char *cSql = hb_parc( 1 ), c;
int lString = FALSE;
int lInjection = FALSE;
while( c = *cSql++ )
{
if( c == ''' )
lString = !lString;
else if( ( c == ';' ) && ( !lString ) )
{
lInjection = TRUE;
break;
}
}
hb_retl( lInjection );
}
//---------------------------------------------------------- ----------------
Simplemente se le pasa la sentencia SQL y devuelve .T. si se trata de un
'SQL injection', o .F. si todo está correcto.
--
Un saludo,
José F. Giménez
http://www.xailer.com
http://www.xailer.info

Sql asesino

Publicado: Mar Jul 17, 2007 11:56 pm
por jose.luis
José,
>
> Sí­, por supuesto. Lo que hay que buscar es el ; fuera de cualquier cadena
> de texto. El ejemplo que ha puesto José Luis termina con la sentencia:
>
> UPDATE CLIENTES SET Nombre = ''; DELETE FROM CLIENTES; UPDATE CLIENTES SET
> Nombre = 'A' WHERE codigo = 'micodigo'
>
> Si te fijas, los ; están fuera de las cadenas, y eso es muy fácil
> detectarlo.
Ya... pero en SqlServer puedes no colocar ; como separador de instrucciones.
Puedes poner GO o incluso nada.
Creo que lo más efectivo serí­a utilizar procedimientos almacenados para
lanzar nuestras consultas al servidor. Como he comentado en otro mensaje de
este hilo, SqlServer provee de un procedimiento almacenado especializado
para la ejecución de sentencias sql. Este procedimiento tiene una ventaja
adicional que es el hecho de que ante consultas repetitivas funciona más
rápido dado que el servidor las 'precompila'. No tengo claro si MySql tiene
algo parecido.
Saludos,
José Luis Capel
Saludos,
José Luis Capel

Sql asesino

Publicado: Mié Jul 18, 2007 9:38 am
por jose.luis
José,
> Sí, por supuesto. Lo que hay que buscar es el ; fuera de cualquier cadena
> de texto. El ejemplo que ha puesto José Luis termina con la sentencia:
>
> UPDATE CLIENTES SET Nombre = ''; DELETE FROM CLIENTES; UPDATE CLIENTES SET
> Nombre = 'A' WHERE codigo = 'micodigo'
>
Creo que esta forma no es ágil. En muchos casos utilizo varias sentencias
en la misma consulta. Básicamente el uso de SETS.
Saludos,
José Luis Capel

Sql asesino

Publicado: Mié Jul 18, 2007 11:41 am
por jfgimenez
José Luis,
>> Sí, por supuesto. Lo que hay que buscar es el ; fuera de cualquier cadena
>> de texto. El ejemplo que ha puesto José Luis termina con la sentencia:
>>
>> UPDATE CLIENTES SET Nombre = ''; DELETE FROM CLIENTES; UPDATE CLIENTES
>> SET
>> Nombre = 'A' WHERE codigo = 'micodigo'
>>
>
> Creo que esta forma no es ágil. En muchos casos utilizo varias sentencias
> en la misma consulta. Básicamente el uso de SETS.
Bueno, por ahora ya está puesto en Xailer en los dataset de MySQL. Si se
utiliza directamente Execute(), no se comprueba nada, y puedes poner todas
las sentencias que quieras. Pero en los dataset, que están orientados al
manejo de tablas individuales (los de lectura-escritura), las sentencias las
genera el propio dataset, y es ahí donde hemos metido esta protección. Así,
si un 'usuario espabilado' se le ocurre poner alguna perla de las que has
comentado en el nombre de un cliente, p.ej., ya no puede hacer esos
destrozos.
--
Un saludo,
José F. Giménez
http://www.xailer.com
http://www.xailer.info

Sql asesino

Publicado: Jue Jul 19, 2007 8:37 pm
por jose.luis
José,
Estupendo!! Es una buena noticia.
>
> Bueno, por ahora ya está puesto en Xailer en los dataset de MySQL. Si se
> utiliza directamente Execute(), no se comprueba nada, y puedes poner todas
> las sentencias que quieras. Pero en los dataset, que están orientados al
> manejo de tablas individuales (los de lectura-escritura), las sentencias
> las genera el propio dataset, y es ahí­ donde hemos metido esta protección.
> Así­, si un 'usuario espabilado' se le ocurre poner alguna perla de las que
> has comentado en el nombre de un cliente, p.ej., ya no puede hacer esos
> destrozos.
Solo una puntualización:
Creo que el proceso de comprobación de código asesino deberí­a anular ese
código en vez de invalidar sentencia (no se si es tu caso). Desde mi punto
de vista creo que deberí­a sustituir los caracteres potencialmente peligrosos
por otros que neutralicen la acción dañina.
Por ejemplo:
SELECT * FROM clientes WHERE clicodi = 'M'; DROP TABLE mitabla
Sustituirlo por ;
SELECT * FROM clientes WHERE clicodi = 'M' /* DROP TABLE mitabla
Saludos,
José Luis Capel