Inyeccion de codigo

17/03/2005 - 18:37 por Infoliber | Informe spam
Hola,
mirando el help me parecio que para que no me pudieran inyectar codigo
desde un campo de consulta era mejor poner storedprocedures.

He empezado una aplicacion en asp.net y todas las consultas las hago con
storedProcedures pero no veo el motivo por el cual se evita la inyeccion de
codigo, si yo le paso a un parametro una parte de codigo este se pasa al sql
server, lo veo igual que hacer la consulta sin los storedProcedures.

¿Como se puede evitar la inyeccion de codigo?

Gracias

Preguntas similare

Leer las respuestas

#11 Miguel Egea
19/03/2005 - 11:54 | Informe spam
Muchas gracias Maxi, he estado 4 meses con una punta de trabajo
impresionante, la verdad es que no ha pasado, aún al contrario, pero este
grupo de noticias es muy importante para mí e intentaré sacar hueco para
estar más seguidito.



-
Miguel Egea Gómez
Microsoft SQL-Server MVP, MCSD, MCAD,MCT
Webmaster de PortalSql.Com
¿Te interesa participar en las reuniones
del grupo de Usuarios de SQL-Server y .NET
Se harán en levante de España, (Alicante o Murcia)?

"MAXI" escribió en el mensaje
news:%
Aparecio el master de los master :-), me ganaste de mano con la respuesta
:( pero la verdad que la hiciste mucho mejor de lo que la pensaba
responder yo y ademas aprendi cosas :-)

Muchas gracias maestro, deberias estar mas seguido por aqui, se te extraña
:S



Maxi
Buenos Aires - Argentina
Desarrollador .NET 3 Estrellas
Microsoft User Group (MUG)



"Miguel Egea" escribió en el mensaje
news:%238%234Q9$
Ese código que tu montas no tiene posiblidad de inyección de código SQL
es correcto.

La inyección de código tiene dos vertientes, muchos desarrolladores pasan
parámetros a sus aplicaciones(por ejemplo asp) en la url imagina algo así

http://tuempresa.com/mostrarcuenta?idCliente#,

Bien, tanto si se arma la sentencia en asp como en SQL en un stored, si
la sentencia se arma con ejecución dinámica puedes tener ese problema

Imagina asp
SQL="select * from cliente where idcliente=" + Request("idcliente"),

Si algún listillo te teclea algo así (fijaos que el %20 es el espacio)
http://tuempresa.com/mostrarcuenta?...ving%201=1 ,
tu sentencia queda algo así
Select * from clientes where idcliente# having 1=1
Lo más normal es que aparezca un error diciendo que uno de los nombres de
tu tabla no está en group by (acaba de averiguar como se llama tu primer
campo)
Column 'Clientes.dni' is invalid in the select list because it is not
contained in an aggregate function and there is no GROUP BY clause.

Si te teclean algo así
http://tuempresa.com/mostrarcuenta?...%20by%2024 ,
tu sentencia queda algo así
Select * from clientes where idcliente# order by 24
Lo más normal es que el error sea algo así
The ORDER BY position number 24 is out of range of the number of items in
the select list.

Iterando puede obtener el número de columnas que tienes y después
simplemente puede añadirte detrás un union all con un select por ejemplo
de sysobjects, tu aplicación lo más normal es que muy amablemente le
muestre los nombres de tus tablas, y a partir de ahí, pues ya imagina lo
que puede hacer

Como vés esto no se soluciona sustituyendo un ' por dos ', ya que aquí
solo hay caracteres numéricos, el problema no son los strings o los
números sino la forma de construir las sentencias.

Esto se solucionaría así
SQL="select * from cliente where idcliente=@idCliente"
y después si por ejemplo es .net
Comando.Parameters.add y añadiendo así el valor de la variable.

Si esto lo hacemos con procedures también tenemos el mismo problema
imagina que el código es

SQL="Exec DameCliente " + Request("idcliente"),

y Dame cliente es algo así, muy sencillo

