Check-in [c53f529c1f]
Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | add some tags: to sample rules |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
c53f529c1f234e1436f9998f50553855 |
User & Date: | mario 2020-12-26 22:35:17 |
Context
2020-12-26
| ||
22:37 | Use radiobuttons for exclusive actions (deny/block), move pause into params section, fix SecRuleCombined to use deepcopy (instead of duplicating flags in global rule) check-in: 129ce9633e user: mario tags: trunk | |
22:35 | add some tags: to sample rules check-in: c53f529c1f user: mario tags: trunk | |
2020-12-23
| ||
23:25 | Release as 0.7.0 check-in: a191732f7b user: mario tags: trunk, 0.7.0 | |
Changes
Changes to modseccfg/recipe.py.
︙ | ︙ | |||
104 105 106 107 108 109 110 | # SecRuleUpdateActionById $id "pass,status:200,log,auditlog" """, "URL to DetectionOnly": """ # Set one URL to DetectionOnly # | | | | | | | | 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | # SecRuleUpdateActionById $id "pass,status:200,log,auditlog" """, "URL to DetectionOnly": """ # Set one URL to DetectionOnly # SecRule REQUEST_URI "$request_uri" "phase:1,id:$rand,tag:modseccfg,tag:url-detectiononly,t:none,t:lowercase,pass,msg:'DetectionOnly for $request_uri',ctl:ruleEngine=DetectionOnly" """, #-- from REQUEST-900-EXCLUSION examples "Example Exlusions": { "Ignore param for tag": """ # Removing a specific ARGS parameter from inspection for only certain attacks SecRule REQUEST_FILENAME "@endsWith $PATH" "id:$rand,phase:2,pass,nolog,tag:modseccfg,tag:ignore-param,ctl:ruleRemoveTargetByTag=attack-sqli;ARGS:pwd" """, "Ignore param for all": """ # Removing a specific ARGS parameter from inspection for all CRS rules SecRule REQUEST_FILENAME "@endsWith /wp-login.php" "id:$rand,phase:2,pass,nolog,tag:modseccfg,tag:ignore-param,ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pwd" """, "Remove rule range": """ # Removing a range of rules SecRule REQUEST_FILENAME "@beginsWith /admin" "id:$rand,phase:2,pass,nolog,tag:modseccfg,tag:remove-rule,ctl:ruleRemoveById=941000-942999" """ }, #-- developer tools "Whitelist IP": { "Exempt REMOTE_ADDR": """ # Exempt client addr from all SecRules # SecRule REMOTE_ADDR "@streq $remote_addr" "phase:1,id:$rand,t:none,nolog,allow,tag:modseccfg,tag:whitelist,ctl:ruleEngine=Off,ctl:auditEngine=Off" """, "Whitelist from file": """ # List of IPs from filename trigger DetectionOnly mode # SecRule REMOTE_ADDR "@pmFromFile $confn.whitelist" "phase:1,id:$rand,t:none,nolog,allow,tag:modseccfg,tag:whitelist,ctl:ruleEngine=DetectionOnly" """ }, #-- complex/setup rules "Macros": { "Macro definitions": """ |
︙ | ︙ | |||
162 163 164 165 166 167 168 | <Macro NEWID $STR> # define %{ENV:NEWID} in the 50000 range; might yield duplicates SetEnvIfExpr "md5('$STR') =~ /(\d).*(\d).*(\d).*(\d)/" "NEWID=5$1$2$3$4" </Macro> <Macro SecRuleRemoveByPath $ID $PATH> Use NEWID "$ID$PATH" | | | | | 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 | <Macro NEWID $STR> # define %{ENV:NEWID} in the 50000 range; might yield duplicates SetEnvIfExpr "md5('$STR') =~ /(\d).*(\d).*(\d).*(\d)/" "NEWID=5$1$2$3$4" </Macro> <Macro SecRuleRemoveByPath $ID $PATH> Use NEWID "$ID$PATH" SecRule REQUEST_URI "@streq $PATH" "id:%{ENV:NEWID},phase:1,t:none,pass,tag:modseccfg,tag:whitelist,msg:'Whitelist Β«$PATHΒ»',ctl:removeById=$ID" </Macro> <Macro SecIgnoreArgByPathAndId $ID $PATH $ARG> Use NEWID "$ID$PATH" SecRule REQUEST_URI "@streq $PATH" "id:%{ENV:NEWID},phase:1,t:none,nolog,pass,tag:modseccfg,tag:remove-rule,ctl:ruleRemoveTargetById=$ID;ARGS:$ARG" </Macro> <Macro SecVar $VAR $VAL> Use NEWID "$VAR=$VAL" SecAction "id:%{ENV:NEWID},phase:1,nolog,pass,tag:modseccfg,tag:setvar,t:none,setvar:'$VAR=$VAL'" </Macro> </IfModule> """ }, #-- main config |
︙ | ︙ | |||
228 229 230 231 232 233 234 | # but update only CRSs tx.real_ip and remote_addr internally. Not sure # if this will yield correct audit log entries. # <IfModule mod_security.c> # Test if remote_addr matches Cloudflare IPs # SecRule REMOTE_ADDR "@ipMatch 173.245.48.0/20,103.21.244.0/22,103.22.200.0/22,103.31.4.0/22,141.101.64.0/18,108.162.192.0/18,190.93.240.0/20,188.114.96.0/20,197.234.240.0/22,198.41.128.0/17,162.158.0.0/15,104.16.0.0/12,172.64.0.0/13,131.0.72.0/22,2400:cb00::/32,2606:4700::/32,2803:f800::/32,2405:b500::/32,2405:8100::/32,2a06:98c0::/29,2c0f:f248::/32" \ | | | | 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 | # but update only CRSs tx.real_ip and remote_addr internally. Not sure # if this will yield correct audit log entries. # <IfModule mod_security.c> # Test if remote_addr matches Cloudflare IPs # SecRule REMOTE_ADDR "@ipMatch 173.245.48.0/20,103.21.244.0/22,103.22.200.0/22,103.31.4.0/22,141.101.64.0/18,108.162.192.0/18,190.93.240.0/20,188.114.96.0/20,197.234.240.0/22,198.41.128.0/17,162.158.0.0/15,104.16.0.0/12,172.64.0.0/13,131.0.72.0/22,2400:cb00::/32,2606:4700::/32,2803:f800::/32,2405:b500::/32,2405:8100::/32,2a06:98c0::/29,2c0f:f248::/32" \ "id:7030,t:none,pass,setvar:TX.IS_CLOUDFLARE=1,setvar:TX.IS_CDN=1,tag:modseccfg,tag:remote-addr,tag:setvar,msg:'Cloudflare CDN'" # Update TX.REAL.IP + REMOTE_ADDR from CF-Connecting-IP: # SecRule TX.IS_CLOUDFLARE "@eq 1" "id:7031,t:none,chain,pass,tag:modseccfg,tag:remote-addr,tag:setvar,msg:'Set TX.REAL_IP from Cloudflare CF-Connecting-IP'" SecRule REQUEST_HEADERS:cf-connecting-ip "@rx ^[\d\.:a-f]+$" "pass,t:none,capture,setvar:'TX.REAL_IP=%{TX:0}',setvar:'REMOTE_ADDR=%{TX:0}',setenv:'REMOTE_ADDR=%{TX:0}',logdata:'TX.REAL_IP=%{TX:0} set from Cloudflare CDN header'" </IfModule> """, "Apache Error/LogFormat": """ # Extend error log w/ REQUEST_URI and somewhat standard datetime format (not quite 8601) # β Feedback appreciated. What ought to be the post-90s Apache default? |
︙ | ︙ | |||
295 296 297 298 299 300 301 | def user_rec(): templates[".config/modseccfg/*"] = add = {} for fn in glob.glob(f"{conf.conf_dir}/**/*.txt"): src = open(fn, "r", encoding="utf-8").read() add[fn[len(conf.conf_dir)+1:]] = src # inject recipe list to main menu | | | 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 | def user_rec(): templates[".config/modseccfg/*"] = add = {} for fn in glob.glob(f"{conf.conf_dir}/**/*.txt"): src = open(fn, "r", encoding="utf-8").read() add[fn[len(conf.conf_dir)+1:]] = src # inject recipe list to main menu def init(menu, **kwargs): if conf.get("user_recipes"): user_rec() i_ls = menu.index(["Recipe"]) # already a list menu[i_ls].append(ls(templates.__dict__)) def has(name): return name in templates.has |
︙ | ︙ | |||
318 319 320 321 322 323 324 325 326 327 328 329 330 331 | self.name = name self.fn = data["confn"] vars = self.vars(data) # find text or func text = self.find_in_dict(raw_event, templates) if type(text) is str: text = dedent(text).lstrip() text = self.repl(text, vars) else: text = text(data, vars).lstrip() #print(data) #print(text) | > > > > | 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 | self.name = name self.fn = data["confn"] vars = self.vars(data) # find text or func text = self.find_in_dict(raw_event, templates) if type(text) is str: if text.startswith("@"): # or better: pluginconf.get_data() text = re.sub("[^/]+$", text.lstrip("@"), __file__) text = open(text, "r", encoding="utf-8").read() text = dedent(text).lstrip() text = self.repl(text, vars) else: text = text(data, vars).lstrip() #print(data) #print(text) |
︙ | ︙ |