In this article
Lo simple no siempre es seguro: evita este patrón de XSS en Golang
Los ataques de cross-site scripting (XSS) son una vulnerabilidad web frecuente que permite a los atacantes inyectar scripts maliciosos en páginas web que ven otros usuarios. Podrías pensar que mantener las cosas simples daría como resultado un código más seguro: sin dependencias de terceros y con menos abstracciones. Parece ideal, pero ¿lo es?
En este artículo veremos un servidor web sencillo en Golang y explicaremos por qué lo simple no siempre es seguro.
Acerca de los ataques de cross-site scripting
El cross-site scripting (XSS) consiste en scripts que suelen robar datos de usuarios, secuestrar sesiones o desfigurar sitios web. Aunque Golang ofrece herramientas sólidas para el desarrollo web, no es inmune a las vulnerabilidades de XSS si no se toman las precauciones adecuadas.
Ejemplo de cross-site scripting en Golang
Una fuente frecuente de vulnerabilidades de XSS es insertar directamente en la salida HTML datos proporcionados por el usuario, sin una sanitización adecuada ni otros controles de seguridad. Como referencia, el control de seguridad eficaz no siempre es la sanitización, sino la codificación de salida.
Un ejemplo de aplicación de Go es aquella que recibe datos de un usuario mediante un campo de formulario o un parámetro de URL (como una cadena de consulta) y luego los inserta directamente en una página HTML como parte de la respuesta HTTP. Un atacante podría inyectar código JavaScript malicioso (de ahí el nombre cross-site scripting). Cuando otro usuario ve la página, su navegador ejecuta el script inyectado, lo que puede poner en riesgo sus datos o su sesión.
En los servidores HTTP de Golang, un error común es usar fmt.Fprint o funciones similares para escribir directamente en la respuesta HTTP datos proporcionados por el usuario. Considera el siguiente fragmento de código:
http.HandleFunc("/greet", func(w http.ResponseWriter, r *http.Request) {
name := r.URL.Query().Get("name")
response := fmt.Sprintf("<html><body><h1>Hello, %s!</h1></body></html>", name)
fmt.Fprint(w, response)
})Si un usuario establece la cadena de consulta name con una entrada como <script>alert('XSS!')</script>, este código inyectará el código JavaScript alert() en la página y demostrará un ataque XSS básico. La función fmt.Sprintf no escapa automáticamente las entidades HTML, por lo que la aplicación queda vulnerable.
Ese fragmento de código de Golang forma parte de un desafío de seguridad de código abierto. Snyk importó este repositorio de código y pudo detectar la presencia de datos de entrada sin sanitizar provenientes de la URL de la solicitud, así como rastrear cómo llegan a la llamada insegura a la función fmt.Fprint, que renderiza la cadena de la plantilla HTML. El análisis completo del código fuente y de la ruta del código de Snyk SAST muestra los hallazgos con más detalle:

Cómo corregir el XSS en Golang
El ejemplo vulnerable de Golang anterior resalta la necesidad de escapar o sanitizar correctamente las entradas de usuario antes de incluirlas en las respuestas HTML.
Escapar código HTML potencialmente peligroso significa que el código de la aplicación o la dependencia de terceros utilizada debe codificar determinadas entradas del usuario para evitar que se interpreten directamente como elementos del DOM HTML. Por ejemplo, los frameworks de frontend como React o Vue convierten el carácter < en su entidad HTML equivalente: <.
¿Significa esto que siempre debes depender de dependencias de terceros? Bueno, no, pero si las monitoreas y analizas activamente para detectar vulnerabilidades de seguridad y les das el mantenimiento adecuado con actualizaciones automatizadas, es más fácil controlar el riesgo de seguridad. También existe el riesgo de usar la biblioteca de forma incorrecta y generar una vulnerabilidad.
¿Qué hay de los problemas de código seguro en Golang? Snyk ofrece un amplio soporte para Go en lo que respecta al código Go, las dependencias de Go y los administradores de paquetes.
Herramienta gratuita en línea para revisar código
Protege tu código antes de tu próximo commit.