create table clientes(idcliente int primary key,nombre nvarchar(100))
go
create procedure DameClientes @idcliente int
as
select * from clientes where idcliente=@idcliente
go
Si en la url te teclean algo así
http://tuempresa.com/mostrarcuenta?...e%clientes ,
tu sentencia SQl queda algo así
exec Dameclientes 23 drop table clientes

Si lanzas mi script y lo pruebas verás que tu tabla clientes desaparecerá
sin dejar rastro

Espero que este correo ayude a entender el problema y a evitar que lo
hagamos.

Saludos



"Alejandro Mesa" escribió en el
mensaje news:
Maxi,

Estoy de acuerdo contigo, pero el ejemplo de Miguel crea la sentencia en
la
aplicacion cliente. Si en este caso, por ejemplo, creamos el
procedimiento:

create procedure dbo.usp_check_user
@login varchar(10),
@password varchar(10),
@ok int output
as
set nocount on

declare @user nvarchar(256)
declare @app nvarchar(128)
declare @workstation nvarchar(128)

if not exists(select * from usuarios where login = @login)
begin
raiserror('No existe login [%s].', 16, 1, @login)
return 0
end

if exists(select * from usuarios where login = @login and password >>> @password)
set @ok = 1
else
begin
set @ok = 0
set @user = suser_sname()
set @app = app_name()
set @workstation = cast(host_name() as nvarchar(128))

raiserror('Incorrect password. login=[@login]; user=[%s]; app=[%s];
workstation=[%s].', 16, 1, @login, @user, @app, @workstation) with log
end

return 0
go

y lo llamamos desde la aplicacion cliente, entonces no veo como
pudieramos
inyectar codigo.


AMB

"Maxi" wrote:

Si ya se, pero no me entendiste creo. Proba de armar un Sp's y usar las
' y
veras las maravillas que puedes hacer :)

Lo que te queria decir que no alcanza solo con usar SP, sino que
tambien hay
que controlar como vienen los datos.


Salu2
Maxi


