Getting Started
Here, we will explain how to protect an application using Waffle with a sample application.
Example application
The following examples use a web application built with standard libraries. However, you don’t need to be using these libraries specifically - Waffle can be used with other libraries such as Gin and GORM.
For a complete list of supported libraries, please refer to the contrib
directory in the repository or supported libraries page.
Protecting example application
Full example code is available at example/basic
directory
To protect an example application built with net/http
, you simply need to add the Waffle middleware.
package main
import (
"net/http"
"github.com/sitebatch/waffle-go"
waffleHttp "github.com/sitebatch/waffle-go/contrib/net/http"
)
func main() {
// Start waffle with debug mode
waffle.Start(waffle.WithDebug())
srv := &http.Server{
Addr: ":8000",
Handler: newHTTPHandler(),
}
srv.ListenAndServe()
}
func ping(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("pong"))
}
func newHTTPHandler() http.Handler {
mux := http.NewServeMux()
mux.Handle("/ping", http.HandlerFunc(ping))
// Add Waffle middleware
handler := waffleHttp.WafMiddleware(mux)
return handler
}
To verify the effect of this middleware, run the following command.
$ go run main.go
# Access the server
$ curl -i http://localhost:8000/ping
HTTP/1.1 200 OK
Date: Thu, 26 Dec 2024 12:49:41 GMT
Content-Length: 4
Content-Type: text/plain; charset=utf-8
pong
Next, send a directory traversal attack request.
$ curl -i 'http://localhost:8000/ping?file=../../../../../etc/hosts'
HTTP/1.1 200 OK
Date: Thu, 26 Dec 2024 12:49:41 GMT
Content-Length: 4
Content-Type: text/plain; charset=utf-8
pong
This request attempts directory traversal, but the application does not have a file reading function.
Therefore, Waffle does not block this request. However, this request is logged.
level=INFO msg="[waffle] Threat detected: detected match \\.\\./" ruleID=directory-traversal-attempts inspector=regex clientIP=[::1]:55612 url="http://localhost:8000/ping?file=../../../"
Now, let’s see how to prevent attacks if the application has a file reading function.
Waffle can prevent attacks “more accurately” by propagating context. This context-aware approach allows you to maintain effective defense while reducing false positives.
package main
import (
"net/http"
"github.com/sitebatch/waffle-go"
waffleHttp "github.com/sitebatch/waffle-go/contrib/net/http"
waffleOs "github.com/sitebatch/waffle-go/contrib/os"
)
func main() {
// Start waffle with debug mode
waffle.Start(waffle.WithDebug())
srv := &http.Server{
Addr: ":8000",
Handler: newHTTPHandler(),
}
srv.ListenAndServe()
}
func ping(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("pong"))
}
// readFile reads a file from the path specified in the query parameter.
// This function has a vulnerability that allows any file to be read, but it is protected by Waffle.
func readFile(w http.ResponseWriter, r *http.Request) {
path := r.URL.Query().Get("file")
// Protect the file read operations
if _, err := waffleOs.ProtectReadFile(r.Context(), path); err != nil {
var actionErr *action.BlockError
if errors.As(err, &actionErr) {
return
}
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Write([]byte("file read"))
}
func newHTTPHandler() http.Handler {
mux := http.NewServeMux()
mux.Handle("/ping", http.HandlerFunc(ping))
mux.Handle("/get-file", http.HandlerFunc(readFile))
handler := waffleHttp.WafMiddleware(mux)
return handler
}
To verify that the attack request is blocked, run the following command.
$ curl -i 'http://localhost:8000/get-file?file=main.go'
HTTP/1.1 200 OK
Date: Thu, 26 Dec 2024 14:19:34 GMT
Content-Length: 9
Content-Type: text/plain; charset=utf-8
file read⏎
$ curl -i 'http://localhost:8000/get-file?file=/etc/hosts'
HTTP/1.1 403 Forbidden
Date: Fri, 03 Jan 2025 09:43:52 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>
...
Waffle also provides features to prevent attacks such as SQL injection, SSRF and more.
Next Steps
For more information about protect your application, refer the guides.