Hoy los sitios web tienen mucho contenido dinámico en orden de mejorar la experiencia de usuario, lo que significa que debemos proveer información dinámica en función de cada comportamiento individual, desafortunadamente, los sitios web dinámicos son suceptibles a ataques maliciosos conocidos como "Cross site scripting" (abreviado "XSS"). Los sitios web estáticos no son vulnerables a este tipo de ataque.
Los atacantes usualmente inyectan código malicioso como Javascript, VBScript, ActiveX o Flash en sitios que tienen vulnerabilidades. Una vez que han conseguido enyectar sus scripts, la información del usuario puede ser robada y tu sitio web puede ser inundado de Spam. Los atacantes también pueden cambiar las configuraciones de los usuarios como sea que ellos quieran.
Si deseas prevenir este tipo de ataques, deberías combinar las siguientes dos aproximaciones
- Validar toda la información de los usuarios, que discutimos en la sección pasada.
- Manejar cuidadosamente la información enviada por los clientes en orden de prevenir cualquier inyección de scripts hecha desde los navegadores.
Entonces ¿Cómo podemos haces estas dos cosas en Go? Afortunadamente, el paquete http/template
tiene algunas funciones que nos permiten escapar los datos como sigue:
func HTMLEscape(w io.Writer, b []byte)
escapa b to w.func HTMLEscapeString(s string) string
retorna una cadena después de escaparla de sfunc HTMLEscaper(args ...interface{}) string
retorna una cadena después de escaparla de algunos argumentos.
Vamos a cambiar el ejemplo de la sección 4.1:
fmt.Println("username:", template.HTMLEscapeString(r.Form.Get("username"))) // Imprime en el lado del servidor
fmt.Println("password:", template.HTMLEscapeString(r.Form.Get("password")))
template.HTMLEscape(w, []byte(r.Form.Get("username"))) // Respuesta a los clientes
Si alguien trata de ingresar el nombre de usuario como <script>alert()</script>
podremos ver el siguiente contenido en el navegador.
Figure 4.3 JavaScript después del escape
Las funciones en el paquete html/template
nos ayudan a escapar todas las etiquetas HTML. Y ¿qué pasa si queremos imprimir <script>alert()</script>
en los navegarores? Deberías usar el paquete text/template
.
import "text/template"
...
t, err := template.New("foo").Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)
err = t.ExecuteTemplate(out, "T", "<script>alert('you have been pwned')</script>")
Salida:
Hello, <script>alert('you have been pwned')</script>!
O puedes usar el tipo template.HTML
:
El contenido variable no va a ser escapado si es del tipo template.HTML
Variable content will not be escaped if its type is template.HTML
.
import "html/template"
...
t, err := template.New("foo").Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)
err = t.ExecuteTemplate(out, "T", template.HTML("<script>alert('you have been pwned')</script>"))
Salida:
Hello, <script>alert('you have been pwned')</script>!
Un ejemplo mas de escape:
import "html/template"
...
t, err := template.New("foo").Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)
err = t.ExecuteTemplate(out, "T", "<script>alert('you have been pwned')</script>")
Salida:
Hello, <script>alert('you have been pwned')</script>!
- Índice
- Sección anterior: Verificando las entradas
- Siguiente sección: Envíos duplicados