mirror of
https://gitee.com/samwaf/SamWaf.git
synced 2025-12-06 06:58:54 +08:00
@@ -4,6 +4,7 @@ type WebLog struct {
|
||||
WafInnerDFlag string `json:"waf_inner_dflag"` //日志队列处理方式
|
||||
HOST string `json:"host"`
|
||||
URL string `json:"url"`
|
||||
RawQuery string `json:"raw_query"` //原始URL查询
|
||||
REFERER string `json:"referer"`
|
||||
USER_AGENT string `json:"user_agent"`
|
||||
METHOD string `json:"method"`
|
||||
|
||||
58
libinjection-go/dir_traversal.go
Normal file
58
libinjection-go/dir_traversal.go
Normal file
@@ -0,0 +1,58 @@
|
||||
package libinjection
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// HasDirTraversal 检测URL是否存在目录穿越漏洞
|
||||
func HasDirTraversal(rawURL string) bool {
|
||||
// 解析URL
|
||||
parsedURL, err := url.Parse(rawURL)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// 定义路径穿越特征正则表达式
|
||||
pattern := `(\.\./|\.\.\\|%2e%2e/|%2e%2e\\)`
|
||||
regex := regexp.MustCompile(pattern)
|
||||
|
||||
// 检查URL路径部分
|
||||
path := parsedURL.Path
|
||||
if checkComponent(path, regex) {
|
||||
return true
|
||||
}
|
||||
|
||||
// 检查查询参数值
|
||||
query := parsedURL.Query()
|
||||
for _, values := range query {
|
||||
for _, value := range values {
|
||||
// 解码URL编码后再检查(防止%2e%2e%2f绕过)
|
||||
decodedValue, err := url.QueryUnescape(value)
|
||||
if err != nil {
|
||||
decodedValue = value // 如果解码失败,使用原始值
|
||||
}
|
||||
if checkComponent(decodedValue, regex) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// 检查单个组件是否包含恶意特征
|
||||
func checkComponent(component string, regex *regexp.Regexp) bool {
|
||||
// 检查是否包含路径遍历模式
|
||||
if regex.MatchString(component) {
|
||||
return true
|
||||
}
|
||||
|
||||
// 额外检查Windows路径特征
|
||||
if strings.Contains(component, "..\\") {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
22
libinjection-go/dir_traversal_test.go
Normal file
22
libinjection-go/dir_traversal_test.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package libinjection
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestHasDirTraversal(t *testing.T) {
|
||||
// 测试用例
|
||||
testURLs := []string{
|
||||
"http://example.com/download?file=../../etc/passwd", // 应检测到
|
||||
"http://example.com/?id=../../../../etc/passwd", // 应检测到
|
||||
"http://example.com/../../secret.txt", // 应检测到
|
||||
"http://example.com/?path=%2e%2e%2fetc%2fpasswd", // 应检测到(URL编码的../)
|
||||
"http://example.com/valid?file=doc.pdf", // 正常URL
|
||||
"http://example.com/?data=..\\Windows\\system.ini", // 检测Windows路径
|
||||
}
|
||||
|
||||
for _, u := range testURLs {
|
||||
fmt.Printf("检测URL: %-50s => 存在漏洞: %t\n", u, HasDirTraversal(u))
|
||||
}
|
||||
}
|
||||
@@ -34,10 +34,11 @@ type Hosts struct {
|
||||
}
|
||||
|
||||
type HostsDefense struct {
|
||||
DEFENSE_BOT int `json:"bot"` //防御-虚假BOT
|
||||
DEFENSE_SQLI int `json:"sqli"` //防御-Sql注入
|
||||
DEFENSE_XSS int `json:"xss"` //防御-xss攻击
|
||||
DEFENSE_SCAN int `json:"scan"` //防御-scan工具扫描
|
||||
DEFENSE_RCE int `json:"rce"` //防御-scan工具扫描
|
||||
DEFENSE_SENSITIVE int `json:"sensitive"` //敏感词检测
|
||||
DEFENSE_BOT int `json:"bot"` //防御-虚假BOT
|
||||
DEFENSE_SQLI int `json:"sqli"` //防御-Sql注入
|
||||
DEFENSE_XSS int `json:"xss"` //防御-xss攻击
|
||||
DEFENSE_SCAN int `json:"scan"` //防御-scan工具扫描
|
||||
DEFENSE_RCE int `json:"rce"` //防御-scan工具扫描
|
||||
DEFENSE_SENSITIVE int `json:"sensitive"` //敏感词检测
|
||||
DEFENSE_DIR_TRAVERSAL int `json:"traversal"` //目录穿越检测
|
||||
}
|
||||
|
||||
43
wafenginecore/check_dir_traversal.go
Normal file
43
wafenginecore/check_dir_traversal.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package wafenginecore
|
||||
|
||||
import (
|
||||
"SamWaf/innerbean"
|
||||
"SamWaf/libinjection-go"
|
||||
"SamWaf/model/detection"
|
||||
"SamWaf/model/wafenginmodel"
|
||||
"net/http"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
// CheckDirTraversal 穿越漏洞检测
|
||||
func (waf *WafEngine) CheckDirTraversal(r *http.Request, weblogbean *innerbean.WebLog, formValue url.Values, hostTarget *wafenginmodel.HostSafe, globalHostTarget *wafenginmodel.HostSafe) detection.Result {
|
||||
result := detection.Result{
|
||||
JumpGuardResult: false,
|
||||
IsBlock: false,
|
||||
Title: "",
|
||||
Content: "",
|
||||
}
|
||||
var flag = false
|
||||
//检测sql注入
|
||||
if libinjection.HasDirTraversal(weblogbean.RawQuery) ||
|
||||
libinjection.HasDirTraversal(weblogbean.BODY) {
|
||||
flag = true
|
||||
}
|
||||
if flag == false {
|
||||
for _, value := range formValue {
|
||||
for _, v := range value {
|
||||
if libinjection.HasDirTraversal(v) {
|
||||
flag = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if flag == true {
|
||||
weblogbean.RISK_LEVEL = 2
|
||||
result.IsBlock = true
|
||||
result.Title = "目录穿越漏洞"
|
||||
result.Content = "请正确访问"
|
||||
return result
|
||||
}
|
||||
return result
|
||||
}
|
||||
@@ -22,7 +22,7 @@ func (waf *WafEngine) CheckSql(r *http.Request, weblogbean *innerbean.WebLog, fo
|
||||
}
|
||||
var sqlFlag = false
|
||||
//检测sql注入
|
||||
if libinjection.IsSQLiNotReturnPrint(weblogbean.URL) ||
|
||||
if libinjection.IsSQLiNotReturnPrint(weblogbean.RawQuery) ||
|
||||
libinjection.IsSQLiNotReturnPrint(weblogbean.BODY) ||
|
||||
libinjection.IsSQLiNotReturnPrint(weblogbean.POST_FORM) {
|
||||
sqlFlag = true
|
||||
|
||||
@@ -21,7 +21,7 @@ func (waf *WafEngine) CheckXss(r *http.Request, weblogbean *innerbean.WebLog, fo
|
||||
Content: "",
|
||||
}
|
||||
var xssFlag = false
|
||||
if libinjection.IsXSS(weblogbean.URL) ||
|
||||
if libinjection.IsXSS(weblogbean.RawQuery) ||
|
||||
libinjection.IsXSS(weblogbean.POST_FORM) {
|
||||
xssFlag = true
|
||||
}
|
||||
|
||||
@@ -183,11 +183,12 @@ func (waf *WafEngine) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
currentDay, _ := strconv.Atoi(time.Now().Format("20060102"))
|
||||
|
||||
//URL 解码
|
||||
enEscapeUrl := wafhttpcore.WafHttpCoreUrlEncode(r.RequestURI, 100)
|
||||
deRawQueryUrl := wafhttpcore.WafHttpCoreUrlEncode(r.URL.RawQuery, 10)
|
||||
datetimeNow := time.Now()
|
||||
weblogbean := innerbean.WebLog{
|
||||
HOST: host,
|
||||
URL: enEscapeUrl,
|
||||
URL: r.RequestURI,
|
||||
RawQuery: deRawQueryUrl,
|
||||
REFERER: r.Referer(),
|
||||
USER_AGENT: r.UserAgent(),
|
||||
METHOD: r.Method,
|
||||
@@ -287,12 +288,13 @@ func (waf *WafEngine) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
hostDefense := model.HostsDefense{
|
||||
DEFENSE_BOT: 1,
|
||||
DEFENSE_SQLI: 1,
|
||||
DEFENSE_XSS: 1,
|
||||
DEFENSE_SCAN: 1,
|
||||
DEFENSE_RCE: 1,
|
||||
DEFENSE_SENSITIVE: 1,
|
||||
DEFENSE_BOT: 1,
|
||||
DEFENSE_SQLI: 1,
|
||||
DEFENSE_XSS: 1,
|
||||
DEFENSE_SCAN: 1,
|
||||
DEFENSE_RCE: 1,
|
||||
DEFENSE_SENSITIVE: 1,
|
||||
DEFENSE_DIR_TRAVERSAL: 1,
|
||||
}
|
||||
err := json.Unmarshal([]byte(hostTarget.Host.DEFENSE_JSON), &hostDefense)
|
||||
if err != nil {
|
||||
@@ -328,6 +330,12 @@ func (waf *WafEngine) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
}
|
||||
//目录穿越检测
|
||||
if hostDefense.DEFENSE_DIR_TRAVERSAL == 1 {
|
||||
if handleBlock(waf.CheckDirTraversal) {
|
||||
return
|
||||
}
|
||||
}
|
||||
//检测CC
|
||||
if handleBlock(waf.CheckCC) {
|
||||
return
|
||||
|
||||
@@ -3,12 +3,22 @@ package wafhttpcore
|
||||
import (
|
||||
"SamWaf/libinjection-go"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSql(t *testing.T) {
|
||||
payload := "data/index.html?id=1 and (select top 1 count(*) from admin where unicode(substring(a,1,1))=asc%E5%80%BC%20and%20id=1)%3E0"
|
||||
payload := "id=1+and+1=2+union+select+1"
|
||||
decodedValue, err := url.QueryUnescape(payload)
|
||||
|
||||
sqlB, sqlstring := libinjection.IsSQLi(payload)
|
||||
fmt.Println(sqlB, sqlstring)
|
||||
payLoadReturnPrint := libinjection.IsSQLiNotReturnPrint(payload)
|
||||
fmt.Println(fmt.Sprintf("payload=%v Result:%v", payload, payLoadReturnPrint))
|
||||
|
||||
decodepayLoadReturnPrint := libinjection.IsSQLiNotReturnPrint(decodedValue)
|
||||
if err != nil {
|
||||
fmt.Println(fmt.Sprintf("decodePayload=%v Result:%v QueryUnescapeErr:%v", decodedValue, decodepayLoadReturnPrint, err))
|
||||
} else {
|
||||
fmt.Println(fmt.Sprintf("decodePayload=%v Result:%v ", decodedValue, decodepayLoadReturnPrint))
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,16 +3,10 @@ package wafhttpcore
|
||||
import (
|
||||
"SamWaf/common/zlog"
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// 逆向编码处理
|
||||
func WafHttpCoreUrlEncode(encoded string, maxDepth int) string {
|
||||
// 如果没有编码格式,直接返回
|
||||
if !strings.Contains(encoded, "%") {
|
||||
return encoded
|
||||
}
|
||||
|
||||
// 限制递归的最大深度,防止无限递归
|
||||
if maxDepth <= 0 {
|
||||
return encoded // 达到最大递归深度时返回原始字符串
|
||||
|
||||
Reference in New Issue
Block a user