Segurança de aplicações Go: top 10 vulnerabilidades para iniciantes
Go (Golang) é conhecido por seu desempenho e mecanismos de segurança integrados, como tipagem forte e gerenciamento automático de memória. No entanto, como qualquer outra linguagem, ele não protege o desenvolvedor de erros lógicos, tratamento incorreto de entrada ou configuração insegura. Neste artigo, vamos analisar as top 10 vulnerabilidades que desenvolvedores Go iniciantes mais enfrentam e mostrar como evitá-las.
1. Injeção de SQL (SQL Injection)
A vulnerabilidade mais comum em aplicações web. Ela ocorre quando a entrada do usuário é concatenada diretamente em uma consulta SQL.
Código perigoso:
username := r.URL.Query().Get("username")query := fmt.Sprintf("SELECT * FROM users WHERE name='%s'", username)rows, err := db.Query(query)Código seguro (usando consultas parametrizadas):
username := r.URL.Query().Get("username")query := "SELECT * FROM users WHERE name=$1"rows, err := db.Query(query, username)Dica: Sempre use placeholders ($1, ? ou @p1) dependendo do seu banco de dados. Nunca construa consultas usando fmt.Sprintf com dados do usuário.
2. Cross-Site Scripting (XSS)
A vulnerabilidade ocorre quando a aplicação exibe entrada do usuário não validada em código HTML. Em Go, isso acontece frequentemente ao usar html/template sem escapamento.
Código perigoso:
tmpl := template.Must(template.New("page").Parse("<h1>{{.}}</h1>"))tmpl.Execute(w, r.URL.Query().Get("name")) // <script>alert('xss')</script>O pacote embutido html/template escapa automaticamente a saída, então no caso padrão você está protegido. Mas tome cuidado com as funções template.HTML — elas desativam o escapamento.
Abordagem segura: Use text/template apenas para dados textuais, e para web use html/template. Evite usar template.HTML a menos que seja extremamente necessário.
3. Race Conditions (Condição de corrida)
Go usa goroutines ativamente, e se várias goroutines leem e escrevem em uma mesma variável simultaneamente sem sincronização, ocorre uma condição de corrida. Isso pode levar a um estado incorreto da aplicação e vazamento de dados.
Código perigoso:
var counter intfor i := 0; i < 1000; i++ { go func() { counter++ // Inseguro! }()}Código seguro (usando mutex):
var ( counter int mu sync.Mutex)for i := 0; i < 1000; i++ { go func() { mu.Lock() counter++ mu.Unlock() }()}Dica: Sempre use sync.Mutex, sync.RWMutex ou operações atômicas (sync/atomic) ao trabalhar com dados compartilhados. Execute testes com a flag -race para detectar condições de corrida.
4. Path Traversal (Ataque de caminho)
A vulnerabilidade permite que um invasor leia arquivos fora do diretório permitido, usando caracteres ../.
Código perigoso:
filename := r.URL.Query().Get("file")data, _ := os.ReadFile("/data/" + filename) // /data/../../etc/passwdCódigo seguro (limpeza do caminho):
filename := r.URL.Query().Get("file")cleanPath := filepath.Clean("/data/" + filename)if !strings.HasPrefix(cleanPath, "/data/") { http.Error(w, "Invalid path", http.StatusBadRequest) return}data, _ := os.ReadFile(cleanPath)Dica: Use