Segurança de aplicações Go: top 10 vulnerabilidades e métodos de proteção
A linguagem Go (Golang) ganhou popularidade devido ao seu alto desempenho, simplicidade e mecanismos de segurança integrados. No entanto, como qualquer outra linguagem, ela não protege o desenvolvedor de todas as ameaças possíveis. Erros de design, descuido ao trabalhar com dados externos e uso incorreto de bibliotecas padrão podem levar a vulnerabilidades graves. Neste artigo, analisaremos as 10 vulnerabilidades mais críticas de aplicações Go, forneceremos exemplos de código e explicaremos como evitá-las.
1. Injeção de SQL (SQL Injection)
Apesar da existência do pacote database/sql, os desenvolvedores frequentemente cometem o erro de concatenar strings ao construir consultas SQL. Esta é uma vulnerabilidade clássica que permite que um invasor execute código SQL arbitrário.
Código inseguro:
// PERIGOSO: concatenação de stringsfunc getUser(w http.ResponseWriter, r *http.Request) { username := r.URL.Query().Get("username") query := "SELECT * FROM users WHERE username = '" + username + "'" rows, err := db.Query(query) // ...}Código seguro com parametrização:
func getUser(w http.ResponseWriter, r *http.Request) { username := r.URL.Query().Get("username") // Usamos placeholders query := "SELECT * FROM users WHERE username = $1" rows, err := db.Query(query, username) // ...}Recomendação: Use sempre consultas parametrizadas. Nunca concatene entrada do usuário em strings SQL.
2. Cross-Site Scripting (XSS)
Se sua aplicação Go renderiza HTML no servidor (por exemplo, usando html/template), é necessário escapar a saída. O pacote integrado text/template não faz isso.
Código inseguro:
// Usar text/template é perigosotmpl, _ := template.New("test").Parse("<h1>{{.Name}}</h1>")tmpl.Execute(w, map[string]string{"Name": "<script>alert('XSS')</script>"})Código seguro:
// Sempre use html/template para templates HTMLimport "html/template"tmpl, _ := template.New("test").Parse("<h1>{{.Name}}</h1>")tmpl.Execute(w, map[string]string{"Name": "<script>alert('XSS')</script>"})// Saída: <script>alert('XSS')</script>Recomendação: Para trabalhar com HTML, use apenas html/template. Sempre valide e escape a entrada do usuário, especialmente se ela for exibida em atributos de tags ou JavaScript.
3. Race Condition (Condição de corrida)
Go é uma linguagem com concorrência, e race condition é um dos problemas mais comuns. Pode levar à corrupção de dados, vazamentos de memória e falhas inesperadas.
Código inseguro:
var counter int
func increment() { for i := 0; i < 1000; i++ { counter++ // Operação não atômica }}
func main() { go increment() go increment()}Código seguro com mutex:
var ( counter int mu sync.Mutex)
func increment() { for i := 0; i < 1000; i++ { mu.Lock() counter++ mu.Unlock() }}
func main() { go increment() go increment()}Recomendação: Use sync.Mutex, sync.RWMutex ou operações atômicas (sync/atomic). Execute testes com a flag -race para detectar condições de corrida.
4. Path Traversal (Varredura de diretório)
A vulnerabilidade ocorre quando a aplicação usa entrada do usuário para formar um caminho de arquivo sem a devida verificação.
Código inseguro:
func serveFile(w http.ResponseWriter, r *http.Request) { f