waf匹配一般流程
- 对https报文进行加解密处理,根据ssl证书和密钥对对报文进行解密;对明文报文进行统一编码处理;(协议解析模块)
- 提取报文中的字段,与规则库内容进行匹配和筛选,(规则模块)
- 防御动作,(动作模块)
- 将防御过程记录日志,(日志模块)
- 再多一个(配置模块),主要用来配置waf以什么模式工作
ModSecurity搭建教程参考
https://blog.csdn.net/ffffccccccccffff/article/details/132423581
https://cn.linux-console.net/?p=3554
常用waf列表
ModSecurity
https://www.modsecurity.org/
无控制台,star最高的经典waf,母公司已停止维护
雷池社区版
https://waf-ce.chaitin.cn/
长亭科技根据企业版雷池Web应用防护系统提炼而来,核心检测能力由长亭首创的智能语义分析算法驱动。有控制台
Coraza
官网https://coraza.io/
开源,Go语言实现
支持ModSecurity SecLang规则集,并且与OWASP核心规则集完全兼容,与ModSecurity一样不提供界面,只作为检测引擎,需要二次开发才能试用,有机会成为 ModSecurity 的替代品。
Coraza使用示例
代码示例
go get github.com/corazawaf/coraza/v3
package main
import (
"fmt"
"github.com/corazawaf/coraza/v3"
)
func main() {
// 初始化waf和seclang解析器
waf, err := coraza.NewWAF(coraza.NewWAFConfig().
WithDirectives(`SecRule REMOTE_ADDR "@rx .*" "id:1,phase:1,deny,status:403"`))
if err != nil {
fmt.Println(err)
}
// 创建一个事务,一个被waf处理的请求就看作是一个事物transaction
tx := waf.NewTransaction()
defer func() {
tx.ProcessLogging()
tx.Close()
}()
tx.ProcessConnection("127.0.0.1", 8080, "127.0.0.1", 12345)
// Finally we process the request headers phase, which may return an interruption
if it := tx.ProcessRequestHeaders(); it != nil {
fmt.Printf("Transaction was interrupted with status %d\n", it.Status)
}
}
http-server示例
代码来自https://github.com/corazawaf/coraza/tree/main/examples/http-server
package main
import (
"fmt"
"log"
"net/http"
"os"
"strings"
"github.com/corazawaf/coraza/v3"
txhttp "github.com/corazawaf/coraza/v3/http"
"github.com/corazawaf/coraza/v3/types"
)
func exampleHandler(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Content-Type", "text/plain")
resBody := "Hello world, transaction not disrupted."
if body := os.Getenv("RESPONSE_BODY"); body != "" {
resBody = body
}
if h := os.Getenv("RESPONSE_HEADERS"); h != "" {
key, val, _ := strings.Cut(h, ":")
w.Header().Set(key, val)
}
// The server generates the response
w.Write([]byte(resBody))
}
func main() {
waf := createWAF()
http.Handle("/", txhttp.WrapHandler(waf, http.HandlerFunc(exampleHandler)))
fmt.Println("Server is running. Listening port: 8090")
log.Fatal(http.ListenAndServe(":8090", nil))
}
func createWAF() coraza.WAF {
directivesFile := "./default.conf"
if s := os.Getenv("DIRECTIVES_FILE"); s != "" {
directivesFile = s
}
waf, err := coraza.NewWAF(
coraza.NewWAFConfig().
WithErrorCallback(logError).
WithDirectivesFromFile(directivesFile),
)
if err != nil {
log.Fatal(err)
}
return waf
}
func logError(error types.MatchedRule) {
msg := error.ErrorLog()
fmt.Printf("[logError][%s] %s\n", error.Rule().Severity(), msg)
}
效果如下,防护效果主要还是看seclang配置文件的编写
http:/ip:8090/?id=1 =>Hello world, transaction not disrupted.
http:/ip:8090/?id=0 =>403
拆装coraza非常方便,如果要拆除,只需要修改main函数为如下,这就是最原始的http通信
func main() {
http.Handle("/", http.HandlerFunc(exampleHandler))
fmt.Println("Server is running. Listening port: 8090")
log.Fatal(http.ListenAndServe(":8090", nil))
}
接下来需要学一下seclang语法和coraza源码