Skip to content

Commit 8afb897

Browse files
committed
add stop_if_match/mismatch
1 parent 4c9d500 commit 8afb897

File tree

3 files changed

+59
-44
lines changed

3 files changed

+59
-44
lines changed

pkg/core/checker.go

+19-31
Original file line numberDiff line numberDiff line change
@@ -34,19 +34,18 @@ func (c *Checker) Check(target string, pocItem poc.Poc) (err error) {
3434
c.FastClient.DialTimeout = c.Options.Config.ConfigHttp.DialTimeout
3535
c.FastClient.UserAgent = c.Options.Config.ConfigHttp.UserAgent
3636

37-
pocHandler := ""
37+
matchCondition := ""
3838
if strings.Contains(pocItem.Expression, "&&") && !strings.Contains(pocItem.Expression, "||") {
39-
pocHandler = poc.ALLAND
39+
matchCondition = poc.STOP_IF_FIRST_MISMATCH
4040
}
4141
if strings.Contains(pocItem.Expression, "||") && !strings.Contains(pocItem.Expression, "&&") {
42-
pocHandler = poc.ALLOR
42+
matchCondition = poc.STOP_IF_FIRST_MATCH
4343
}
4444

4545
if !strings.HasPrefix(target, "http://") && !strings.HasPrefix(target, "https://") {
4646
target = "http://" + target
4747
}
4848

49-
// original request
5049
c.OriginalRequest, err = http.NewRequest("GET", target, nil)
5150
if err != nil {
5251
log.Log().Error(fmt.Sprintf("rule map originalRequest err, %s", err.Error()))
@@ -76,67 +75,56 @@ func (c *Checker) Check(target string, pocItem poc.Poc) (err error) {
7675
k := ruleMap.Key
7776
rule := ruleMap.Value
7877

79-
utils.RandSleep(500) // firewall just test.
78+
utils.RandSleep(500)
8079

81-
err = c.FastClient.HTTPRequest(c.OriginalRequest, rule, c.VariableMap)
82-
if err != nil {
83-
log.Log().Error(fmt.Sprintf("rule map fasthttp.HTTPRequest err, %s", err.Error()))
84-
c.CustomLib.WriteRuleFunctionsROptions(k, false)
85-
continue
86-
}
87-
88-
// run cel expression
89-
isVul, err := c.CustomLib.RunEval(rule.Expression, c.VariableMap)
90-
if err != nil {
91-
log.Log().Error(fmt.Sprintf("rule map RunEval err, %s", err.Error()))
92-
c.CustomLib.WriteRuleFunctionsROptions(k, false)
93-
continue // not return, because may be need test next pocItem. ???
80+
isMatch := false
81+
if err = c.FastClient.HTTPRequest(c.OriginalRequest, rule, c.VariableMap); err == nil {
82+
evalResult, _ := c.CustomLib.RunEval(rule.Expression, c.VariableMap)
83+
isMatch = evalResult.Value().(bool)
9484
}
9585

96-
// set result function eg: r1() r2()
97-
c.CustomLib.WriteRuleFunctionsROptions(k, isVul.Value().(bool))
86+
c.CustomLib.WriteRuleFunctionsROptions(k, isMatch)
9887

99-
// update output cel and variableMap
10088
if len(rule.Output) > 0 {
10189
c.UpdateVariableMap(rule.Output)
10290
}
10391

104-
c.Result.AllPocResult = append(c.Result.AllPocResult, &PocResult{IsVul: isVul.Value().(bool), ResultRequest: c.VariableMap["request"].(*proto.Request), ResultResponse: c.VariableMap["response"].(*proto.Response)})
92+
c.Result.AllPocResult = append(c.Result.AllPocResult,
93+
&PocResult{IsVul: isMatch, ResultRequest: c.VariableMap["request"].(*proto.Request), ResultResponse: c.VariableMap["response"].(*proto.Response)})
10594

106-
if rule.Request.Todo == poc.TODO_FAILURE_NOT_CONTINUE && !isVul.Value().(bool) {
95+
if rule.StopIfMismatch && !isMatch {
10796
c.Result.IsVul = false
10897
c.Options.ApiCallBack(c.Result)
10998
return err
11099
}
111100

112-
if rule.Request.Todo == poc.TODO_SUCCESS_NOT_CONTINUE && isVul.Value().(bool) {
101+
if rule.StopIfMatch && isMatch {
113102
c.Result.IsVul = true
114103
c.Options.ApiCallBack(c.Result)
115104
return err
116105
}
117106

118-
if pocHandler == poc.ALLOR && isVul.Value().(bool) {
119-
c.Result.IsVul = true
107+
if matchCondition == poc.STOP_IF_FIRST_MISMATCH && !isMatch {
108+
c.Result.IsVul = false
120109
c.Options.ApiCallBack(c.Result)
121110
return err
122111
}
123-
if pocHandler == poc.ALLAND && !isVul.Value().(bool) {
124-
c.Result.IsVul = false
112+
113+
if matchCondition == poc.STOP_IF_FIRST_MATCH && isMatch {
114+
c.Result.IsVul = true
125115
c.Options.ApiCallBack(c.Result)
126116
return err
127117
}
128118
}
129119

130-
// run final cel expression
131120
isVul, err := c.CustomLib.RunEval(pocItem.Expression, c.VariableMap)
132121
if err != nil {
133-
log.Log().Error(fmt.Sprintf("final RunEval err, %s", err.Error()))
122+
log.Log().Error(fmt.Sprintf("Final RunEval Error: %s", err.Error()))
134123
c.Result.IsVul = false
135124
c.Options.ApiCallBack(c.Result)
136125
return err
137126
}
138127

139-
// save final result
140128
c.Result.IsVul = isVul.Value().(bool)
141129
c.Options.ApiCallBack(c.Result)
142130

pkg/poc/poc.go

+15-13
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,8 @@ import (
1313
// Rule有序,参考:https://github.com/WAY29/pocV/blob/main/pkg/xray/structs/poc.go
1414

1515
const (
16-
ALLOR = "allor"
17-
ALLAND = "alland"
18-
TODO_FAILURE_NOT_CONTINUE = "TODO_FAILURE_NOT_CONTINUE" // 请求失败不继续
19-
TODO_SUCCESS_NOT_CONTINUE = "TODO_SUCCESS_NOT_CONTINUE" // 请求成功不继续
16+
STOP_IF_FIRST_MATCH = "STOP_IF_FIRST_MATCH"
17+
STOP_IF_FIRST_MISMATCH = "STOP_IF_FIRST_MISMATCH"
2018
)
2119

2220
type Poc struct {
@@ -47,24 +45,27 @@ type RuleMap struct {
4745
// 用于帮助yaml解析,保证Rule有序
4846
type RuleMapSlice []RuleMap
4947
type Rule struct {
50-
Request RuleRequest `yaml:"request"`
51-
Expression string `yaml:"expression"`
52-
Output yaml.MapSlice `yaml:"output"`
53-
order int
48+
Request RuleRequest `yaml:"request"`
49+
Expression string `yaml:"expression"`
50+
Output yaml.MapSlice `yaml:"output"`
51+
StopIfMatch bool `yaml:"stop_if_match"`
52+
StopIfMismatch bool `yaml:"stop_if_mismatch"`
53+
order int
5454
}
5555

5656
type ruleAlias struct {
57-
Request RuleRequest `yaml:"request"`
58-
Expression string `yaml:"expression"`
59-
Output yaml.MapSlice `yaml:"output"`
57+
Request RuleRequest `yaml:"request"`
58+
Expression string `yaml:"expression"`
59+
Output yaml.MapSlice `yaml:"output"`
60+
StopIfMatch bool `yaml:"stop_if_match"`
61+
StopIfMismatch bool `yaml:"stop_if_mismatch"`
6062
}
6163

6264
// http/tcp/udp cache 是否使用缓存的请求,如果该选项为 true,那么如果在一次探测中其它脚本对相同目标发送过相同请求,那么便使用之前缓存的响应,而不发新的数据包
6365
// content 用于tcp/udp请求,请求内容,比如:content: "request"
6466
// read_timeout 用于tcp/udp请求,发送请求之后的读取超时时间(注 实际是一个 int, 但是为了能够变量渲染,设置为 string)
6567
// connection_id 用于tcp/udp请求,连接 id ,同一个连接 id 复用连接(注 不允许用0; cache 为 true 的时候可能会导致请求不会发送,所以如果有特殊需求记得 cache: false)
6668
type RuleRequest struct {
67-
Cache bool `yaml:"cache"`
6869
Content string `yaml:"content"` // tcp/udp专用
6970
ReadTimeout string `yaml:"read_timeout"` // tcp/udp专用
7071
ConnectionId string `yaml:"connection_id"` // tcp/udp专用
@@ -73,7 +74,6 @@ type RuleRequest struct {
7374
Headers map[string]string `yaml:"headers"`
7475
Body string `yaml:"body"`
7576
FollowRedirects bool `yaml:"follow_redirects"`
76-
Todo string `yaml:"todo"`
7777
}
7878

7979
// 以下开始是 信息部分
@@ -162,6 +162,8 @@ func (r *Rule) UnmarshalYAML(unmarshal func(interface{}) error) error {
162162
r.Request = tmp.Request
163163
r.Expression = tmp.Expression
164164
r.Output = tmp.Output
165+
r.StopIfMatch = tmp.StopIfMatch
166+
r.StopIfMismatch = tmp.StopIfMismatch
165167
r.order = order
166168

167169
order += 1

pocs/stop_if_match_test.yaml

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
id: stop_if_match_test
2+
3+
info:
4+
name: Stop if match test
5+
author: zan8in
6+
severity: info
7+
8+
rules:
9+
r0:
10+
request:
11+
method: GET
12+
path: /
13+
expression: response.status==200
14+
stop_if_match: true
15+
r1:
16+
request:
17+
method: GET
18+
path: /test1.php
19+
expression: response.status == 200
20+
r2:
21+
request:
22+
method: GET
23+
path: /test1.php
24+
expression: response.status == 200
25+
expression: r0() && (r1() || r2())

0 commit comments

Comments
 (0)