Einführung in Waffle: In-App-WAF für Go-Anwendungen
Einführung
Web Application Firewalls (WAF) sind seit langem eine Standard-Sicherheitslösung zum Schutz von Webanwendungen. Cloudbasierte WAFs wie AWS WAF und Cloudflare WAF erfreuen sich aufgrund ihrer einfachen Implementierung besonders großer Beliebtheit. Sie bringen jedoch mehrere Herausforderungen mit sich:
- Eingeschränktes Verständnis des Anwendungskontexts
- Hohe Rate falsch positiver Ergebnisse
- Eingeschränkte benutzerdefinierte Logikimplementierung
Um diese Herausforderungen anzugehen, hat ein neuer Ansatz namens In-App WAF oder RASP (Runtime Application Self-Protection) an Aufmerksamkeit gewonnen.
In diesem Beitrag stelle ich Waffle vor, eine Bibliothek zur Integration von In-App-WAF-Funktionen in Go-Webanwendungen.
- https://sitebatch.github.io/waffle-website
- https://github.com/sitebatch/waffle-go
Was ist In-App WAF/RASP?
In-App-WAF/RASP ist nicht dazu gedacht, bestehende Cloud-WAFs zu ersetzen, sondern sie vielmehr zu ergänzen, indem die WAF-Funktionalität direkt in Ihre Anwendung eingebettet wird, um den Schutz zu verbessern.
Es kann gängige Webanwendungsangriffe wie SQL-Injection und XSS sowie Angriffe auf die Geschäftslogik von Anwendungen wie Credential Stuffing und Brute-Force-Versuche bewältigen.
Der Hauptvorteil ist die genaue Erkennung und Prävention durch vollständige Kenntnis des Anforderungskontexts.
Bedenken Sie diese HTTP-Anfrage zum Erstellen eines Blogbeitrags:
POST /blog/post HTTP/1.1 ... { "title": "What is SQL ?" "body": "SQL example code: `SELECT * FROM users` ..." }
Wenn Ihre Anwendung Platzhalter verwendet, um SQL-Anweisungen sicher zu erstellen, ist eine SQL-Injection nicht möglich. Cloudbasierte WAFs, die auf Mustervergleich basieren, würden diese Anfrage jedoch blockieren, da sie verdächtige SQL-ähnliche Muster enthält (die Zeichenfolge SELECT * FROM wirft Bedenken hinsichtlich der SQL-Injection auf).
Entwickler müssen oft mühsam Parameter, Endpunkte oder WAF-Regeln anpassen, um diese Fehlalarme zu reduzieren. Was für eine umständliche Aufgabe!
Im Gegensatz dazu versteht In-App WAF/RASP den Anforderungskontext. Es erkennt, wenn keine Platzhalter verwendet werden und blockiert Angriffe nur dann, wenn „SQL-Injection tatsächlich möglich ist“. Dieser kontextbewusste Ansatz führt zu weniger Fehlalarmen und kann sogar dazu beitragen, Zero-Day-Schwachstellen zu mindern.
Implementierung von In-App WAF/RASP mit Waffle in Go-Anwendungen
Waffle ist eine Bibliothek, die In-App WAF/RASP-Funktionalität in Go-Webanwendungen ermöglicht.
Sehen wir uns an, wie Sie Waffle in Ihre Anwendung integrieren und wie es Angriffe verhindert.
Beispielanwendung
Während dieses Beispiel net/http der Standardbibliothek verwendet, unterstützt Waffle auch andere Bibliotheken wie Gin und GORM.
Weitere Informationen finden Sie in der Dokumentation zu den unterstützten Bibliotheken.
Die folgende Anwendung weist eine SQL-Injection-Schwachstelle im /login-Endpunkt auf:
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 }
Integration von Waffle zur Verhinderung von SQL-Injection
Lassen Sie uns Waffle integrieren, um SQL-Injection zu verhindern:
$ 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
Ändern Sie main.go wie folgt:
$ go get github.com/sitebatch/waffle-go
Die Änderungen sind minimal:
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 }
Wenn wir jetzt einen SQL-Injection-Angriff versuchen, blockiert Waffle ihn:
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) }
Dieser HTML-Code ist die standardmäßig von Waffle zurückgegebene Fehlermeldung und sieht folgendermaßen aus:
Bei Verwendung von Platzhaltern:
Bei der Verwendung von Platzhaltern erkennt Waffle, dass eine SQL-Injection nicht möglich ist und blockiert die Anfrage nicht:
$ 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 <!DOCTYPE html> <html lang="en"> <head> <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 }
Beachten Sie, dass Waffle selbst in diesem Fall immer noch versuchte SQL-Injection wie eine cloudbasierte WAF erkennen kann (obwohl es diese nicht blockiert):
# 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
Angriffe werden von Waffle erkannt und verhindert
Während wir die Verhinderung von SQL-Injection demonstriert haben, kann Waffle verschiedene Angriffe erkennen und verhindern:
- Aufklärung durch bekannte Sicherheitsscanner
- Verzeichnisdurchlauf
- XSS
- SQL-Injection
- Zugriff auf vertrauliche Dateien
- SSRF
- Kontoübernahme
Weitere Einzelheiten finden Sie in der Dokumentation zur Regelliste.
Die Regeln werden kontinuierlich aktualisiert und Beiträge sind willkommen.
Abschluss
Durch die Integration von Waffle in Ihre Anwendung können Sie Angriffe genau erkennen und verhindern.
Framework-spezifische Implementierungsleitfäden und detaillierte Nutzungsanweisungen finden Sie im Abschnitt „Leitfäden“ in der Dokumentation.
Waffle befindet sich in aktiver Entwicklung. Wir freuen uns über Feedback und Beiträge.
- https://github.com/sitebatch/waffle-go
Das obige ist der detaillierte Inhalt vonEinführung in Waffle: In-App-WAF für Go-Anwendungen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