"Alejandro Mesa" escribió en
el
mensaje news:
> Maxi,
>
> Esto es cuando generas la sentencia dinamicamente en la aplicacion
> cliente.
> Esto es peor, no solo debes chequear la inyeccion de codigo, sino que
> si
> debes arreglar algo o cambiarlo, debes buscar por cuanta aplicacion
> tengas.
>
>
> AMB
>
>
> "Maxi" wrote:
>
>> Hola mi amigo, te paso un articulo de Miguel Egea donde muestra
>> algunas
>> cosas de las que te comente ;)
>>
>> http://www.configuracionesintegrale...p?articulo4
>>
>> prometo buscarte algo mas especifico en cuento a los parametros de
>> los
>> sp's
>> :-)
>>
>>
>> Salu2
>> Maxi
>>
>>
>> "Alejandro Mesa" escribió
>> en el
>> mensaje news:
>> > Hombre, donde has estado?
>> >
>> >> Ojo ALe, hay veces que un SP puede tener un param varcghar(300) y
>> >> ya
>> >> ahi
>> >> puedes injectar mucho codigo aunque no lo creas, y no es
>> >> necesario
>> >> usar
>> >> sql-dinamico para que esto suceda
>> >
>> > No se me ocurre como, pudieras exponernos un ejemplo?
>> >
>> >
>> > AMB
>> >
>> >
>> >
>> >
>> > "Maxi" wrote:
>> >
>> >> Ojo ALe, hay veces que un SP puede tener un param varcghar(300) y
>> >> ya
>> >> ahi
>> >> puedes injectar mucho codigo aunque no lo creas, y no es
>> >> necesario
>> >> usar
>> >> sql-dinamico para que esto suceda
>> >>
>> >>
>> >> Salu2
>> >> Maxi
>> >>
>> >>
>> >> "Alejandro Mesa"
>> >> escribió en
>> >> el
>> >> mensaje
>> >> news:
>> >> > Una forma de evitar inyeccion atraves de los sp es el tipo de
>> >> > dato
>> >> > de
>> >> > los
>> >> > parametros. Si declaras @par1 como INT entonces que vas a
>> >> > inyectar?.
>> >> > Tambien
>> >> > si el parametro es por ejemplo char(3), pues no podras inyectar
>> >> > mucho
>> >> > que
>> >> > digamos. El problema estaria en aquellos sp que usan sql
>> >> > dinamico y
>> >> > esperan
>> >> > parametros con tipo de datos char / nchar/ varchar / etc., y
>> >> > para
>> >> > poder
>> >> > inyectar codigo habria que de alguna manera cerrar la cadena.
>> >> >
>> >> > Ejemplo:
>> >> >
>> >> > use northwind
>> >> > go
>> >> >
>> >> > alter procedure proc1
>> >> > @par1 nvarchar(40)
>> >> > as
>> >> > set nocount on
>> >> >
>> >> > declare @sql nvarchar(4000)
>> >> >
>> >> > set @sql = N'
>> >> > select *
>> >> > from customers
>> >> > where companyname = ''' + @par1 + ''''
>> >> >
>> >> > print @sql
>> >> > exec sp_executesql @sql
>> >> > go
>> >> >
>> >> > create table t(colA int)
>> >> > go
>> >> >
>> >> > exec proc1 N'''; drop table t; select 1 where '''' = '''
>> >> > go
>> >> >
>> >> > select * from t
>> >> > go
>> >> >
>> >> > Fijate en la sentencia que se armo dinamicamente.
>> >> >
>> >> > Puedes hacer lo siguiente, si vas a usar sql dinamico. Usar
>> >> > sp_executesql
>> >> > y
>> >> > no EXEC(), usar parametros en el procedimiento sp_executesql o
>> >> > duplicar
>> >> > todos
>> >> > los apostrofes dentro del parametro pasado.
>> >> >
>> >> > alter procedure proc1
>> >> > @par1 nvarchar(40)
>> >> > as
>> >> > set nocount on
>> >> >
>> >> > declare @sql nvarchar(4000)
>> >> >
>> >> > set @sql = N'
>> >> > select *
>> >> > from customers
>> >> > where companyname = ''' + replace(@par1, '''', '''''') + ''''
>> >> >
>> >> > print @sql
>> >> > exec sp_executesql @sql
>> >> > go
>> >> >
>> >> > create table t(colA int)
>> >> > go
>> >> >
>> >> > exec proc1 N'''; drop table t; select 1 where '''' = '''
>> >> > go
>> >> >
>> >> > select * from t
>> >> > go
>> >> >
>> >> > drop table t
>> >> > go
>> >> >
>> >> > alter procedure proc1
>> >> > @par1 nvarchar(40)
>> >> > as
>> >> > set nocount on
>> >> >
>> >> > declare @sql nvarchar(4000)
>> >> >
>> >> > set @sql = N'
>> >> > select *
>> >> > from customers
>> >> > where companyname = @par1'
>> >> >
>> >> > print @sql
>> >> > exec sp_executesql @sql, N'@par1 nvarchar(40)', @par1
>> >> > go
>> >> >
>> >> > create table t(colA int)
>> >> > go
>> >> >
>> >> > exec proc1 N'''; drop table t; select 1 where '''' = '''
>> >> > go
>> >> >
>> >> > select * from t
>> >> > go
>> >> >
>> >> > drop table t
>> >> > go
>> >> >
>> >> >
>> >> > AMB
>> >> >
>> >> > "Infoliber" wrote:
>> >> >
>> >> >> Hola,
>> >> >> mirando el help me parecio que para que no me pudieran
>> >> >> inyectar
>> >> >> codigo
>> >> >> desde un campo de consulta era mejor poner storedprocedures.
>> >> >>
>> >> >> He empezado una aplicacion en asp.net y todas las consultas
>> >> >> las
>> >> >> hago
>> >> >> con
>> >> >> storedProcedures pero no veo el motivo por el cual se evita la
>> >> >> inyeccion
>> >> >> de
>> >> >> codigo, si yo le paso a un parametro una parte de codigo este
>> >> >> se
>> >> >> pasa
>> >> >> al
>> >> >> sql
>> >> >> server, lo veo igual que hacer la consulta sin los
>> >> >> storedProcedures.
>> >> >>
>> >> >> ¿Como se puede evitar la inyeccion de codigo?
>> >> >>
>> >> >> Gracias
>> >> >>
>> >> >>
>> >> >>
>> >>
>> >>
>> >>
>>
>>
>>
















