Ver Mensaje Individual
  #19 (permalink)  
Antiguo 02/10/2007, 23:28
Avatar de u_goldman
u_goldman
Moderador
 
Fecha de Ingreso: enero-2002
Mensajes: 8.031
Antigüedad: 22 años, 10 meses
Puntos: 98
Re: Un módulo de usuarios

Cita:
Iniciado por Myakire Ver Mensaje
Para que no digas que nadie sigue el código :

<input type="password" id="pwd" name="pwd" maxlength="8" vcalue="" />


Mis padres no pudieron venir, pero mi padre se aventó una firma sobre el citatorio espero que con eso ya pueda volver a entrar a tan interesante clase
Gracias con respecto a "la firma de tu padre", esteeeeeeeeee, mejor ni hablar :-p

Bueno chic@s, nos quedamos en que necesitabamos implementar nuestro primer método público de la clase usuario que nos servirá para autentificar a nuestro usuario.

Primero que nada, dos recomendaciones importantes con respecto al acceso a datos:

1. No dejen campos nulos en sus tablas si no es algo que realmente se necesite, los datos nulos ralentizan las consultas y le dan a la aplicación una tarea extra que hacer -manejar otro tipo de dato-, en la medida de lo posible, utiliza valores por defecto para tus campos, estandarízalos de modo que tu aplicación los entienda, por ejemplo, yo se que en mis aplicaciones la fecha '1/1/1800' es regularmente un valor por defecto salvo en los casos que estemos tratando de fechas históricas, así pues, vamos a poner valores por defecto a nuestros campos:

usuario_uname | ''
usuario_pwd | ''

2. Parametricen sus consultas, es una buena práctica que ayuda a tener un orden, saber precisamente el tipo de dato, su longitud, por si fuera poco, ayuda a controlar la inyección de SQL, esta es una lectura que siempre recomiendo, creo recordar que existia el mismo artículo en español, pero no encontré el link

Nuestra forma tradicional de hacer consultas SQL, es un string, al cual concatenamos variables, dicho en nuestro idioma:

Código:
Ej. 1
uname = Request("valor")
pwd = Request("valor")
query = "SELECT usuario_id FROM tbl_usuario WHERE usuario_uname = '" & uname & "' AND pwd = '" & pwd & "'"
Está perfecto ¿no es así? el query se forma correctamente y la sintáxis es correcta, ahora qué pasa si envío los siguientes valores?

usuario
' OR 1 = 1

pwd
' OR 'A' = 'A

Sutituimos los valores:
Código:
SELECT usuario_id FROM tbl_usuario WHERE usuario_uname = '' OR 1 = 1 AND pwd = '' OR 'A' = 'A'
A mi me parece una sentencia correcta y que además siempre será verdadera ¿A tí?

La solución es controlar la comilla simple, pero ¿Qué pasa en el caso de valores numéricos? Supóngase el caso de una página de detalles donde envíamos el id por querystring:

Código:
SELECT campos FROM tabla WHERE campoid = Request.QueryString("id")
Recuerden que para hacer un ataque, se require un poco de intuición, así que supongamos que mediante ciertas excepciones provocadas, nuestro atacante se entera de que tenemos un campo llamado user_uname y nos envía por querystring lo siguiente:

id=1+update tbl_usuario set usuario_uname='<script type=text/javascript>location.href=http://www.unsitio.com</script>'

NUestra consulta quedaría de la siguiente forma:
Código:
SELECT campos FROM tabla WHERE campoid = 1+update tbl_usuario set usuario_uname='<script type=text/javascript>location.href=http://www.unsitio.com</script>'
Woops, que crees? también es una consulta válida, que no solo nos hace una inyección de sql, sino también nos inyectan javascript.

Recuerda que ninguna técnica debe tomarse como religión, quizás te puedas valer de ciertas funciones para reemplazar los posibles ataques de este tipo, pero en todo este tiempo que he estado trabajando con ASP, no he encontrado nada más ordenado, simple y concreto que el objeto command como medio de seguridad.

*El objeto Command desmistificado:

Te voy a poner la parte condensada sin tantos rodeos, básicamente se trata de hacer nuestra consulta, y en lugar de concatenar variables de VBS, envíamos a la consulta un caractér que nuestro objeto reconoce como un parámetro, y se representa mediante un signo de interrogación (?), cada parámetro necesita tener un:

nombre, tipo de dato, tipo de parámetro, tamaño y valor


¿Qué datos requiere el objeto command?
- Conexión activa
- Tipo de Comando
- Texto del comando, la consulta
- Parámetros


-Tipos de datos más comunes para parámetros y su tamaño

adInteger | 4
adDouble | 8
adDate | 8
adVarChar | tamaño del campo
adBoolean | 1
adLongVarChar | regularmente mas de 1000,000

Aterrizando todo:

Código:
Dim ObjConn
Dim rs
Dim cmd
Dim param
Dim qry
Dim id

id = Request.QueryString("id")

'Comando
Set cmd = Server.CreateObject("ADODB.Command")
Set rs = Server.CreateObject("ADODB.Recordset")
Set ObjConn = Server.CreateObject("ADODB.Connection")

'CommandText
qry = "SELECT campo FROM tabla WHERE campoid = ?"

'Parámetro en orden, solo tenemos uno, el id
Set param = cmd.CreateParameter("id", adInteger, adParamInput, 4, id)
cmd.Parameters.Append(param)


ObjConn.Open strConnect
'Conexion activa
cmd.ActiveConnection = ObjConn
'Tipo de comando
cmd.CommandType = adCmdText
'command text para el comando
cmd.CommandText = qry

'abrimos nuestro recordset
rs.Open cmd
Y eso sería todo...qué crees? que me extendí mucho y no me da más tiempo de implementar el método, así que lo dejaremos para el rato


Saludos
__________________
"El hombre que ha empezado a vivir seriamente por dentro, empieza a vivir más sencillamente por fuera."
-- Ernest Hemingway