Segurança de aplicações Go: top 10 vulnerabilidades

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Segurança de aplicações Go: top 10 vulnerabilidades



Go (Golang) é uma linguagem compilada, estaticamente tipada, criada no Google. Graças ao suporte embutido para concorrência, alta performance e modelo de memória simples, tornou-se popular para a criação de microsserviços, API gateways, aplicações cloud e ferramentas DevOps. No entanto, como qualquer outra linguagem, Go não está imune a erros de segurança. Desenvolvedores frequentemente confiam na "segurança por padrão", o que leva ao surgimento de vulnerabilidades graves. Neste artigo, vamos analisar as top 10 questões de segurança mais críticas em aplicações Go e mostrar como evitá-las.



1. Injeção de SQL (SQL Injection)



Apesar de o Go fornecer drivers de banco de dados poderosos (database/sql), desenvolvedores frequentemente cometem o erro clássico — concatenação de strings ao formar consultas.



Código vulnerável:

package main

import ( "database/sql" "fmt" _ "github.com/lib/pq")

func getUser(db *sql.DB, username string) { // Nunca faça isso! query := fmt.Sprintf("SELECT * FROM users WHERE username = '%s'", username) rows, _ := db.Query(query) // ...}


Solução: Use consultas parametrizadas (prepared statements).



func getUserSafe(db *sql.DB, username string) {    query := "SELECT * FROM users WHERE username = $1"    rows, err := db.Query(query, username)    if err != nil {        // Tratamento de erro    }    // ...}


A parametrização escapa automaticamente caracteres especiais, tornando a injeção impossível.



2. Cross-Site Scripting (XSS)



Go é frequentemente usado para o backend de aplicações web. Se você retornar a entrada do usuário sem escapá-la, estará abrindo caminho para ataques XSS.



Código vulnerável (usando fmt.Fprintf):

http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {    name := r.URL.Query().Get("name")    fmt.Fprintf(w, "<h1>Olá, %s!</h1>", name) // XSS!})


Solução: Use o pacote html/template para escapamento automático.



import "html/template"

http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { tmpl := template.Must(template.New("index").Parse("<h1>Olá, {{.}}!</h1>")) name := r.URL.Query().Get("name") tmpl.Execute(w, name) // Seguro})


O template engine html/template escapa automaticamente contextos HTML, JavaScript e CSS.



3. Condições de Corrida (Race Conditions)



Go é famoso por sua concorrência leve (goroutines e canais). No entanto, o uso incorreto de recursos compartilhados (como maps ou contadores) sem sincronização leva a data races.



Código vulnerável:

var counter int

func increment() { for i := 0; i < 1000; i++ { counter++ // Não atômico! }}

func main() { go increment() go increment()}


Solução: Use mutexes (sync.Mutex) ou operações atômicas (sync/atomic).



import "sync"

var ( counter int mu sync.Mutex)

func increment() { for i := 0; i < 1000; i++ { mu.Lock() counter++ mu.Unlock() }}


Sempre execute testes com a flag -race: go test -race.



4. Vazamentos de Memória e Goroutines (Memory & Goroutine Leaks)



Uma das vulnerabilidades mais traiçoeiras em Go são as goroutines "esquecidas". Se uma goroutine bloqueia para sempre (por exemplo, aguardando dados de um canal que nunca será fechado), isso leva a vazamento de memória e falha da aplicação.



Exemplo de vazamento:

Blogs

Book Recommendations