WAF综述和Coraza基本使用

788 阅读2分钟

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源码