mirror of
https://github.com/chainreactors/spray.git
synced 2025-09-15 19:50:18 +00:00
feat: 支持通配符状态码, https://github.com/chainreactors/spray/issues/38
This commit is contained in:
parent
fd7b603e02
commit
0a833b0326
@ -241,18 +241,18 @@ func (opt *Option) Prepare() error {
|
|||||||
ihttp.DefaultMaxBodySize = opt.MaxBodyLength * 1024
|
ihttp.DefaultMaxBodySize = opt.MaxBodyLength * 1024
|
||||||
}
|
}
|
||||||
|
|
||||||
pkg.BlackStatus = pkg.ParseStatus(pkg.BlackStatus, opt.BlackStatus)
|
pkg.BlackStatus = pkg.ParseStatus(pkg.DefaultBlackStatus, opt.BlackStatus)
|
||||||
pkg.WhiteStatus = pkg.ParseStatus(pkg.WhiteStatus, opt.WhiteStatus)
|
pkg.WhiteStatus = pkg.ParseStatus(pkg.DefaultWhiteStatus, opt.WhiteStatus)
|
||||||
if opt.FuzzyStatus == "all" {
|
if opt.FuzzyStatus == "all" {
|
||||||
pool.EnableAllFuzzy = true
|
pool.EnableAllFuzzy = true
|
||||||
} else {
|
} else {
|
||||||
pkg.FuzzyStatus = pkg.ParseStatus(pkg.FuzzyStatus, opt.FuzzyStatus)
|
pkg.FuzzyStatus = pkg.ParseStatus(pkg.DefaultFuzzyStatus, opt.FuzzyStatus)
|
||||||
}
|
}
|
||||||
|
|
||||||
if opt.Unique {
|
if opt.Unique {
|
||||||
pool.EnableAllUnique = true
|
pool.EnableAllUnique = true
|
||||||
} else {
|
} 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)
|
logs.Log.Logf(pkg.LogVerbose, "Black Status: %v, WhiteStatus: %v, WAFStatus: %v", pkg.BlackStatus, pkg.WhiteStatus, pkg.WAFStatus)
|
||||||
|
@ -545,7 +545,7 @@ func (pool *BrutePool) Upgrade(bl *baseline.Baseline) error {
|
|||||||
|
|
||||||
func (pool *BrutePool) PreCompare(resp *ihttp.Response) error {
|
func (pool *BrutePool) PreCompare(resp *ihttp.Response) error {
|
||||||
status := resp.StatusCode()
|
status := resp.StatusCode()
|
||||||
if iutils.IntsContains(pkg.WhiteStatus, status) {
|
if pkg.StatusContain(pkg.WhiteStatus, status) {
|
||||||
// 如果为白名单状态码则直接返回
|
// 如果为白名单状态码则直接返回
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -553,11 +553,11 @@ func (pool *BrutePool) PreCompare(resp *ihttp.Response) error {
|
|||||||
// return pkg.ErrSameStatus
|
// return pkg.ErrSameStatus
|
||||||
//}
|
//}
|
||||||
|
|
||||||
if iutils.IntsContains(pkg.BlackStatus, status) {
|
if pkg.StatusContain(pkg.BlackStatus, status) {
|
||||||
return pkg.ErrBadStatus
|
return pkg.ErrBadStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
if iutils.IntsContains(pkg.WAFStatus, status) {
|
if pkg.StatusContain(pkg.WAFStatus, status) {
|
||||||
return pkg.ErrWaf
|
return pkg.ErrWaf
|
||||||
}
|
}
|
||||||
|
|
||||||
|
79
pkg/utils.go
79
pkg/utils.go
@ -27,10 +27,14 @@ import (
|
|||||||
var (
|
var (
|
||||||
LogVerbose = logs.Warn - 2
|
LogVerbose = logs.Warn - 2
|
||||||
LogFuzz = logs.Warn - 1
|
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
|
WhiteStatus = []int{} // cmd input, 200
|
||||||
BlackStatus = []int{} // cmd input, 400,410
|
BlackStatus = []int{} // cmd input, 400,410
|
||||||
FuzzyStatus = []int{} // cmd input, 500,501,502,503
|
FuzzyStatus = []int{} // cmd input, 500,501,502,503
|
||||||
WAFStatus = []int{493, 418, 1020, 406, 429}
|
WAFStatus = []int{493, 418, 1020, 406, 429, 406, 412}
|
||||||
UniqueStatus = []int{} // 相同unique的403表示命中了同一条acl, 相同unique的200表示default页面
|
UniqueStatus = []int{} // 相同unique的403表示命中了同一条acl, 相同unique的200表示default页面
|
||||||
|
|
||||||
// plugins
|
// plugins
|
||||||
@ -417,40 +421,87 @@ func ParseExtension(s string) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseStatus parses the input string and updates the preset status filters.
|
||||||
func ParseStatus(preset []int, changed string) []int {
|
func ParseStatus(preset []int, changed string) []int {
|
||||||
if changed == "" {
|
if changed == "" {
|
||||||
return preset
|
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, "+") {
|
if strings.HasPrefix(changed, "+") {
|
||||||
for _, s := range strings.Split(changed[1:], ",") {
|
for _, s := range strings.Split(changed[1:], ",") {
|
||||||
if t, err := strconv.Atoi(s); err != nil {
|
if t, _ := parseToken(s); t != 0 {
|
||||||
continue
|
|
||||||
} else {
|
|
||||||
preset = append(preset, t)
|
preset = append(preset, t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if strings.HasPrefix(changed, "!") {
|
} else if strings.HasPrefix(changed, "!") {
|
||||||
for _, s := range strings.Split(changed[1:], ",") {
|
for _, s := range strings.Split(changed[1:], ",") {
|
||||||
for i, status := range preset {
|
if t, _ := parseToken(s); t != 0 {
|
||||||
if t, err := strconv.Atoi(s); err != nil {
|
newPreset := preset[:0]
|
||||||
break
|
for _, val := range preset {
|
||||||
} else if t == status {
|
if val != t {
|
||||||
preset = append(preset[:i], preset[i+1:]...)
|
newPreset = append(newPreset, val)
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
preset = newPreset
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
preset = []int{}
|
preset = []int{}
|
||||||
for _, s := range strings.Split(changed, ",") {
|
for _, s := range strings.Split(changed, ",") {
|
||||||
if t, err := strconv.Atoi(s); err != nil {
|
if t, _ := parseToken(s); t != 0 {
|
||||||
continue
|
|
||||||
} else {
|
|
||||||
preset = append(preset, t)
|
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) {
|
func LoadFileToSlice(filename string) ([]string, error) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user