Respuesta Responder a este mensaje
#12 MAXI
19/03/2005 - 13:51 | Informe spam
Hola sera un placer poderte leer mas seguido :-)



Maxi
Buenos Aires - Argentina
Desarrollador .NET 3 Estrellas
Microsoft User Group (MUG)



"Miguel Egea" escribió en el mensaje
news:
Muchas gracias Maxi, he estado 4 meses con una punta de trabajo
impresionante, la verdad es que no ha pasado, aún al contrario, pero este
grupo de noticias es muy importante para mí e intentaré sacar hueco para
estar más seguidito.



-
Miguel Egea Gómez
Microsoft SQL-Server MVP, MCSD, MCAD,MCT
Webmaster de PortalSql.Com
¿Te interesa participar en las reuniones
del grupo de Usuarios de SQL-Server y .NET
Se harán en levante de España, (Alicante o Murcia)?

"MAXI" escribió en el mensaje
news:%
Aparecio el master de los master :-), me ganaste de mano con la respuesta
:( pero la verdad que la hiciste mucho mejor de lo que la pensaba
responder yo y ademas aprendi cosas :-)

Muchas gracias maestro, deberias estar mas seguido por aqui, se te
extraña :S



Maxi
Buenos Aires - Argentina
Desarrollador .NET 3 Estrellas
Microsoft User Group (MUG)



"Miguel Egea" escribió en el mensaje
news:%238%234Q9$
Ese código que tu montas no tiene posiblidad de inyección de código SQL
es correcto.

La inyección de código tiene dos vertientes, muchos desarrolladores
pasan parámetros a sus aplicaciones(por ejemplo asp) en la url imagina
algo así

http://tuempresa.com/mostrarcuenta?idCliente#,

Bien, tanto si se arma la sentencia en asp como en SQL en un stored, si
la sentencia se arma con ejecución dinámica puedes tener ese problema

Imagina asp
SQL="select * from cliente where idcliente=" + Request("idcliente"),

Si algún listillo te teclea algo así (fijaos que el %20 es el espacio)
http://tuempresa.com/mostrarcuenta?...ving%201=1 ,
tu sentencia queda algo así
Select * from clientes where idcliente# having 1=1
Lo más normal es que aparezca un error diciendo que uno de los nombres
de tu tabla no está en group by (acaba de averiguar como se llama tu
primer campo)
Column 'Clientes.dni' is invalid in the select list because it is not
contained in an aggregate function and there is no GROUP BY clause.

Si te teclean algo así
http://tuempresa.com/mostrarcuenta?...%20by%2024 ,
tu sentencia queda algo así
Select * from clientes where idcliente# order by 24
Lo más normal es que el error sea algo así
The ORDER BY position number 24 is out of range of the number of items
in the select list.

Iterando puede obtener el número de columnas que tienes y después
simplemente puede añadirte detrás un union all con un select por ejemplo
de sysobjects, tu aplicación lo más normal es que muy amablemente le
muestre los nombres de tus tablas, y a partir de ahí, pues ya imagina lo
que puede hacer

Como vés esto no se soluciona sustituyendo un ' por dos ', ya que aquí
solo hay caracteres numéricos, el problema no son los strings o los
números sino la forma de construir las sentencias.

Esto se solucionaría así
SQL="select * from cliente where idcliente=@idCliente"
y después si por ejemplo es .net
Comando.Parameters.add y añadiendo así el valor de la variable.

Si esto lo hacemos con procedures también tenemos el mismo problema
imagina que el código es

SQL="Exec DameCliente " + Request("idcliente"),

y Dame cliente es algo así, muy sencillo

create table clientes(idcliente int primary key,nombre nvarchar(100))
go
create procedure DameClientes @idcliente int
as
select * from clientes where idcliente=@idcliente
go
Si en la url te teclean algo así
http://tuempresa.com/mostrarcuenta?...e%clientes
,
tu sentencia SQl queda algo así
exec Dameclientes 23 drop table clientes

Si lanzas mi script y lo pruebas verás que tu tabla clientes
desaparecerá sin dejar rastro

