mirror of
https://gitee.com/samwaf/SamWaf.git
synced 2026-10-31 02:01:44 +08:00
Detection engine: - Normalize request data (body, cookies, form and JSON values, request headers) before inspection instead of only the URL query string, so encoded variants are evaluated consistently. - Extend XSS / SQLi / command-injection inspection to request bodies and to custom request headers; bodies and headers are scanned per value rather than as one blob to keep false positives low. - Add a configurable body inspection mode (body_detect_mode: observe/block/off, default observe) so the new deep checks record rather than block until an operator confirms them, plus body_detect_field_exclude to skip fields that legitimately carry rich text. - Keep false positives down on the new paths: skip structured values, require a corroborating signal before flagging body/header XSS, and leave dual-use keywords out of the fallback lists. - Path traversal is now normalized and judged on whether it escapes the site root instead of matching literally; this also clears a long-standing false positive on legitimate in-site relative paths. Adds a sensitive-file list. - Scanner detection now covers all request headers and known probe paths. Plugins: - Suspend plugin loading pending signing and admission work. The code path is retained but gated off, and shipped disabled by default. Validated against a local test corpus and a 33k real-traffic benchmark: detection improved across every category while the real-traffic false-positive count stayed flat.
66 lines
2.0 KiB
Go
66 lines
2.0 KiB
Go
package wafenginecore
|
|
|
|
import (
|
|
"net/http"
|
|
"testing"
|
|
)
|
|
|
|
func reqWithHeader(name, val string) *http.Request {
|
|
r, _ := http.NewRequest("GET", "http://x/", nil)
|
|
r.Header.Set(name, val)
|
|
return r
|
|
}
|
|
|
|
// S1-4:自定义头里的注入应被对应 check 命中
|
|
func TestHeaderDetect_Hits(t *testing.T) {
|
|
if !headerXSSHit(reqWithHeader("X-Custom", "<script>alert(1)</script>")) {
|
|
t.Error("头位 XSS 应命中")
|
|
}
|
|
if !headerSQLHit(reqWithHeader("X-Api", "1;exec sp_configure 'xp_cmdshell',1;reconfigure;--")) {
|
|
t.Error("头位 SQLi(关键字) 应命中")
|
|
}
|
|
if !headerSQLHit(reqWithHeader("X-Forwarded-Host", "1' or '1'='1")) {
|
|
t.Error("头位 SQLi(libinjection) 应命中")
|
|
}
|
|
if ok, _ := headerRCEHit(reqWithHeader("X-Cmd", "who^ami")); !ok {
|
|
t.Error("头位命令注入(反混淆) 应命中")
|
|
}
|
|
if ok, _ := headerRCEHit(reqWithHeader("X-Debug", ";id")); !ok {
|
|
t.Error("头位命令注入 应命中")
|
|
}
|
|
}
|
|
|
|
// 标准/浏览器头及正常自定义头不应误报
|
|
func TestHeaderDetect_NoFP(t *testing.T) {
|
|
r, _ := http.NewRequest("GET", "http://x/", nil)
|
|
r.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")
|
|
r.Header.Set("Referer", "https://site.com/search?q=select+all&cat=news")
|
|
r.Header.Set("Accept", "text/html,application/xhtml+xml,*/*;q=0.8")
|
|
r.Header.Set("Sec-Ch-Ua", `"Chromium";v="120", "Not?A_Brand";v="8"`)
|
|
r.Header.Set("X-Requested-With", "XMLHttpRequest")
|
|
r.Header.Set("X-Custom-Id", "user-12345")
|
|
if headerXSSHit(r) {
|
|
t.Error("正常头不应判 XSS")
|
|
}
|
|
if headerSQLHit(r) {
|
|
t.Error("正常头不应判 SQLi")
|
|
}
|
|
if ok, _ := headerRCEHit(r); ok {
|
|
t.Error("正常头不应判命令注入")
|
|
}
|
|
}
|
|
|
|
func TestSkipDetectHeader(t *testing.T) {
|
|
skip := []string{"Host", "User-Agent", "Referer", "Accept", "Cookie", "Sec-Fetch-Site", "waf_req_uuid"}
|
|
for _, h := range skip {
|
|
if !skipDetectHeader(h) {
|
|
t.Errorf("应跳过标准头: %s", h)
|
|
}
|
|
}
|
|
for _, h := range []string{"X-Custom", "X-Forwarded-Host", "X-Cmd"} {
|
|
if skipDetectHeader(h) {
|
|
t.Errorf("自定义头不应跳过: %s", h)
|
|
}
|
|
}
|
|
}
|