Video Face Swap
Tauschen Sie Gesichter in jedem Video mühelos mit unserem völlig kostenlosen KI-Gesichtstausch-Tool aus!

Heißer Artikel

Heiße Werkzeuge

Notepad++7.3.1
Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version
Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1
Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6
Visuelle Webentwicklungstools

SublimeText3 Mac-Version
Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Heiße Themen











Golang ist in Bezug auf Leistung und Skalierbarkeit besser als Python. 1) Golangs Kompilierungseigenschaften und effizientes Parallelitätsmodell machen es in hohen Parallelitätsszenarien gut ab. 2) Python wird als interpretierte Sprache langsam ausgeführt, kann aber die Leistung durch Tools wie Cython optimieren.

Golang ist in Gleichzeitigkeit besser als C, während C bei Rohgeschwindigkeit besser als Golang ist. 1) Golang erreicht durch Goroutine und Kanal eine effiziente Parallelität, die zum Umgang mit einer großen Anzahl von gleichzeitigen Aufgaben geeignet ist. 2) C über Compiler -Optimierung und Standardbibliothek bietet es eine hohe Leistung in der Nähe der Hardware, die für Anwendungen geeignet ist, die eine extreme Optimierung erfordern.

GoisidealforBeginersandSuitableforCloudandNetWorkServicesDuetoitsSimplicity, Effizienz und Konsumfeaturen.1) InstallgoFromTheofficialwebSiteAnDverifyWith'goversion'.2) CreateAneDrunyourFirstProgramwith'gorunhello.go.go.go.

Golang ist für schnelle Entwicklung und gleichzeitige Szenarien geeignet, und C ist für Szenarien geeignet, in denen extreme Leistung und Kontrolle auf niedriger Ebene erforderlich sind. 1) Golang verbessert die Leistung durch Müllsammlung und Parallelitätsmechanismen und eignet sich für die Entwicklung von Webdiensten mit hoher Konsequenz. 2) C erreicht die endgültige Leistung durch das manuelle Speicherverwaltung und die Compiler -Optimierung und eignet sich für eingebettete Systementwicklung.

GoimpactsDevelopmentPositivyThroughSpeed, Effizienz und DiasMlitication.1) Geschwindigkeit: Gocompilesquickandrunseffiction, idealforlargeProjects

Golang und Python haben jeweils ihre eigenen Vorteile: Golang ist für hohe Leistung und gleichzeitige Programmierung geeignet, während Python für Datenwissenschaft und Webentwicklung geeignet ist. Golang ist bekannt für sein Parallelitätsmodell und seine effiziente Leistung, während Python für sein Ökosystem für die kurze Syntax und sein reiches Bibliothek bekannt ist.

Die Leistungsunterschiede zwischen Golang und C spiegeln sich hauptsächlich in der Speicherverwaltung, der Kompilierungsoptimierung und der Laufzeiteffizienz wider. 1) Golangs Müllsammlung Mechanismus ist praktisch, kann jedoch die Leistung beeinflussen.

Golang und C haben jeweils ihre eigenen Vorteile bei Leistungswettbewerben: 1) Golang ist für eine hohe Parallelität und schnelle Entwicklung geeignet, und 2) C bietet eine höhere Leistung und eine feinkörnige Kontrolle. Die Auswahl sollte auf Projektanforderungen und Teamtechnologie -Stack basieren.