Espero que este correo ayude a entender el problema y a evitar que lo
hagamos.

Saludos



"Alejandro Mesa" escribió en
el mensaje news:
Maxi,

Estoy de acuerdo contigo, pero el ejemplo de Miguel crea la sentencia
en la
aplicacion cliente. Si en este caso, por ejemplo, creamos el
procedimiento:

create procedure dbo.usp_check_user
@login varchar(10),
@password varchar(10),
@ok int output
as
set nocount on

declare @user nvarchar(256)
declare @app nvarchar(128)
declare @workstation nvarchar(128)

if not exists(select * from usuarios where login = @login)
begin
raiserror('No existe login [%s].', 16, 1, @login)
return 0
end

if exists(select * from usuarios where login = @login and password >>>> @password)
set @ok = 1
else
begin
set @ok = 0
set @user = suser_sname()
set @app = app_name()
set @workstation = cast(host_name() as nvarchar(128))

raiserror('Incorrect password. login=[@login]; user=[%s]; app=[%s];
workstation=[%s].', 16, 1, @login, @user, @app, @workstation) with log
end

return 0
go

y lo llamamos desde la aplicacion cliente, entonces no veo como
pudieramos
inyectar codigo.


AMB

"Maxi" wrote:

Si ya se, pero no me entendiste creo. Proba de armar un Sp's y usar
las ' y
veras las maravillas que puedes hacer :)

Lo que te queria decir que no alcanza solo con usar SP, sino que
tambien hay
que controlar como vienen los datos.


Salu2
Maxi


