From b73c707a3bf27ceede28078464c6d7b2f2373cf6 Mon Sep 17 00:00:00 2001 From: ZacharyZcR Date: Tue, 1 Sep 2026 15:09:00 +0800 Subject: [PATCH] fix: handle encoded POC set values --- webscan/lib/eval_misc.go | 10 ++++ webscan/lib/eval_test.go | 17 ++++++ webscan/lib/poc_executor.go | 38 ++++++++++++ webscan/lib/poc_executor_test.go | 58 ++++++++++++++----- .../ecology-hrmcareerapplyperview-sqli.yaml | 2 +- 5 files changed, 110 insertions(+), 15 deletions(-) diff --git a/webscan/lib/eval_misc.go b/webscan/lib/eval_misc.go index c6e0656..e540194 100644 --- a/webscan/lib/eval_misc.go +++ b/webscan/lib/eval_misc.go @@ -21,6 +21,10 @@ func registerMiscDeclarations() []*exprpb.Decl { decls.NewOverload("tongda_date", []*exprpb.Type{}, decls.String)), + decls.NewFunction("timestamp_second", + decls.NewOverload("timestamp_second_zero", + []*exprpb.Type{}, + decls.Int)), } } @@ -47,5 +51,11 @@ func registerMiscImplementations() []*functions.Overload { return types.String(time.Now().Format("0601")) }, }, + { + Operator: "timestamp_second_zero", + Function: func(value ...ref.Val) ref.Val { + return types.Int(time.Now().Unix()) + }, + }, } } diff --git a/webscan/lib/eval_test.go b/webscan/lib/eval_test.go index 9115dd8..3f83ac8 100644 --- a/webscan/lib/eval_test.go +++ b/webscan/lib/eval_test.go @@ -10,6 +10,7 @@ import ( "net/url" "strings" "testing" + "time" "github.com/google/cel-go/common/types" ) @@ -1393,3 +1394,19 @@ func TestMakeVarDecl(t *testing.T) { }) } } + +func TestTimestampSecond(t *testing.T) { + before := time.Now().Unix() + result, err := Evaluate(GetBaseEnv(), "timestamp_second()", map[string]interface{}{}) + if err != nil { + t.Fatal(err) + } + got, ok := result.Value().(int64) + if !ok { + t.Fatalf("timestamp_second() type = %T, want int64", result.Value()) + } + after := time.Now().Unix() + if got < before || got > after { + t.Fatalf("timestamp_second() = %d, want [%d, %d]", got, before, after) + } +} diff --git a/webscan/lib/poc_executor.go b/webscan/lib/poc_executor.go index 0f25879..c87f800 100644 --- a/webscan/lib/poc_executor.go +++ b/webscan/lib/poc_executor.go @@ -869,6 +869,10 @@ func cloneMap(tags map[string]string) map[string]string { // evalset 执行CEL表达式并处理特殊类型结果 func evalset(env *cel.Env, variableMap map[string]interface{}, k string, expression string) (string, error) { + if isPlainLiteral(expression, variableMap) { + variableMap[k] = expression + return expression, nil + } out, err := Evaluate(env, expression, variableMap) if err != nil { variableMap[k] = "" @@ -915,6 +919,11 @@ func isPlainLiteral(expr string, variableMap map[string]interface{}) bool { if _, exists := variableMap[expr]; exists { return false } + // Base64/JWT 常量常包含 +、/、= 或 .,这些字符在 CEL 中也是语法符号。 + // 先识别编码值,避免把密钥和令牌误当成表达式编译。 + if isEncodedLiteral(expr) { + return true + } // 含 CEL 语法特征的需要走 CEL 编译 for _, c := range expr { switch c { @@ -925,6 +934,35 @@ func isPlainLiteral(expr string, variableMap map[string]interface{}) bool { return true } +func isEncodedLiteral(value string) bool { + if strings.Count(value, ".") == 2 { + parts := strings.Split(value, ".") + for _, part := range parts { + if part == "" || strings.IndexFunc(part, func(r rune) bool { + return !isASCIIAlphaNumeric(r) && r != '-' && r != '_' + }) >= 0 { + return false + } + } + return true + } + + if len(value) < 4 || len(value)%4 != 0 { + return false + } + padding := strings.TrimRight(value, "=") + if len(value)-len(padding) > 2 { + return false + } + return strings.IndexFunc(padding, func(r rune) bool { + return !isASCIIAlphaNumeric(r) && r != '+' && r != '/' + }) < 0 +} + +func isASCIIAlphaNumeric(r rune) bool { + return r >= 'a' && r <= 'z' || r >= 'A' && r <= 'Z' || r >= '0' && r <= '9' +} + // CheckInfoPoc 检查POC信息并返回别名 func CheckInfoPoc(infostr string) string { for _, poc := range fingerprint.PocDatas { diff --git a/webscan/lib/poc_executor_test.go b/webscan/lib/poc_executor_test.go index d5ea069..3bb1fe8 100644 --- a/webscan/lib/poc_executor_test.go +++ b/webscan/lib/poc_executor_test.go @@ -608,16 +608,16 @@ func stringMatrixEqual(a, b [][]string) bool { func TestBuildVulnDetails(t *testing.T) { tests := []struct { - name string - pocDef *Poc - vulName string - params StrMap - wantKeys []string - wantNoKeys []string - wantVulnType string - wantVulnName string - wantParamVal string - wantParamKey string + name string + pocDef *Poc + vulName string + params StrMap + wantKeys []string + wantNoKeys []string + wantVulnType string + wantVulnName string + wantParamVal string + wantParamKey string }{ { name: "最小Poc只有Name", @@ -647,15 +647,15 @@ func TestBuildVulnDetails(t *testing.T) { wantVulnName: "Full Vuln", }, { - name: "有params则details含parameters字段", - pocDef: &Poc{Name: "poc-yaml-params"}, + name: "有params则details含parameters字段", + pocDef: &Poc{Name: "poc-yaml-params"}, vulName: "Params Vuln", params: StrMap{ {Key: "user", Value: "admin"}, {Key: "pass", Value: "123456"}, }, - wantKeys: []string{"vulnerability_type", "vulnerability_name", "parameters"}, - wantNoKeys: []string{"author"}, + wantKeys: []string{"vulnerability_type", "vulnerability_name", "parameters"}, + wantNoKeys: []string{"author"}, wantParamKey: "user", wantParamVal: "admin", }, @@ -865,3 +865,33 @@ func TestCollectVarDeclarations(t *testing.T) { } }) } + +func TestEvalSetTreatsEncodedValuesAsLiterals(t *testing.T) { + env := GetBaseEnv() + tests := []string{ + "fsHspZw/92PrS3XrPW+vxw==", + "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJuYWNvcyJ9.feetKmWoPnMkAebjkNnyuKo6c21_hzTgu0dfNqbdpZQ", + } + + for _, value := range tests { + variables := map[string]interface{}{} + got, err := evalset(env, variables, "token", value) + if err != nil { + t.Fatalf("evalset(%q) error = %v", value, err) + } + if got != value || variables["token"] != value { + t.Fatalf("evalset(%q) = %q, stored %v", value, got, variables["token"]) + } + } +} + +func TestEvalSetStillEvaluatesExpressions(t *testing.T) { + variables := map[string]interface{}{} + got, err := evalset(GetBaseEnv(), variables, "token", "randomLowercase(6)") + if err != nil { + t.Fatal(err) + } + if len(got) != 6 { + t.Fatalf("randomLowercase result length = %d, want 6", len(got)) + } +} diff --git a/webscan/pocs/ecology-hrmcareerapplyperview-sqli.yaml b/webscan/pocs/ecology-hrmcareerapplyperview-sqli.yaml index f813ea7..5183fe6 100644 --- a/webscan/pocs/ecology-hrmcareerapplyperview-sqli.yaml +++ b/webscan/pocs/ecology-hrmcareerapplyperview-sqli.yaml @@ -12,7 +12,7 @@ info: created: 2025/06/11 set: - randstr: randLowercase(6) + randstr: randomLowercase(6) rules: r0: request: