


Introduction à Waffle : WAF intégré à l'application pour les applications Go
Introduction
Les pare-feu d'applications Web (WAF) sont depuis longtemps une solution de sécurité standard pour protéger les applications Web. Les WAF basés sur le cloud comme AWS WAF et Cloudflare WAF sont particulièrement populaires en raison de leur facilité de mise en œuvre. Cependant, ils comportent plusieurs défis :
- Compréhension limitée du contexte de l'application
- Taux élevé de faux positifs
- Implémentation de logique personnalisée restreinte
Pour relever ces défis, une nouvelle approche appelée In-app WAF ou RASP (Runtime Application Self-Protection) a retenu l'attention.
Dans cet article, je présenterai Waffle, une bibliothèque permettant d'intégrer les fonctionnalités WAF intégrées à l'application dans les applications Web Go.
- https://sitebatch.github.io/waffle-website
- https://github.com/sitebatch/waffle-go
Qu'est-ce que le WAF/RASP intégré à l'application ?
WAF/RASP intégré à l'application n'est pas destiné à remplacer les WAF cloud existants, mais plutôt à les compléter en intégrant la fonctionnalité WAF directement dans votre application pour une protection améliorée.
Il peut gérer les attaques courantes d'applications Web telles que l'injection SQL et XSS, ainsi que les attaques de logique métier d'application telles que le credential stuffing et les tentatives de force brute.
Le principal avantage est une détection et une prévention précises grâce à une connaissance complète du contexte de la demande.
Considérez cette requête HTTP pour créer un article de blog :
POST /blog/post HTTP/1.1 ... { "title": "What is SQL ?" "body": "SQL example code: `SELECT * FROM users` ..." }
Si votre application utilise des espaces réservés pour construire des instructions SQL en toute sécurité, l'injection SQL n'est pas possible. Cependant, les WAF basés sur le cloud qui s'appuient sur la correspondance de modèles bloqueraient cette requête car elle contient des modèles suspects de type SQL (la chaîne SELECT * FROM soulève des problèmes d'injection SQL).
Les développeurs se retrouvent souvent fastidieux à ajuster les paramètres, les points de terminaison ou les règles WAF pour réduire ces faux positifs. Quelle lourde tâche !
En revanche, In-app WAF / RASP comprend le contexte de la requête. Il reconnaît quand les espaces réservés ne sont pas utilisés et bloque les attaques uniquement lorsque « l'injection SQL est réellement possible ». Cette approche contextuelle entraîne moins de faux positifs et peut même contribuer à atténuer les vulnérabilités du jour zéro.
Implémentation de WAF/RASP dans l'application avec les applications Waffle in Go
Waffle est une bibliothèque qui active la fonctionnalité In-App WAF/RASP dans les applications Web Go.
Voyons comment intégrer Waffle dans votre application et comment il prévient les attaques.
Exemple d'application
Bien que cet exemple utilise le net/http de la bibliothèque standard, Waffle prend également en charge d'autres bibliothèques comme Gin et GORM.
Pour plus de détails, consultez la documentation des bibliothèques prises en charge.
L'application suivante présente une vulnérabilité d'injection SQL dans le point de terminaison /login :
POST /blog/post HTTP/1.1 ... { "title": "What is SQL ?" "body": "SQL example code: `SELECT * FROM users` ..." }
package main import ( "context" "database/sql" "fmt" "net/http" _ "github.com/mattn/go-sqlite3" ) var database *sql.DB func init() { setupDB() } func newHTTPHandler() http.Handler { mux := http.NewServeMux() mux.Handle("/login", http.HandlerFunc(loginController)) return mux } func main() { srv := &http.Server{ Addr: ":8000", Handler: newHTTPHandler(), } srv.ListenAndServe() } func loginController(w http.ResponseWriter, r *http.Request) { email := r.FormValue("email") password := r.FormValue("password") if err := login(r.Context(), email, password); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } w.Write([]byte("Login success")) } func login(ctx context.Context, email, password string) error { // ⚠️ SQL INJECTION VULNERABILITY rows, err := database.QueryContext(ctx, fmt.Sprintf("SELECT * FROM users WHERE email = '%s' AND password = '%s'", email, password)) if err != nil { return err } defer rows.Close() if !rows.Next() { return fmt.Errorf("invalid email or password") } // do something return nil } func setupDB() { db, err := sql.Open("sqlite3", "file::memory:?cache=shared") if err != nil { panic(err) } if _, err := db.Exec("CREATE TABLE users(id int, email text, password text);"); err != nil { panic(err) } if _, err := db.Exec("INSERT INTO users(id, email, password) VALUES(1, 'user@example.com', 'password');"); err != nil { panic(err) } database = db }
Intégration de Waffle pour empêcher l'injection SQL
Intégrons Waffle pour empêcher l'injection SQL :
$ go run . # SQL injection attack $ curl -i -X POST 'http://localhost:8000/login' \ --data "email=user@example.com' OR 1=1--&password=" HTTP/1.1 200 OK Date: Sun, 05 Jan 2025 10:32:50 GMT Content-Length: 13 Content-Type: text/plain; charset=utf-8 Login success
Modifiez main.go comme suit :
$ go get github.com/sitebatch/waffle-go
Les changements sont minimes :
package main import ( "context" "database/sql" "errors" "fmt" "net/http" "github.com/sitebatch/waffle-go" "github.com/sitebatch/waffle-go/action" waffleSQL "github.com/sitebatch/waffle-go/contrib/database/sql" waffleHTTP "github.com/sitebatch/waffle-go/contrib/net/http" _ "github.com/mattn/go-sqlite3" ) var database *sql.DB func init() { setupDB() } func newHTTPHandler() http.Handler { mux := http.NewServeMux() mux.Handle("/login", http.HandlerFunc(loginController)) handler := waffleHTTP.WafMiddleware(mux) return handler } func main() { srv := &http.Server{ Addr: ":8000", Handler: newHTTPHandler(), } // Start waffle with debug mode waffle.Start(waffle.WithDebug()) srv.ListenAndServe() } func loginController(w http.ResponseWriter, r *http.Request) { email := r.FormValue("email") password := r.FormValue("password") if err := login(r.Context(), email, password); err != nil { var actionErr *action.BlockError if errors.As(err, &actionErr) { return } http.Error(w, err.Error(), http.StatusInternalServerError) return } w.Write([]byte("Login success")) } func login(ctx context.Context, email, password string) error { // ⚠️ SQL INJECTION VULNERABILITY rows, err := database.QueryContext(ctx, fmt.Sprintf("SELECT * FROM users WHERE email = '%s' AND password = '%s'", email, password)) if err != nil { return err } defer rows.Close() if !rows.Next() { return fmt.Errorf("invalid email or password") } // do something return nil } func setupDB() { db, err := waffleSQL.Open("sqlite3", "file::memory:?cache=shared") if err != nil { panic(err) } if _, err := db.Exec("CREATE TABLE users(id int, email text, password text);"); err != nil { panic(err) } if _, err := db.Exec("INSERT INTO users(id, email, password) VALUES(1, 'user@example.com', 'password');"); err != nil { panic(err) } database = db }
Maintenant, lorsque nous essayons une attaque par injection SQL, Waffle la bloque :
diff --git a/main.go b/main.go index 90b8197..9fefb06 100644 --- a/main.go +++ b/main.go @@ -3,9 +3,15 @@ package main import ( "context" "database/sql" + "errors" "fmt" "net/http" + "github.com/sitebatch/waffle-go" + "github.com/sitebatch/waffle-go/action" + waffleSQL "github.com/sitebatch/waffle-go/contrib/database/sql" + waffleHTTP "github.com/sitebatch/waffle-go/contrib/net/http" + _ "github.com/mattn/go-sqlite3" ) @@ -19,7 +25,9 @@ func newHTTPHandler() http.Handler { mux := http.NewServeMux() mux.Handle("/login", http.HandlerFunc(loginController)) - return mux + handler := waffleHTTP.WafMiddleware(mux) + + return handler } func main() { @@ -28,6 +36,9 @@ func main() { Handler: newHTTPHandler(), } + // Start waffle with debug mode + waffle.Start(waffle.WithDebug()) + srv.ListenAndServe() } @@ -36,6 +47,11 @@ func loginController(w http.ResponseWriter, r *http.Request) { password := r.FormValue("password") if err := login(r.Context(), email, password); err != nil { + var actionErr *action.BlockError + if errors.As(err, &actionErr) { + return + } + http.Error(w, err.Error(), http.StatusInternalServerError) return } @@ -60,7 +76,7 @@ func login(ctx context.Context, email, password string) error { } func setupDB() { - db, err := sql.Open("sqlite3", "file::memory:?cache=shared") + db, err := waffleSQL.Open("sqlite3", "file::memory:?cache=shared") if err != nil { panic(err) }
Ce code HTML est le message d'erreur renvoyé par défaut par Waffle et ressemble à ceci :
Si vous utilisez des espaces réservés :
Lors de l'utilisation d'espaces réservés, Waffle reconnaît que l'injection SQL n'est pas possible et ne bloquera pas la requête :
$ curl -i -X POST 'http://localhost:8000/login' \ --data "email=user@example.com' OR 1=1--&password=" -i HTTP/1.1 403 Forbidden Date: Sun, 05 Jan 2025 10:38:22 GMT Content-Length: 1574 Content-Type: text/html; charset=utf-8 <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Access Denied</title>
# Fix SQL injection vulnerability diff --git a/main.go b/main.go index 9fefb06..5b482f2 100644 --- a/main.go +++ b/main.go @@ -60,7 +60,7 @@ func loginController(w http.ResponseWriter, r *http.Request) { } func login(ctx context.Context, email, password string) error { - rows, err := database.QueryContext(ctx, fmt.Sprintf("SELECT * FROM users WHERE email = '%s' AND password = '%s'", email, password)) + rows, err := database.QueryContext(ctx, "SELECT * FROM users WHERE email = ? AND password = ?", email, password) if err != nil { return err }
Notez que même dans ce cas, Waffle peut toujours détecter les tentatives d'injection SQL comme un WAF basé sur le cloud (bien qu'il ne la bloque pas) :
# Waffle won't block the request since SQL injection isn't possible $ curl -i -X POST 'http://localhost:8000/login' \ --data "email=user@example.com' OR 1=1--&password=" HTTP/1.1 500 Internal Server Error Content-Type: text/plain; charset=utf-8 X-Content-Type-Options: nosniff Date: Sun, 05 Jan 2025 10:49:05 GMT Content-Length: 26 invalid email or password
Attaques détectées et empêchées par Waffle
Bien que nous ayons démontré la prévention des injections SQL, Waffle peut détecter et prévenir diverses attaques :
- Reconnaissance par des scanners de sécurité connus
- Parcours de répertoire
- XSS
- Injection SQL
- Accès aux fichiers sensibles
- SSRF
- Reprise de compte
Pour plus de détails, consultez la documentation sur la liste des règles.
Les règles sont continuellement mises à jour et les contributions sont les bienvenues.
Conclusion
En intégrant Waffle dans votre application, vous pouvez détecter et prévenir avec précision les attaques.
Pour les guides de mise en œuvre spécifiques au framework et les instructions d'utilisation détaillées, reportez-vous à la section Guides de la documentation.
Waffle est en cours de développement actif. Nous apprécions les commentaires et les contributions.
- https://github.com/sitebatch/waffle-go
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

GohandlesInterfaces etTypeAssertionSEffectively, EnhancingCodeFlexibilityAndRobustness.1) TypeAssertionsallowruntimeTypeCHecking, asseenwithheshapeInterfaceandCirctleTy.2)

GO Language Les erreurs de la langue deviennent plus flexibles et lisibles via Errors.is et Errors. Comme fonctions. 1.Errors.is est utilisé pour vérifier si l'erreur est la même que l'erreur spécifiée et convient au traitement de la chaîne d'erreur. 2. ERRORS. As peut non seulement vérifier le type d'erreur, mais également convertir l'erreur en un type spécifique, ce qui est pratique pour extraire les informations d'erreur. L'utilisation de ces fonctions peut simplifier la logique de gestion des erreurs, mais faire attention à la livraison correcte des chaînes d'erreur et éviter une dépendance excessive pour éviter la complexité du code.

TomakeGoapplicationsRunfasterandMoreEfficiently, useProfilingTools, LeverageConcurrency et ManageMemoryEffective.1) useProfforcpuandMemoryProfilingtodentifyBottleneck

GO'sfutureisbrightwithTrends like improvedtooling, génériques, cloud-nativeadoption, performanceenhancements et webassembly integration, butchallengeSincludemainainingImPlicityAnd Improverrorror.

GoroutinesaConctionnement est en train de savoir-faire, en permettant à la croissance de la pondération.1).

La poursuite de la théorie des fonctionnalités, les réglementations de configurations, l'orperformance a été utile, utilise-to-nection des fonctionnalités.

GoInterfaceSareMethodsignatisesetSeTyPesmustimplement, permettant de permettre à la transfert depolymorphisms avec une information pour laCleaner, modularCode.Eplicite Implicitement satisfait, utile pour lesquelleserrorSandDeCoupling, ButrequireCarefusetoavoidRumeerRorroSedMaintAntainTaidTaipTyPesafety.

Utilisez la fonction Recover () dans GO pour récupérer de la panique. Les méthodes spécifiques sont: 1) Utiliser Recover () pour capturer la panique dans la fonction de différence pour éviter les accidents du programme; 2) Enregistrer les informations d'erreur détaillées pour le débogage; 3) Décidez de reprendre l'opportunité de reprendre l'exécution du programme en fonction de la situation spécifique; 4) Utiliser avec prudence pour éviter d'affecter les performances.


Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

Video Face Swap
Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

Article chaud

Outils chauds

Version Mac de WebStorm
Outils de développement JavaScript utiles

SublimeText3 version anglaise
Recommandé : version Win, prend en charge les invites de code !

Version crackée d'EditPlus en chinois
Petite taille, coloration syntaxique, ne prend pas en charge la fonction d'invite de code

ZendStudio 13.5.1 Mac
Puissant environnement de développement intégré PHP

Télécharger la version Mac de l'éditeur Atom
L'éditeur open source le plus populaire
