Rumah > pembangunan bahagian belakang > Golang > Pengenalan kepada Wafel: Aplikasi WAF untuk Go dalam apl

Pengenalan kepada Wafel: Aplikasi WAF untuk Go dalam apl

Patricia Arquette
Lepaskan: 2025-01-05 22:42:45
asal
467 orang telah melayarinya

pengenalan

Tembok Api Aplikasi Web (WAF) telah lama menjadi penyelesaian keselamatan standard untuk melindungi aplikasi web. WAF berasaskan awan seperti AWS WAF dan Cloudflare WAF amat popular kerana kemudahan pelaksanaannya. Walau bagaimanapun, ia datang dengan beberapa cabaran:

  • Pemahaman terhad tentang konteks aplikasi
  • Kadar positif palsu yang tinggi
  • Pelaksanaan logik tersuai terhad

Untuk menangani cabaran ini, pendekatan baharu yang dipanggil WAF Dalam Apl atau RASP (Perlindungan Kendiri Aplikasi Waktu Jalan) telah mendapat perhatian.

Dalam siaran ini, saya akan memperkenalkan Waffle, sebuah perpustakaan untuk menyepadukan keupayaan WAF Dalam apl ke dalam aplikasi web Go.

  • https://sitebatch.github.io/waffle-website
  • https://github.com/sitebatch/waffle-go

Introduction to Waffle: In-app WAF for Go Applications

Apakah WAF dalam apl / RASP?

WAF/RASP dalam apl bukan bertujuan untuk menggantikan WAF awan sedia ada tetapi untuk melengkapkannya dengan membenamkan fungsi WAF terus ke dalam aplikasi anda untuk perlindungan yang dipertingkatkan.
Ia boleh mengendalikan serangan aplikasi web biasa seperti suntikan SQL dan XSS, serta serangan logik perniagaan aplikasi seperti pemadat bukti kelayakan dan percubaan kekerasan.

Kelebihan utama ialah pengesanan dan pencegahan yang tepat melalui kesedaran konteks permintaan yang lengkap.

Pertimbangkan permintaan HTTP ini untuk membuat catatan blog:

POST /blog/post HTTP/1.1
...

{
  "title": "What is SQL ?"
  "body": "SQL example code: `SELECT * FROM users` ..."
}
Salin selepas log masuk
Salin selepas log masuk

Jika aplikasi anda menggunakan ruang letak untuk membina pernyataan SQL dengan selamat, suntikan SQL tidak boleh dilakukan. Walau bagaimanapun, WAF berasaskan awan yang bergantung pada padanan corak akan menyekat permintaan ini kerana ia mengandungi corak seperti SQL yang mencurigakan (rentetan SELECT * FROM menimbulkan kebimbangan suntikan SQL).

Pembangun sering mendapati diri mereka membosankan melaraskan parameter, titik akhir atau peraturan WAF untuk mengurangkan positif palsu ini. Tugas yang menyusahkan!

Sebaliknya, WAF / RASP dalam apl memahami konteks permintaan. Ia mengiktiraf apabila pemegang tempat tidak digunakan dan hanya menyekat serangan apabila "suntikan SQL sebenarnya boleh dilakukan." Pendekatan sedar konteks ini menghasilkan lebih sedikit positif palsu malah boleh membantu mengurangkan kerentanan sifar hari.

Melaksanakan WAF / RASP Dalam Apl dengan Aplikasi Waffle in Go

Waffle ialah perpustakaan yang mendayakan fungsi WAF / RASP Dalam Apl dalam aplikasi web Go.

Mari lihat cara menyepadukan Waffle ke dalam aplikasi anda dan cara ia menghalang serangan.

Contoh Permohonan

Walaupun contoh ini menggunakan jaring/http perpustakaan standard, Waffle turut menyokong perpustakaan lain seperti Gin dan GORM.
Untuk butiran lanjut, lihat dokumentasi Perpustakaan yang Disokong.

Aplikasi berikut mempunyai kelemahan suntikan SQL dalam titik akhir /login:

POST /blog/post HTTP/1.1
...

{
  "title": "What is SQL ?"
  "body": "SQL example code: `SELECT * FROM users` ..."
}
Salin selepas log masuk
Salin selepas log masuk
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
}
Salin selepas log masuk

Mengintegrasikan Wafel untuk mengelakkan suntikan SQL

Mari kita integrasikan Waffle untuk mengelakkan suntikan 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
Salin selepas log masuk

Ubah suai main.go seperti berikut:

$ go get github.com/sitebatch/waffle-go
Salin selepas log masuk

Perubahan adalah minimum:

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
}
Salin selepas log masuk

Kini apabila kami mencuba serangan suntikan SQL, Waffle menyekatnya:

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)
    }
Salin selepas log masuk

HTML ini ialah mesej ralat yang dikembalikan secara lalai oleh wafel dan kelihatan seperti ini:

Introduction to Waffle: In-app WAF for Go Applications

Jika menggunakan ruang letak:

Apabila menggunakan ruang letak, Waffle menyedari bahawa suntikan SQL tidak boleh dilakukan dan tidak akan menyekat permintaan:

$ 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>
Salin selepas log masuk
# 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
    }
Salin selepas log masuk

Perhatikan bahawa walaupun dalam kes ini, Waffle masih boleh mengesan percubaan suntikan SQL seperti WAF berasaskan awan (walaupun ia tidak akan menyekatnya):

# 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
Salin selepas log masuk

Serangan Dikesan dan Dicegah oleh Wafel

Walaupun kami telah menunjukkan pencegahan suntikan SQL, Waffle boleh mengesan dan menghalang pelbagai serangan:

  • Peninjauan oleh pengimbas keselamatan yang diketahui
  • Lintasan direktori
  • XSS
  • Suntikan SQL
  • Akses fail sensitif
  • SSRF
  • Pengambilalihan akaun

Untuk butiran lanjut, lihat dokumentasi Senarai Peraturan.

Peraturan sentiasa dikemas kini dan sumbangan dialu-alukan.

Kesimpulan

Dengan menyepadukan Waffle ke dalam aplikasi anda, anda boleh mengesan dan mencegah serangan dengan tepat.

Untuk panduan pelaksanaan khusus rangka kerja dan arahan penggunaan terperinci, rujuk bahagian Panduan dalam dokumentasi.

Wafel sedang dalam pembangunan aktif. Kami mengalu-alukan maklum balas dan sumbangan.

  • https://github.com/sitebatch/waffle-go

Atas ialah kandungan terperinci Pengenalan kepada Wafel: Aplikasi WAF untuk Go dalam apl. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:dev.to
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel terbaru oleh pengarang
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan