github.com/crowdsecurity/crowdsec@v1.6.1/pkg/types/appsec_event.go (about) 1 package types 2 3 import ( 4 "regexp" 5 "slices" 6 7 log "github.com/sirupsen/logrus" 8 ) 9 10 /* 11 1. If user triggered a rule that is for a CVE, that has high confidence and that is blocking, ban 12 2. If user triggered 3 distinct rules with medium confidence across 3 different requests, ban 13 14 15 any(evt.Waf.ByTag("CVE"), {.confidence == "high" && .action == "block"}) 16 17 len(evt.Waf.ByTagRx("*CVE*").ByConfidence("high").ByAction("block")) > 1 18 19 */ 20 21 type MatchedRules []map[string]interface{} 22 23 type AppsecEvent struct { 24 HasInBandMatches, HasOutBandMatches bool 25 MatchedRules 26 Vars map[string]string 27 } 28 type Field string 29 30 func (f Field) String() string { 31 return string(f) 32 } 33 34 const ( 35 ID Field = "id" 36 RuleType Field = "rule_type" 37 Tags Field = "tags" 38 File Field = "file" 39 Confidence Field = "confidence" 40 Revision Field = "revision" 41 SecMark Field = "secmark" 42 Accuracy Field = "accuracy" 43 Msg Field = "msg" 44 Severity Field = "severity" 45 Kind Field = "kind" 46 ) 47 48 func (w AppsecEvent) GetVar(varName string) string { 49 if w.Vars == nil { 50 return "" 51 } 52 if val, ok := w.Vars[varName]; ok { 53 return val 54 } 55 log.Infof("var %s not found. Available variables: %+v", varName, w.Vars) 56 return "" 57 58 } 59 60 // getters 61 func (w MatchedRules) GetField(field Field) []interface{} { 62 ret := make([]interface{}, 0) 63 for _, rule := range w { 64 ret = append(ret, rule[field.String()]) 65 } 66 return ret 67 } 68 69 func (w MatchedRules) GetURI() string { 70 for _, rule := range w { 71 return rule["uri"].(string) 72 } 73 return "" 74 } 75 76 func (w MatchedRules) GetHash() string { 77 for _, rule := range w { 78 //@sbl : let's fix this 79 return rule["hash"].(string) 80 } 81 return "" 82 } 83 84 func (w MatchedRules) GetVersion() string { 85 for _, rule := range w { 86 //@sbl : let's fix this 87 return rule["version"].(string) 88 } 89 return "" 90 } 91 92 func (w MatchedRules) GetName() string { 93 for _, rule := range w { 94 //@sbl : let's fix this 95 return rule["name"].(string) 96 } 97 return "" 98 } 99 100 func (w MatchedRules) GetMethod() string { 101 for _, rule := range w { 102 return rule["method"].(string) 103 } 104 return "" 105 } 106 107 func (w MatchedRules) GetRuleIDs() []int { 108 ret := make([]int, 0) 109 for _, rule := range w { 110 ret = append(ret, rule["id"].(int)) 111 } 112 return ret 113 } 114 115 func (w MatchedRules) Kinds() []string { 116 ret := make([]string, 0) 117 for _, rule := range w { 118 exists := false 119 for _, val := range ret { 120 if val == rule["kind"] { 121 exists = true 122 break 123 } 124 } 125 if !exists { 126 ret = append(ret, rule["kind"].(string)) 127 } 128 } 129 return ret 130 } 131 132 func (w MatchedRules) GetMatchedZones() []string { 133 ret := make([]string, 0) 134 135 for _, rule := range w { 136 for _, zone := range rule["matched_zones"].([]string) { 137 if !slices.Contains(ret, zone) { 138 ret = append(ret, zone) 139 } 140 } 141 } 142 return ret 143 } 144 145 // filters 146 func (w MatchedRules) ByID(id int) MatchedRules { 147 ret := MatchedRules{} 148 149 for _, rule := range w { 150 if rule["id"] == id { 151 ret = append(ret, rule) 152 } 153 } 154 return ret 155 } 156 157 func (w MatchedRules) ByKind(kind string) MatchedRules { 158 ret := MatchedRules{} 159 for _, rule := range w { 160 if rule["kind"] == kind { 161 ret = append(ret, rule) 162 } 163 } 164 return ret 165 } 166 167 func (w MatchedRules) ByTags(match []string) MatchedRules { 168 ret := MatchedRules{} 169 for _, rule := range w { 170 for _, tag := range rule["tags"].([]string) { 171 for _, match_tag := range match { 172 if tag == match_tag { 173 ret = append(ret, rule) 174 break 175 } 176 } 177 } 178 } 179 return ret 180 } 181 182 func (w MatchedRules) ByTag(match string) MatchedRules { 183 ret := MatchedRules{} 184 for _, rule := range w { 185 for _, tag := range rule["tags"].([]string) { 186 if tag == match { 187 ret = append(ret, rule) 188 break 189 } 190 } 191 } 192 return ret 193 } 194 195 func (w MatchedRules) ByTagRx(rx string) MatchedRules { 196 ret := MatchedRules{} 197 re := regexp.MustCompile(rx) 198 if re == nil { 199 return ret 200 } 201 for _, rule := range w { 202 for _, tag := range rule["tags"].([]string) { 203 log.Debugf("ByTagRx: %s = %s -> %t", rx, tag, re.MatchString(tag)) 204 if re.MatchString(tag) { 205 ret = append(ret, rule) 206 break 207 } 208 } 209 } 210 return ret 211 } 212 213 func (w MatchedRules) ByDisruptiveness(is bool) MatchedRules { 214 ret := MatchedRules{} 215 for _, rule := range w { 216 if rule["disruptive"] == is { 217 ret = append(ret, rule) 218 } 219 } 220 log.Debugf("ByDisruptiveness(%t) -> %d", is, len(ret)) 221 222 return ret 223 } 224 225 func (w MatchedRules) BySeverity(severity string) MatchedRules { 226 ret := MatchedRules{} 227 for _, rule := range w { 228 if rule["severity"] == severity { 229 ret = append(ret, rule) 230 } 231 } 232 log.Debugf("BySeverity(%s) -> %d", severity, len(ret)) 233 return ret 234 } 235 236 func (w MatchedRules) ByAccuracy(accuracy string) MatchedRules { 237 ret := MatchedRules{} 238 for _, rule := range w { 239 if rule["accuracy"] == accuracy { 240 ret = append(ret, rule) 241 } 242 } 243 log.Debugf("ByAccuracy(%s) -> %d", accuracy, len(ret)) 244 return ret 245 }