Cuando accesamos a la base de datos buscando información o bien insertando nueva información corremos el riesgo de ser atacados mediante SQL Injection.
¿Por qué o cómo pasa esto?
Cuando un usuario introduce información en los formularios que hemos creado en nuestra página, éste texto es concatenado de algún modo en sentencias SQL para realizar queries. Por ejemplo, cuando un usuario escribe su UserName y su Password formamos una sentencia como esta:
SELECT * FROM Usuarios WHERE UserName='usr1' AND Password='pwd1'
Como vemos, las comillas simples delimitan cadenas en la sentencia.
¿Qué pasaría si el usuario en lugar de escribir [usr1] escribiera ['; DROP--]
La sentencia sería:
SELECT * FROM Usuarios WHERE UserName=''; DROP--' AND Password='pwd1'
Seguramente el usuario verá un error en la aplicación. Pero observemos:
1. El punto y coma provocó finalizar una sentencia
2. Los dos guiones provocan que el texto siguiente sea un simple comentario
3. Drop podría ser utilizado para borrar completamente una tabla.
En fin, no queremos ahondar en este tema, pero sí prevenir este tipo de ataques, así que en el caso de nuestras aplicaciones que corren en Web podemos utilizar dos rutinas. Una de ellas que convierta cualquier texto en código HTML, incluyendo la comilla simple, y sólo así guardar la información en la base de datos. La otra tomará texto de la base de datos, que viene en formato HTML y de ser necesario la decodificará para mostrarla correctamente (en controles textbox principalmente).
Function TextFromBD(ByVal StrText As String, ByVal BlnType As Boolean) As String
'BlnType: (0 - Para mostrar en HTML) (1 - Para mostrar en TextBox)
If BlnType = True Then
StrText = Server.HtmlDecode(StrText)
StrText = Replace(StrText, "'", "")
StrText = Replace(StrText, "", "")
StrText = Replace(StrText, "&#lt", "")
StrText = Replace(StrText, "&#l", "")
StrText = Replace(StrText, "&#gt", "")
StrText = Replace(StrText, "&#g", "")
StrText = Replace(StrText, "&#", "")
Else
StrText = Replace(StrText, ControlChars.CrLf, "<br>")
StrText = Replace(StrText, ControlChars.Tab, " ")
End If
Return StrText
End Function
Function TextToBD(ByVal StrText As String, ByVal IntLeft As String) As String
StrText = Trim(StrText)
StrText = Server.HtmlEncode(StrText)
StrText = Replace(StrText, "'", "'")
StrText = Replace(Replace(StrText, "<", "<"), ">", ">")
If IntLeft > 0 Then StrText = Left(StrText, IntLeft)
Return StrText
End Function
jueves, agosto 17, 2006
Expresiones regulares
Para validar URLs:
http(s)?://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?
Para validar correo:
^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$
Para validar cadenas sin caracteres especiales:
^[a-zA-Z0-9ñÑáéíóúÁÉÍÓÚ]+$
Para validar RFC
^[a-zA-Z]{3,4}(\d{6})((\D|\d){3})?$
Función general para utilizar las expresiones:
Ejemplifiquemos con la expresión regular que valida el correo. Esta función regresará False cuando strIn sea un correo no válido.
Function IsValidEmail(ByVal strIn As String) As Boolean
Return Regex.IsMatch(strIn, ("^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$"))
End Function
http(s)?://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?
Para validar correo:
^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$
Para validar cadenas sin caracteres especiales:
^[a-zA-Z0-9ñÑáéíóúÁÉÍÓÚ]+$
Para validar RFC
^[a-zA-Z]{3,4}(\d{6})((\D|\d){3})?$
Función general para utilizar las expresiones:
Ejemplifiquemos con la expresión regular que valida el correo. Esta función regresará False cuando strIn sea un correo no válido.
Function IsValidEmail(ByVal strIn As String) As Boolean
Return Regex.IsMatch(strIn, ("^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$"))
End Function
¿Cómo crear un DataSet que contenga llave primaria?
Supongamos que requerimos una tabla que tenga dos columnas: ID y Nombre. La primera columna (ID) deberá ser llave primaria y además será de tipo "UniqueIdentifier" de modo que nos permita almacenar valores alfanuméricos y que no se repitan.
Dim dsProcesadas As New DataSet("MiDataSet")
Dim newTable1 As New DataTable("MiTabla1")
dsProcesadas.Tables.Add(newTable1)
newTable1.Columns.Add("ID", Type.GetType("System.Guid"), "")
newTable1.Columns.Add("Nombre", Type.GetType("System.String"), "")
Dim key(0) As DataColumn
key(0) = newTable1.Columns("ID")
newTable1.PrimaryKey = key
¿Cómo añado registros?
Es muy fácil, podemos crear una rutina muy aparte que lo haga y que reciba como parámetros los valores de las columnas. No nos confundamos, veamos el ejemplo:
Sub CreaRegistro(ByVal GuidID As Guid,ByVal StrNombre As String, ByRef ds As DataSet)
Dim row As DataRow
row = ds.Tables("MiTabla1").NewRow
ds.Tables("MiTabla1").Rows.Add(row)
row("ID") = GuidID
row("Nombre") = StrNombre
End Sub
Juntemos todo el código en la siguiente función:
<script runat="server">
Sub Page_Load()
Dim ds As new DataSet
ds = GetDataSetPrincipal()
'# A PARTIR DE AQUI PODEMOS HACER Y DESHACER
'# EN EL DATASET
End Sub
Function GetDataSetPrincipal() As DataSet
Dim ds As New DataSet("MiDataSet")
Dim newTable1 As New DataTable("MiTabla1")
ds.Tables.Add(newTable1)
newTable1.Columns.Add("ID", Type.GetType("System.Guid"), "")
newTable1.Columns.Add("Nombre", Type.GetType("System.String"), "")
Dim key(0) As DataColumn
key(0) = newTable1.Columns("ID")
newTable1.PrimaryKey = key
Dim GuidJuan As Guid = New Guid("9CD8769C-7DEB-40A0-828E-DBB03556B451")
Dim GuidPedro As Guid = New Guid("9CD8769C-7DEB-40A0-828E-DBB03556B452")
Dim GuidAna As Guid = New Guid("9CD8769C-7DEB-40A0-828E-DBB03556B453")
CreaRegistro(GuidJuan, "Juan" , ds)
CreaRegistro(GuidPedro, "Pedro" , ds)
CreaRegistro(GuidAna, "Ana" , ds)
Return ds
End Function
Sub CreaRegistro(ByVal GuidID As Guid,ByVal StrNombre As String, ByRef ds As DataSet)
Dim row As DataRow
row = ds.Tables("MiTabla1").NewRow
ds.Tables("MiTabla1").Rows.Add(row)
row("ID") = GuidID
row("Nombre") = StrNombre
End Sub
</script>
Dim dsProcesadas As New DataSet("MiDataSet")
Dim newTable1 As New DataTable("MiTabla1")
dsProcesadas.Tables.Add(newTable1)
newTable1.Columns.Add("ID", Type.GetType("System.Guid"), "")
newTable1.Columns.Add("Nombre", Type.GetType("System.String"), "")
Dim key(0) As DataColumn
key(0) = newTable1.Columns("ID")
newTable1.PrimaryKey = key
¿Cómo añado registros?
Es muy fácil, podemos crear una rutina muy aparte que lo haga y que reciba como parámetros los valores de las columnas. No nos confundamos, veamos el ejemplo:
Sub CreaRegistro(ByVal GuidID As Guid,ByVal StrNombre As String, ByRef ds As DataSet)
Dim row As DataRow
row = ds.Tables("MiTabla1").NewRow
ds.Tables("MiTabla1").Rows.Add(row)
row("ID") = GuidID
row("Nombre") = StrNombre
End Sub
Juntemos todo el código en la siguiente función:
<script runat="server">
Sub Page_Load()
Dim ds As new DataSet
ds = GetDataSetPrincipal()
'# A PARTIR DE AQUI PODEMOS HACER Y DESHACER
'# EN EL DATASET
End Sub
Function GetDataSetPrincipal() As DataSet
Dim ds As New DataSet("MiDataSet")
Dim newTable1 As New DataTable("MiTabla1")
ds.Tables.Add(newTable1)
newTable1.Columns.Add("ID", Type.GetType("System.Guid"), "")
newTable1.Columns.Add("Nombre", Type.GetType("System.String"), "")
Dim key(0) As DataColumn
key(0) = newTable1.Columns("ID")
newTable1.PrimaryKey = key
Dim GuidJuan As Guid = New Guid("9CD8769C-7DEB-40A0-828E-DBB03556B451")
Dim GuidPedro As Guid = New Guid("9CD8769C-7DEB-40A0-828E-DBB03556B452")
Dim GuidAna As Guid = New Guid("9CD8769C-7DEB-40A0-828E-DBB03556B453")
CreaRegistro(GuidJuan, "Juan" , ds)
CreaRegistro(GuidPedro, "Pedro" , ds)
CreaRegistro(GuidAna, "Ana" , ds)
Return ds
End Function
Sub CreaRegistro(ByVal GuidID As Guid,ByVal StrNombre As String, ByRef ds As DataSet)
Dim row As DataRow
row = ds.Tables("MiTabla1").NewRow
ds.Tables("MiTabla1").Rows.Add(row)
row("ID") = GuidID
row("Nombre") = StrNombre
End Sub
</script>
Suscribirse a:
Entradas (Atom)