Sécurité des applications Go : top 10 des vulnérabilités et méthodes de protection
Le langage Go (Golang) a gagné en popularité grâce à ses hautes performances, sa simplicité et ses mécanismes de sécurité intégrés. Cependant, comme tout autre langage, il ne protège pas le développeur contre toutes les menaces possibles. Les erreurs de conception, le manque d'attention lors du traitement de données externes et une mauvaise utilisation des bibliothèques standard peuvent entraîner de graves vulnérabilités. Dans cet article, nous allons analyser le top 10 des vulnérabilités les plus critiques des applications Go, fournir des exemples de code et expliquer comment les éviter.
1. Injections SQL (SQL Injection)
Malgré la présence du package database/sql, les développeurs commettent souvent l'erreur de concaténer des chaînes lors de la construction de requêtes SQL. Il s'agit d'une vulnérabilité classique qui permet à un attaquant d'exécuter du code SQL arbitraire.
Code non sécurisé :
// DANGEREUX : concaténation de chaînesfunc 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) // ...}Code sécurisé avec paramétrage :
func getUser(w http.ResponseWriter, r *http.Request) { username := r.URL.Query().Get("username") // Utilisation de placeholders query := "SELECT * FROM users WHERE username = $1" rows, err := db.Query(query, username) // ...}Recommandation : Utilisez toujours des requêtes paramétrées. Ne concaténez jamais les entrées utilisateur dans des chaînes SQL.
2. Cross-Site Scripting (XSS)
Si votre application Go génère du HTML côté serveur (par exemple, avec html/template), vous devez échapper la sortie. Le package intégré text/template ne le fait pas.
Code non sécurisé :
// L'utilisation de text/template est dangereusetmpl, _ := template.New("test").Parse("<h1>{{.Name}}</h1>")tmpl.Execute(w, map[string]string{"Name": "<script>alert('XSS')</script>"})Code sécurisé :
// Utilisez toujours html/template pour les templates HTMLimport "html/template"tmpl, _ := template.New("test").Parse("<h1>{{.Name}}</h1>")tmpl.Execute(w, map[string]string{"Name": "<script>alert('XSS')</script>"})// Sortie : <script>alert('XSS')</script>Recommandation : Pour travailler avec du HTML, utilisez uniquement html/template. Validez et échappez toujours les entrées utilisateur, surtout si elles sont affichées dans des attributs de balises ou du JavaScript.
3. Race Condition (Condition de concurrence)
Go est un langage concurrent, et la race condition est l'un des problèmes les plus fréquents. Elle peut entraîner une corruption des données, des fuites mémoire et des plantages inattendus.
Code non sécurisé :
var counter int
func increment() { for i := 0; i < 1000; i++ { counter++ // Opération non atomique }}
func main() { go increment() go increment()}Code sécurisé avec 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()}Recommandation : Utilisez sync.Mutex, sync.RWMutex ou des opérations atomiques (sync/atomic). Lancez les tests avec le flag -race pour détecter les conditions de concurrence.
4. Path Traversal (Dépassement de chemin)
La vulnérabilité survient lorsque l'application utilise une entrée utilisateur pour former un chemin d'accès à un fichier sans vérification appropriée.
Code non sécurisé :
func serveFile(w http.ResponseWriter, r *http.Request) { f