From 0a833b0326799933ddc4cf0bd8444e161d398f46 Mon Sep 17 00:00:00 2001 From: M09Ic Date: Thu, 5 Jun 2025 13:45:48 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E9=80=9A=E9=85=8D?= =?UTF-8?q?=E7=AC=A6=E7=8A=B6=E6=80=81=E7=A0=81,=20https://github.com/chai?= =?UTF-8?q?nreactors/spray/issues/38?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/option.go | 8 ++-- core/pool/brutepool.go | 6 +-- pkg/utils.go | 91 ++++++++++++++++++++++++++++++++---------- 3 files changed, 78 insertions(+), 27 deletions(-) diff --git a/core/option.go b/core/option.go index 58b7ae7..328354d 100644 --- a/core/option.go +++ b/core/option.go @@ -241,18 +241,18 @@ func (opt *Option) Prepare() error { ihttp.DefaultMaxBodySize = opt.MaxBodyLength * 1024 } - pkg.BlackStatus = pkg.ParseStatus(pkg.BlackStatus, opt.BlackStatus) - pkg.WhiteStatus = pkg.ParseStatus(pkg.WhiteStatus, opt.WhiteStatus) + pkg.BlackStatus = pkg.ParseStatus(pkg.DefaultBlackStatus, opt.BlackStatus) + pkg.WhiteStatus = pkg.ParseStatus(pkg.DefaultWhiteStatus, opt.WhiteStatus) if opt.FuzzyStatus == "all" { pool.EnableAllFuzzy = true } else { - pkg.FuzzyStatus = pkg.ParseStatus(pkg.FuzzyStatus, opt.FuzzyStatus) + pkg.FuzzyStatus = pkg.ParseStatus(pkg.DefaultFuzzyStatus, opt.FuzzyStatus) } if opt.Unique { pool.EnableAllUnique = true } else { - pkg.UniqueStatus = pkg.ParseStatus(pkg.UniqueStatus, opt.UniqueStatus) + pkg.UniqueStatus = pkg.ParseStatus(pkg.DefaultUniqueStatus, opt.UniqueStatus) } logs.Log.Logf(pkg.LogVerbose, "Black Status: %v, WhiteStatus: %v, WAFStatus: %v", pkg.BlackStatus, pkg.WhiteStatus, pkg.WAFStatus) diff --git a/core/pool/brutepool.go b/core/pool/brutepool.go index 8665daf..14786c4 100644 --- a/core/pool/brutepool.go +++ b/core/pool/brutepool.go @@ -545,7 +545,7 @@ func (pool *BrutePool) Upgrade(bl *baseline.Baseline) error { func (pool *BrutePool) PreCompare(resp *ihttp.Response) error { status := resp.StatusCode() - if iutils.IntsContains(pkg.WhiteStatus, status) { + if pkg.StatusContain(pkg.WhiteStatus, status) { // 如果为白名单状态码则直接返回 return nil } @@ -553,11 +553,11 @@ func (pool *BrutePool) PreCompare(resp *ihttp.Response) error { // return pkg.ErrSameStatus //} - if iutils.IntsContains(pkg.BlackStatus, status) { + if pkg.StatusContain(pkg.BlackStatus, status) { return pkg.ErrBadStatus } - if iutils.IntsContains(pkg.WAFStatus, status) { + if pkg.StatusContain(pkg.WAFStatus, status) { return pkg.ErrWaf } diff --git a/pkg/utils.go b/pkg/utils.go index 0891b4d..2d2d82e 100644 --- a/pkg/utils.go +++ b/pkg/utils.go @@ -25,13 +25,17 @@ import ( ) var ( - LogVerbose = logs.Warn - 2 - LogFuzz = logs.Warn - 1 - WhiteStatus = []int{} // cmd input, 200 - BlackStatus = []int{} // cmd input, 400,410 - FuzzyStatus = []int{} // cmd input, 500,501,502,503 - WAFStatus = []int{493, 418, 1020, 406, 429} - UniqueStatus = []int{} // 相同unique的403表示命中了同一条acl, 相同unique的200表示default页面 + LogVerbose = logs.Warn - 2 + LogFuzz = logs.Warn - 1 + DefaultWhiteStatus = []int{200} // cmd input + DefaultBlackStatus = []int{400, 410} // cmd input + DefaultFuzzyStatus = []int{500, 501, 502, 503, 301, 302, 404} // cmd input + DefaultUniqueStatus = []int{403, 200, 404} // 相同unique的403表示命中了同一条acl, 相同unique的200表示default页面 + WhiteStatus = []int{} // cmd input, 200 + BlackStatus = []int{} // cmd input, 400,410 + FuzzyStatus = []int{} // cmd input, 500,501,502,503 + WAFStatus = []int{493, 418, 1020, 406, 429, 406, 412} + UniqueStatus = []int{} // 相同unique的403表示命中了同一条acl, 相同unique的200表示default页面 // plugins EnableAllFingerEngine = false @@ -417,40 +421,87 @@ func ParseExtension(s string) string { return "" } +// ParseStatus parses the input string and updates the preset status filters. func ParseStatus(preset []int, changed string) []int { if changed == "" { return preset } + + parseToken := func(s string) (int, bool) { + s = strings.TrimSpace(s) + if strings.HasSuffix(s, "*") { + prefix := s[:len(s)-1] + if t, err := strconv.Atoi(prefix); err == nil { + return t, true // isPrefix = true + } + } else if t, err := strconv.Atoi(s); err == nil { + return t, false // isPrefix = false + } + return 0, false + } + if strings.HasPrefix(changed, "+") { for _, s := range strings.Split(changed[1:], ",") { - if t, err := strconv.Atoi(s); err != nil { - continue - } else { + if t, _ := parseToken(s); t != 0 { preset = append(preset, t) } } } else if strings.HasPrefix(changed, "!") { for _, s := range strings.Split(changed[1:], ",") { - for i, status := range preset { - if t, err := strconv.Atoi(s); err != nil { - break - } else if t == status { - preset = append(preset[:i], preset[i+1:]...) - break + if t, _ := parseToken(s); t != 0 { + newPreset := preset[:0] + for _, val := range preset { + if val != t { + newPreset = append(newPreset, val) + } } + preset = newPreset } } } else { preset = []int{} for _, s := range strings.Split(changed, ",") { - if t, err := strconv.Atoi(s); err != nil { - continue - } else { + if t, _ := parseToken(s); t != 0 { preset = append(preset, t) } } } - return preset + return UniqueInts(preset) +} + +func UniqueInts(input []int) []int { + seen := make(map[int]bool) + result := make([]int, 0, len(input)) + + for _, val := range input { + if !seen[val] { + seen[val] = true + result = append(result, val) + } + } + return result +} + +// StatusContain checks if a status matches any of the preset filters. +// Preset values < 100 are treated as prefix filters (e.g. 5 = 5xx, 51 = 51x). +func StatusContain(preset []int, status int) bool { + if len(preset) == 0 { + return true + } + for _, s := range preset { + if s < 10 { + if status/100 == s { + return true + } + } else if s < 100 { + if status/10 == s { + return true + } + } else if s == status { + return true + } + } + return false } func LoadFileToSlice(filename string) ([]string, error) {