Go contra hackers: protección contra inyecciones SQL y XSS en la práctica

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

¿Por qué incluso los desarrolladores de Go caen en las trampas de los hackers?

\n\n

Go es famoso por su velocidad, simplicidad y herramientas de seguridad integradas. Pero consolarse con la frase «escribo en Go, por lo tanto, estoy seguro» es una ilusión peligrosa. Las inyecciones SQL y los ataques XSS no son reliquias del pasado. Todavía hoy derriban sitios web y filtran bases de datos a diario, y Go no es una excepción.

\n\n

El problema es que Go le brinda al desarrollador herramientas potentes, pero no las usa por usted. Puede accidentalmente concatenar una consulta SQL usando fmt.Sprintf o mostrar un comentario de usuario sin escape, y un atacante obtendrá acceso a su base de datos o robará las cookies de los visitantes.

\n\n

En este artículo, analizaremos los dos tipos de ataques más peligrosos: inyecciones SQL y Cross-Site Scripting (XSS), y mostraremos cómo prevenirlos usando Go nativo y bibliotecas populares. Obtendrá no solo teoría, sino plantillas de código listas para usar que puede incorporar a su proyecto hoy mismo.

\n\n

Inyecciones SQL en Go: cómo surgen y cómo eliminarlas de raíz

\n\n

Error típico: concatenación de cadenas

\n\n

Imagine que tiene un endpoint para obtener un usuario por ID. La forma más ingenua (y peligrosa) de escribir la consulta es así:

\n\n
package main\n\nimport (\n    "database/sql"\n    "fmt"\n    "log"\n    _ "github.com/lib/pq"\n)\n\nfunc getUserByID(db *sql.DB, userID string) {\n    // ¡PELIGROSO! Concatenación de cadenas\n    query := fmt.Sprintf("SELECT id, name, email FROM users WHERE id = '%s'", userID)\n    rows, err := db.Query(query)\n    if err != nil {\n        log.Fatal(err)\n    }\n    defer rows.Close()\n    // ... procesamiento\n}
\n\n

Si un atacante pasa la cadena 1' OR '1'='1 en userID, la consulta se convierte en:

\n\n
SELECT id, name, email FROM users WHERE id = '1' OR '1'='1'
\n\n

¡Voilà! Obtendrá todos los usuarios de la base de datos. Y si ingresa 1'; DROP TABLE users; --, perderá la tabla.

\n\n

Solución: consultas parametrizadas (sentencias preparadas)

\n\n

El controlador de Go para PostgreSQL, MySQL y SQLite admite sentencias preparadas. Estas separan el código SQL de los datos, y el controlador escapa automáticamente los caracteres peligrosos.

\n\n
func getUserByIDSafe(db *sql.DB, userID string) {\n    // SEGURO: consulta parametrizada\n    query := "SELECT id, name, email FROM users WHERE id = $1"\n    rows, err := db.Query(query, userID)\n    if err != nil {\n        log.Fatal(err)\n    }\n    defer rows.Close()\n    // ... procesamiento\n}
\n\n

Observe el $1 — es un marcador de posición para el primer argumento. En MySQL se usa el símbolo ?. Ahora, incluso si userID contiene 1' OR '1'='1, el controlador lo tratará como un valor de cadena, no como parte del código SQL.

\n\n

Trabajo con el paquete sqlx

\n\n

La biblioteca github.com/jmoiron/sqlx hace que el código sea aún más limpio. Admite parámetros con nombre y escaneo automático a estructuras:

\n\n
import "github.com/jmoiron/sqlx"\n\ntype User struct {\n    ID    int    `db:"id"`\n    Name  string `db:"name"`\n    Email string `db:"email"`\n}\n\nfunc getUserByIDSqlx(db *sqlx.DB, userID string) (*User, error) {\n    user := &User{}\n    // Parámetro con nombre :id\n    err := db.Get(user, "SELECT * FROM users WHERE id = :id", sqlx.Named("id", userID))\n    if err != nil {\n        return nil, err\n    }\n    return user, nil\n}
\n\n

Importante: incluso si usa un ORM como GORM o Ent, asegúrese de que esté configurado para usar sentencias preparadas. Algunas versiones antiguas de ORM permitían consultas «en bruto».

\n\n

XSS en Go: cuando su sitio web se dispara en el pie

\n\n

Cómo ocurre un ataque XSS

\n\n

XSS (Cross-Site Scripting) ocurre cuando inserta contenido de usuario en una página sin escape. Un

Blogs

Book Recommendations