"Alejandro Mesa" escribió en
el
mensaje news:
> Maxi,
>
> Esto es cuando generas la sentencia dinamicamente en la aplicacion
> cliente.
> Esto es peor, no solo debes chequear la inyeccion de codigo, sino
> que si
> debes arreglar algo o cambiarlo, debes buscar por cuanta aplicacion
> tengas.
>
>
> AMB
>
>
> "Maxi" wrote:
>
>> Hola mi amigo, te paso un articulo de Miguel Egea donde muestra
>> algunas
>> cosas de las que te comente ;)
>>
>> http://www.configuracionesintegrale...p?articulo4
>>
>> prometo buscarte algo mas especifico en cuento a los parametros de
>> los
>> sp's
>> :-)
>>
>>
>> Salu2
>> Maxi
>>
>>
>> "Alejandro Mesa" escribió
>> en el
>> mensaje news:
>> > Hombre, donde has estado?
>> >
>> >> Ojo ALe, hay veces que un SP puede tener un param varcghar(300)
>> >> y ya
>> >> ahi
>> >> puedes injectar mucho codigo aunque no lo creas, y no es
>> >> necesario
>> >> usar
>> >> sql-dinamico para que esto suceda
>> >
>> > No se me ocurre como, pudieras exponernos un ejemplo?
>> >
>> >
>> > AMB
>> >
>> >
>> >
>> >
>> > "Maxi" wrote:
>> >
>> >> Ojo ALe, hay veces que un SP puede tener un param varcghar(300)
>> >> y ya
>> >> ahi
>> >> puedes injectar mucho codigo aunque no lo creas, y no es
>> >> necesario
>> >> usar
>> >> sql-dinamico para que esto suceda
>> >>
>> >>
>> >> Salu2
>> >> Maxi
>> >>
>> >>
>> >> "Alejandro Mesa"
>> >> escribió en
>> >> el
>> >> mensaje
>> >> news:
>> >> > Una forma de evitar inyeccion atraves de los sp es el tipo de
>> >> > dato
>> >> > de
>> >> > los
>> >> > parametros. Si declaras @par1 como INT entonces que vas a
>> >> > inyectar?.
>> >> > Tambien
>> >> > si el parametro es por ejemplo char(3), pues no podras
>> >> > inyectar
>> >> > mucho
>> >> > que
>> >> > digamos. El problema estaria en aquellos sp que usan sql
>> >> > dinamico y
>> >> > esperan
>> >> > parametros con tipo de datos char / nchar/ varchar / etc., y
>> >> > para
>> >> > poder
>> >> > inyectar codigo habria que de alguna manera cerrar la cadena.
>> >> >
>> >> > Ejemplo:
>> >> >
>> >> > use northwind
>> >> > go
>> >> >
>> >> > alter procedure proc1
>> >> > @par1 nvarchar(40)
>> >> > as
>> >> > set nocount on
>> >> >
>> >> > declare @sql nvarchar(4000)
>> >> >
>> >> > set @sql = N'
>> >> > select *
>> >> > from customers
>> >> > where companyname = ''' + @par1 + ''''
>> >> >
>> >> > print @sql
>> >> > exec sp_executesql @sql
>> >> > go
>> >> >
>> >> > create table t(colA int)
>> >> > go
>> >> >
>> >> > exec proc1 N'''; drop table t; select 1 where '''' = '''
>> >> > go
>> >> >
>> >> > select * from t
>> >> > go
>> >> >
>> >> > Fijate en la sentencia que se armo dinamicamente.
>> >> >
>> >> > Puedes hacer lo siguiente, si vas a usar sql dinamico. Usar
>> >> > sp_executesql
>> >> > y
>> >> > no EXEC(), usar parametros en el procedimiento sp_executesql o
>> >> > duplicar
>> >> > todos
>> >> > los apostrofes dentro del parametro pasado.
>> >> >
>> >> > alter procedure proc1
>> >> > @par1 nvarchar(40)
>> >> > as
>> >> > set nocount on
>> >> >
>> >> > declare @sql nvarchar(4000)
>> >> >
>> >> > set @sql = N'
>> >> > select *
>> >> > from customers
>> >> > where companyname = ''' + replace(@par1, '''', '''''') + ''''
>> >> >
>> >> > print @sql
>> >> > exec sp_executesql @sql
>> >> > go
>> >> >
>> >> > create table t(colA int)
>> >> > go
>> >> >
>> >> > exec proc1 N'''; drop table t; select 1 where '''' = '''
>> >> > go
>> >> >
>> >> > select * from t
>> >> > go
>> >> >
>> >> > drop table t
>> >> > go
>> >> >
>> >> > alter procedure proc1
>> >> > @par1 nvarchar(40)
>> >> > as
>> >> > set nocount on
>> >> >
>> >> > declare @sql nvarchar(4000)
>> >> >
>> >> > set @sql = N'
>> >> > select *
>> >> > from customers
>> >> > where companyname = @par1'
>> >> >
>> >> > print @sql
>> >> > exec sp_executesql @sql, N'@par1 nvarchar(40)', @par1
>> >> > go
>> >> >
>> >> > create table t(colA int)
>> >> > go
>> >> >
>> >> > exec proc1 N'''; drop table t; select 1 where '''' = '''
>> >> > go
>> >> >
>> >> > select * from t
>> >> > go
>> >> >
>> >> > drop table t
>> >> > go
>> >> >
>> >> >
>> >> > AMB
>> >> >
>> >> > "Infoliber" wrote:
>> >> >
>> >> >> Hola,
>> >> >> mirando el help me parecio que para que no me pudieran
>> >> >> inyectar
>> >> >> codigo
>> >> >> desde un campo de consulta era mejor poner storedprocedures.
>> >> >>
>> >> >> He empezado una aplicacion en asp.net y todas las consultas
>> >> >> las
>> >> >> hago
>> >> >> con
>> >> >> storedProcedures pero no veo el motivo por el cual se evita
>> >> >> la
>> >> >> inyeccion
>> >> >> de
>> >> >> codigo, si yo le paso a un parametro una parte de codigo este
>> >> >> se
>> >> >> pasa
>> >> >> al
>> >> >> sql
>> >> >> server, lo veo igual que hacer la consulta sin los
>> >> >> storedProcedures.
>> >> >>
>> >> >> ¿Como se puede evitar la inyeccion de codigo?
>> >> >>
>> >> >> Gracias
>> >> >>
>> >> >>
>> >> >>
>> >>
>> >>
>> >>
>>
>>
>>





















email Siga el debate Respuesta Responder a este mensaje
Ads by Google
Help Hacer una pregunta AnteriorRespuesta Tengo una respuesta
Search Busqueda sugerida