Seguridad de aplicaciones Go: top 10 vulnerabilidades para principiantes
\n\nGo (Golang) es uno de los lenguajes más populares para crear servicios web de alto rendimiento, microservicios y aplicaciones de red. Sin embargo, como cualquier otro lenguaje, Go requiere un enfoque cuidadoso en la seguridad. Si recién estás comenzando a aprender Go, es importante conocer las principales vulnerabilidades que pueden acechar a tu aplicación. En este artículo, analizaremos las 10 amenazas más comunes y mostraremos cómo evitarlas.
\n\n1. Inyección SQL (SQL Injection)
\n\nLa inyección SQL es una de las vulnerabilidades más antiguas y peligrosas. Ocurre cuando la entrada del usuario se inserta directamente en una consulta SQL.
\n\nEjemplo de código vulnerable:
\nfunc getUser(db *sql.DB, id string) (*User, error) {\n row := db.QueryRow("SELECT * FROM users WHERE id = " + id)\n // ...\n}\n\nCómo corregirlo:
\nUtilice consultas parametrizadas:
\nfunc getUser(db *sql.DB, id string) (*User, error) {\n row := db.QueryRow("SELECT * FROM users WHERE id = $1", id)\n // ...\n}\n\n2. Cross-Site Scripting (XSS)
\n\nXSS ocurre cuando la entrada del usuario sin escapar se muestra en una página web. En Go, esto suele ocurrir al usar html/template en lugar de text/template.
Ejemplo de código vulnerable:
\nfmt.Fprintf(w, "<p>Hola, %s</p>", r.URL.Query().Get("name"))\n\nCómo corregirlo:
\nUtilice html/template para el escape automático:
tmpl := template.Must(template.New("").Parse("<p>Hola, {{.}}</p>"))\ntmpl.Execute(w, r.URL.Query().Get("name"))\n\n3. Cross-Site Request Forgery (CSRF)
\n\nLos ataques CSRF obligan al usuario a realizar una acción no deseada en un sitio donde está autenticado. Las aplicaciones Go a menudo olvidan la protección contra CSRF.
\n\nSolución:
\nUtilice la librería gorilla/csrf o implemente su propio middleware:
import "github.com/gorilla/csrf"\n\nfunc main() {\n r := mux.NewRouter()\n r.Use(csrf.Protect([]byte("clave-de-32-bytes")))\n // ...\n}\n\n4. Manejo inseguro de errores
\n\nUn error común es devolver al usuario mensajes de error del sistema que pueden revelar la estructura interna de la aplicación.
\n\nEjemplo de código vulnerable:
\nif err != nil {\n http.Error(w, err.Error(), http.StatusInternalServerError)\n}\n\nCómo corregirlo:
\nif err != nil {\n log.Printf("Error: %v", err)\n http.Error(w, "Error interno del servidor", http.StatusInternalServerError)\n}\n\n5. Fuga de información a través de cabeceras
\n\nPor defecto, el servidor Go puede revelar la versión de Go, el tipo de servidor y otra información del sistema.
\n\nSolución:
\ntype secureHandler struct {\n next http.Handler\n}\n\nfunc (h *secureHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {\n w.Header().Set("X-Content-Type-Options", "nosniff")\n w.Header().Set("X-Frame-Options", "DENY")\n w.Header().Set("X-XSS-Protection", "1; mode=block")\n h.next.ServeHTTP(w, r)\n}\n\n6. Manejo incorrecto de gorutinas
\n\nLas gorutinas son una herramienta poderosa de Go, pero su uso incorrecto puede provocar condiciones de carrera (race conditions) y fugas de memoria.
\n\nEjemplo de código vulnerable:
\nvar counter int\nfor i := 0; i < 1000; i++ {\n go func() {\n counter++ // race condition!\n }()\n}\n\nCómo corregirlo:
\nvar mu sync.Mutex\nvar counter int\nfor i := 0; i < 1000; i++ {\n go func() {\n mu.Lock()\n counter++\n mu.Unlock()\n }()\n}\n\n7. Almacenamiento inseguro de contraseñas
\n\nAlmacenar contraseñas en texto plano o usando hashes débiles (MD5, SHA1) es un grave error.<