Check-in [8e624a20d3]
Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Type and description changes in crsoptions. Release as 0.3.0 |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk | 0.3.0 |
Files: | files | file ages | folders |
SHA3-256: |
8e624a20d346ccdea2374388ed922380 |
User & Date: | mario 2020-11-20 14:28:48 |
Context
2020-11-21
| ||
22:02 | Fix missing lookahead for rx.end (closing VHost section got stripped after all) check-in: efee51370c user: mario tags: trunk | |
2020-11-20
| ||
14:28 | Type and description changes in crsoptions. Release as 0.3.0 check-in: 8e624a20d3 user: mario tags: trunk, 0.3.0 | |
2020-11-19
| ||
15:49 | Prepare rules_in_between() lookup function. check-in: a1b61ab41b user: mario tags: trunk | |
Changes
Changes to FAQ.md.
︙ | ︙ | |||
78 79 80 81 82 83 84 | #### Are there sshfs options to be set? Secret config option is `sshfs_o`. #### Other secret options | | > > | > | > > | 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | #### Are there sshfs options to be set? Secret config option is `sshfs_o`. #### Other secret options `editor_font` can't be edited from the config window, due to being a list. The config definition allows to add a third font property `["โฆ", "โฆ", "bold"]` however. ### Can this use other log scanners? If there's a command line tool to scan audit logs for problems, then yes, an option could be added. (In fact, it's planned to bundle a bin/ folder and according menu for Log analyzers.) ### Why doesn't this provide for editing of VirtualHost sections? That would be more work. And less intuitive for the majority, and those that have properly separated vhosts into distinct config files. There's a few python packages for Apache config parsing that would allow so, but none that are overly convenient to build upon. (Not to mention support for non-destructive file updating.) #### It always writes to the first VirtualHost in a file Yes. All SecRule* flags are appended, or injected before any first closing `</VirtualHost>` |
︙ | ︙ |
Changes to Makefile.
1 2 3 4 5 6 7 8 9 10 11 | run: ./g.py setup: pandoc README.md -o README.rst version --read modseccfg/__init__.py --write modseccfg/mainwindow.py python3 setup.py bdist_wheel rm -r modseccfg.egg-info upload: setup python3 setup.py bdist_wheel upload | > | 1 2 3 4 5 6 7 8 9 10 11 12 | run: ./g.py setup: pandoc README.md -o README.rst version --read modseccfg/__init__.py --write modseccfg/mainwindow.py python3 setup.py bdist_wheel rm -r modseccfg.egg-info upload: setup python3 setup.py bdist_wheel upload rm -r modseccfg.egg-info |
Changes to NEWS.
1 2 3 4 5 6 7 | 0.2.0 (2020-11-17) * Added an [info] dialog for rule inspection. * Implemented [enable] to undo SecRemoveRemoveRuleById directives. * Keyboard bindings in main window, hourglass mouse pointer for updates, and uses appdirs now instead of a fixed CONFIG_HOME path. * Multiple dialogs (main, editor, window) can now run in parallel. * Config dictionary has been merged into appsettings. | > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 | 0.3.0 (2020-11-20) * Introduced editor for SecOption directives. * And an options dialog for CoreRuleSet variables. * Minor adaptions to pluginconf.gui, and decorators for mainwindow features. 0.2.0 (2020-11-17) * Added an [info] dialog for rule inspection. * Implemented [enable] to undo SecRemoveRemoveRuleById directives. * Keyboard bindings in main window, hourglass mouse pointer for updates, and uses appdirs now instead of a fixed CONFIG_HOME path. * Multiple dialogs (main, editor, window) can now run in parallel. * Config dictionary has been merged into appsettings. |
︙ | ︙ |
Changes to README.md.
1 2 3 4 5 6 7 | > *WARNING: THIS IS ALPHA STAGE QUALITY AND WILL MOST CERTAINLY DELETE YOUR APACHE CONFIGURATION* > - It doesn't, but: no warranty and such. - Also, hasn't many features yet. ## modseccfg * Simple GUI editor for SecRuleRemoveById settings * Tries to suggest false positives from error and audit logs | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | > *WARNING: THIS IS ALPHA STAGE QUALITY AND WILL MOST CERTAINLY DELETE YOUR APACHE CONFIGURATION* > - It doesn't, but: no warranty and such. - Also, hasn't many features yet. ## modseccfg * Simple GUI editor for SecRuleRemoveById settings * Tries to suggest false positives from error and audit logs * And configure mod_security and CoreRuleSet variables. * Runs locally, via `ssh -X` forwarding, or per `modseccfg vps5:/` automount. ![](https://fossil.include-once.org/modseccfg/raw/59f5daf65f51?m=image/gif) ## Installation |
︙ | ︙ | |||
75 76 77 78 79 80 81 | multiple `<VirtualHost>` in one `*.conf` (else only the first section will be augmented). ### Missing features * File permission check on remote host is non-functional still. * Doesn't process any audit.log yet. | | | | | 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | multiple `<VirtualHost>` in one `*.conf` (else only the first section will be augmented). ### Missing features * File permission check on remote host is non-functional still. * Doesn't process any audit.log yet. * Can't classify wrapped (`<Location>`/`<FilesMatch>`) rules yet. * ~~No rule information dialog.~~ * ~~No SecOption editor yet.~~ * ~~No CRS settings (setvar:crsโฆ) editor yet.~~ * Recipes are not worth using yet. * No sudo usage. |
Changes to dev/crsvars.conf.
︙ | ︙ | |||
37 38 39 40 41 42 43 | # # The OWASP ModSecurity Core Rule Set is distributed under # Apache Software License (ASL) version 2 # Please see the enclosed LICENSE file for full details. # ------------------------------------------------------------------------ | < < < < < < | 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | # # The OWASP ModSecurity Core Rule Set is distributed under # Apache Software License (ASL) version 2 # Please see the enclosed LICENSE file for full details. # ------------------------------------------------------------------------ # The OWASP ModSecurity Core Rule Set (CRS) is a set of generic attack # detection rules that provide a base level of protection for any web # application. They are written for the open source, cross-platform # ModSecurity Web Application Firewall. # # See also: # https://coreruleset.org/ # https://github.com/SpiderLabs/owasp-modsecurity-crs # https://www.owasp.org/index.php/Category:OWASP_ModSecurity_Core_Rule_Set_Project # # CRS requires ModSecurity version 2.8.0 or above. # We recommend to always use the newest ModSecurity version. # # The configuration directives/settings in this file are used to control # the OWASP ModSecurity CRS. These settings do **NOT** configure the main # ModSecurity settings (modsecurity.conf) such as SecRuleEngine, # SecRequestBodyAccess, SecAuditEngine, SecDebugLog, and XML processing. |
︙ | ︙ | |||
78 79 80 81 82 83 84 | # 3. rules/*.conf (the CRS rule files) # # Please refer to the INSTALL file for detailed installation instructions. # # | < < | 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | # 3. rules/*.conf (the CRS rule files) # # Please refer to the INSTALL file for detailed installation instructions. # # # The CRS can run in two modes: # # -- [[ Anomaly Scoring Mode (default) ]] -- # In CRS3, anomaly mode is the default and recommended mode, since it gives the # most accurate log information and offers the most flexibility in setting your # blocking policies. It is also called "collaborative detection mode". # In this mode, each matching rule increases an 'anomaly score'. |
︙ | ︙ | |||
156 157 158 159 160 161 162 | # if a Cookie or User-Agent header is blocked, it will also be blocked when # the client subsequently tries to access the homepage. You can also redirect # to another custom URL. # SecDefaultAction "phase:1,log,auditlog,redirect:'http://%{request_headers.host}/',tag:'Host: %{request_headers.host}'" # SecDefaultAction "phase:2,log,auditlog,redirect:'http://%{request_headers.host}/',tag:'Host: %{request_headers.host}'" | < < < | 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | # if a Cookie or User-Agent header is blocked, it will also be blocked when # the client subsequently tries to access the homepage. You can also redirect # to another custom URL. # SecDefaultAction "phase:1,log,auditlog,redirect:'http://%{request_headers.host}/',tag:'Host: %{request_headers.host}'" # SecDefaultAction "phase:2,log,auditlog,redirect:'http://%{request_headers.host}/',tag:'Host: %{request_headers.host}'" # The Paranoia Level (PL) setting allows you to choose the desired level # of rule checks that will add to your anomaly scores. # # With each paranoia level increase, the CRS enables additional rules # giving you a higher level of security. However, higher paranoia levels # also increase the possibility of blocking some legitimate traffic due to # false alarms (also named false positives or FPs). If you use higher |
︙ | ︙ | |||
237 238 239 240 241 242 243 | phase:1,\ nolog,\ pass,\ t:none,\ setvar:tx.executing_paranoia_level=1" | < < < | 226 227 228 229 230 231 232 233 234 235 236 237 238 239 | phase:1,\ nolog,\ pass,\ t:none,\ setvar:tx.executing_paranoia_level=1" # ModSecurity selects the body processor based on the Content-Type request # header. But clients are not always setting the Content-Type header for their # request body payloads. This will leave ModSecurity with limited vision into # the payload. The variable tx.enforce_bodyproc_urlencoded lets you force the # URLENCODED body processor in these situations. This is off by default, as it # implies a change of the behaviour of ModSecurity beyond CRS (the body # processor applies to all rules, not only CRS) and because it may lead to |
︙ | ︙ | |||
261 262 263 264 265 266 267 | phase:1,\ nolog,\ pass,\ t:none,\ setvar:tx.enforce_bodyproc_urlencoded=1" | < < < | 247 248 249 250 251 252 253 254 255 256 257 258 259 260 | phase:1,\ nolog,\ pass,\ t:none,\ setvar:tx.enforce_bodyproc_urlencoded=1" # Each rule in the CRS has an associated severity level. # These are the default scoring points for each severity level. # These settings will be used to increment the anomaly score if a rule matches. # You may adjust these points to your liking, but this is usually not needed. # # - CRITICAL severity: Anomaly Score of 5. # Mostly generated by the application attack rules (93x and 94x files). |
︙ | ︙ | |||
297 298 299 300 301 302 303 | t:none,\ setvar:tx.critical_anomaly_score=5,\ setvar:tx.error_anomaly_score=4,\ setvar:tx.warning_anomaly_score=3,\ setvar:tx.notice_anomaly_score=2" | < < < | 280 281 282 283 284 285 286 287 288 289 290 291 292 293 | t:none,\ setvar:tx.critical_anomaly_score=5,\ setvar:tx.error_anomaly_score=4,\ setvar:tx.warning_anomaly_score=3,\ setvar:tx.notice_anomaly_score=2" # Here, you can specify at which cumulative anomaly score an inbound request, # or outbound response, gets blocked. # # Most detected inbound threats will give a critical score of 5. # Smaller violations, like violations of protocol/standards, carry lower scores. # # [ At default value ] |
︙ | ︙ | |||
346 347 348 349 350 351 352 | phase:1,\ nolog,\ pass,\ t:none,\ setvar:tx.inbound_anomaly_score_threshold=5,\ setvar:tx.outbound_anomaly_score_threshold=4" | < < < | 326 327 328 329 330 331 332 333 334 335 336 337 338 339 | phase:1,\ nolog,\ pass,\ t:none,\ setvar:tx.inbound_anomaly_score_threshold=5,\ setvar:tx.outbound_anomaly_score_threshold=4" # Some well-known applications may undertake actions that appear to be # malicious. This includes actions such as allowing HTML or Javascript within # parameters. In such cases the CRS aims to prevent false positives by allowing # administrators to enable prebuilt, application specific exclusions on an # application by application basis. # These application specific exclusions are distinct from the rules that would # be placed in the REQUEST-900-EXCLUSION-RULES-BEFORE-CRS configuration file as |
︙ | ︙ | |||
390 391 392 393 394 395 396 | setvar:tx.crs_exclusions_cpanel=1,\ setvar:tx.crs_exclusions_drupal=1,\ setvar:tx.crs_exclusions_dokuwiki=1,\ setvar:tx.crs_exclusions_nextcloud=1,\ setvar:tx.crs_exclusions_wordpress=1,\ setvar:tx.crs_exclusions_xenforo=1" | | < < | 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 | setvar:tx.crs_exclusions_cpanel=1,\ setvar:tx.crs_exclusions_drupal=1,\ setvar:tx.crs_exclusions_dokuwiki=1,\ setvar:tx.crs_exclusions_nextcloud=1,\ setvar:tx.crs_exclusions_wordpress=1,\ setvar:tx.crs_exclusions_xenforo=1" # This section defines your policies for the HTTP protocol, such as: # - allowed HTTP versions, HTTP methods, allowed request Content-Types # - forbidden file extensions (e.g. .bak, .sql) and request headers (e.g. Proxy) # # These variables are used in the following rule files: # - REQUEST-911-METHOD-ENFORCEMENT.conf # - REQUEST-912-DOS-PROTECTION.conf |
︙ | ︙ | |||
496 497 498 499 500 501 502 | "id:900280,\ phase:1,\ nolog,\ pass,\ t:none,\ setvar:'tx.allowed_request_content_type_charset=utf-8|iso-8859-1|iso-8859-15|windows-1252'" | | < < | 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 | "id:900280,\ phase:1,\ nolog,\ pass,\ t:none,\ setvar:'tx.allowed_request_content_type_charset=utf-8|iso-8859-1|iso-8859-15|windows-1252'" # Here you can define optional limits on HTTP get/post parameters and uploads. # This can help to prevent application specific DoS attacks. # # These values are checked in REQUEST-920-PROTOCOL-ENFORCEMENT.conf. # Beware of blocking legitimate traffic when enabling these limits. # |
︙ | ︙ | |||
579 580 581 582 583 584 585 | phase:1,\ nolog,\ pass,\ t:none,\ setvar:tx.combined_file_sizes=1048576" | < < < | 552 553 554 555 556 557 558 559 560 561 562 563 564 565 | phase:1,\ nolog,\ pass,\ t:none,\ setvar:tx.combined_file_sizes=1048576" # Adding the Core Rule Set to an existing productive site can lead to false # positives, unexpected performance issues and other undesired side effects. # # It can be beneficial to test the water first by enabling the CRS for a # limited number of requests only and then, when you have solved the issues (if # any) and you have confidence in the setup, to raise the ratio of requests # being sent into the ruleset. |
︙ | ︙ | |||
616 617 618 619 620 621 622 | SecAction "id:900400,\ phase:1,\ pass,\ nolog,\ setvar:tx.sampling_percentage=100" | | < < | 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 | SecAction "id:900400,\ phase:1,\ pass,\ nolog,\ setvar:tx.sampling_percentage=100" # Optionally, you can check the client IP address against the Project Honey Pot # HTTPBL (dnsbl.httpbl.org). In order to use this, you need to register to get a # free API key. Set it here with SecHttpBlKey. # # Project Honeypot returns multiple different malicious IP types. # You may specify which you want to block by enabling or disabling them below. # |
︙ | ︙ | |||
643 644 645 646 647 648 649 | t:none,\ setvar:tx.block_search_ip=1,\ setvar:tx.block_suspicious_ip=1,\ setvar:tx.block_harvester_ip=1,\ setvar:tx.block_spammer_ip=1" | | < < | 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 | t:none,\ setvar:tx.block_search_ip=1,\ setvar:tx.block_suspicious_ip=1,\ setvar:tx.block_harvester_ip=1,\ setvar:tx.block_spammer_ip=1" # There are some rulesets that inspect geolocation data of the client IP address # (geoLookup). The CRS uses geoLookup to implement optional country blocking. # # To use geolocation, we make use of the MaxMind GeoIP database. # This database is not included with the CRS and must be downloaded. # You should also update the database regularly, for instance every month. # The CRS contains a tool to download it to util/geo-location/GeoIP.dat: |
︙ | ︙ | |||
695 696 697 698 699 700 701 | phase:1,\ nolog,\ pass,\ t:none,\ setvar:'tx.high_risk_country_codes='" | < < < | 661 662 663 664 665 666 667 668 669 670 671 672 673 674 | phase:1,\ nolog,\ pass,\ t:none,\ setvar:'tx.high_risk_country_codes='" # Optional DoS protection against clients making requests too quickly. # # When a client is making more than 100 requests (excluding static files) within # 60 seconds, this is considered a 'burst'. After two bursts, the client is # blocked for 600 seconds. # # Requests to static files are not counted towards DoS; they are listed in the |
︙ | ︙ | |||
723 724 725 726 727 728 729 | pass,\ t:none,\ setvar:'tx.dos_burst_time_slice=60',\ setvar:'tx.dos_counter_threshold=100',\ setvar:'tx.dos_block_timeout=600'" | | < < < < < | 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 | pass,\ t:none,\ setvar:'tx.dos_burst_time_slice=60',\ setvar:'tx.dos_counter_threshold=100',\ setvar:'tx.dos_block_timeout=600'" # The CRS can optionally check request contents for invalid UTF-8 encoding. # We only want to apply this check if UTF-8 encoding is actually used by the # site; otherwise it will result in false positives. # # Uncomment this rule to use this feature: # SecAction \ "id:900950,\ phase:1,\ nolog,\ pass,\ t:none,\ setvar:tx.crs_validate_utf8_encoding=1" # Blocking based on reputation is permanent in the CRS. Unlike other rules, # which look at the indvidual request, the blocking of IPs is based on # a persistent record in the IP collection, which remains active for a # certain amount of time. # # There are two ways an individual client can become flagged for blocking: # - External information (RBL, GeoIP, etc.) |
︙ | ︙ | |||
791 792 793 794 795 796 797 | phase:1,\ nolog,\ pass,\ t:none,\ setvar:tx.reput_block_duration=300" | | < < < < < | 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 | phase:1,\ nolog,\ pass,\ t:none,\ setvar:tx.reput_block_duration=300" # Set the SecCollectionTimeout directive from the ModSecurity default (1 hour) # to a lower setting which is appropriate to most sites. # This increases performance by cleaning out stale collection (block) entries. # # This value should be greater than or equal to: # tx.reput_block_duration (see section "Blocking Based on IP Reputation") and # tx.dos_block_timeout (see section "Anti-Automation / DoS Protection"). # # Ref: https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual#wiki-SecCollectionTimeout # Please keep this directive uncommented. # Default: 600 (10 minutes) SecCollectionTimeout 600 # The CRS checks the tx.crs_setup_version variable to ensure that the setup # has been loaded. If you are not planning to use this setup template, # you must manually set the tx.crs_setup_version variable before including # the CRS rules/* files. # # The variable is a numerical representation of the CRS version number. # E.g., v3.0.0 is represented as 300. |
︙ | ︙ |
Changes to dev/crsvars2pmd.py.
︙ | ︙ | |||
41 42 43 44 45 46 47 | "type": "str", "value": val.strip(","), # โ let's keep default values here (might strip it in dialog) "help": doc } if re.search("anomaly_score|paranoia_level", var): p["type"] = "select" | | | | | > | > | | 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | "type": "str", "value": val.strip(","), # โ let's keep default values here (might strip it in dialog) "help": doc } if re.search("anomaly_score|paranoia_level", var): p["type"] = "select" p["select"] = "0=0 (off)|1=1 (standard)|2=2 (extended)|3=3 (excessive)|4=4 (banking sector)|5=5 (absurd)" if var == "id": p["type"] = "select" p["select"] = "5999=5999|900999=900999" elif re.search("tx\.(block_|crs_excl|enforce_|do_|crs_validate)", var): # re.match("^[01]$", val) or re p["type"] = "bool" elif len(p["value"]) >= 50: p["type"] = "text" pmd1[p["name"]] = p # postprocess for name,p in pmd1.items(): if "select" in p: kv = p["select"].split("|") kv = [v.split("=", 2) for v in kv] p["select"] = dict(kv) #std #print(json.dumps(pmd, indent=4)) # write as ordereddict print("setvar = OrderedDict()") for k,d in pmd1.items(): print(f"setvar['{k}'] = " + json.dumps(d, indent=4)) #print(len(pmd2)) |
Changes to modseccfg/__init__.py.
1 2 3 4 5 | # encoding: utf-8 # api: python # type: init # title: modseccfg # description: Editor to tame mod_security rulesets | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | # encoding: utf-8 # api: python # type: init # title: modseccfg # description: Editor to tame mod_security rulesets # version: 0.3.0 # state: prototype # support: none # license: ASL # depends: python:pysimplegui (>= 3.0), python:pluginconf (>= 0.7.3), # python:appdirs (>= 1.3), python (>= 3.6), deb:python3-tk, bin:sshfs # priority: core # url: https://fossil.include-once.org/modseccfg/ # faq: https://fossil.include-once.org/modseccfg/doc/trunk/FAQ.md # category: config # classifiers: x11, http # |
︙ | ︙ |
Changes to modseccfg/crsoptions.py.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | # api: modseccfg # encoding: utf-8 # type: function # category: config # title: CRS options # description: config window for CoreRuleSet setvar flags # version: 0.1 # depends: pluginconf (>= 0.7.3) # config: # { name: crsopt_defaults, type: bool, value: 0, description: "Use defaults in place of existing *.conf options" } # license: ASL # author: OWASP CRS team (options and descriptions) # # Basically like SecOptions, but for CRS options (from crs-setup.conf). # But this module will not replace them, but inject a combined SecAction, # which overrides all variables in one swoop. # | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | # api: modseccfg # encoding: utf-8 # type: function # category: config # title: CRS options # description: config window for CoreRuleSet setvar flags # version: 0.1 # depends: pluginconf (>= 0.7.3) # config: # { name: crsopt_defaults, type: bool, value: 0, description: "Use defaults in place of existing *.conf options" } # { name: crsopt_undefine, type: bool, value: 1, description: "Undefine previous config rules per setvar" } # license: ASL # author: OWASP CRS team (options and descriptions) # # Basically like SecOptions, but for CRS options (from crs-setup.conf). # But this module will not replace them, but inject a combined SecAction, # which overrides all variables in one swoop. # |
︙ | ︙ | |||
29 30 31 32 33 34 35 | import re, json, os, copy from collections import OrderedDict import pluginconf.gui from modseccfg import utils, writer, vhosts, icons from modseccfg.utils import srvroot | | > | < < > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 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 153 154 155 156 157 158 159 160 161 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 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 | import re, json, os, copy from collections import OrderedDict import pluginconf.gui from modseccfg import utils, writer, vhosts, icons from modseccfg.utils import srvroot # autoconverted via `dev/crsvars2pmd.py` setvar = OrderedDict() setvar['id'] = { "id": "5999", "name": "id", "description": "Override variables early (5999) or inject after crs-setup (900999)", "type": "select", "value": "5999", "help": "Override variables early (5999) or inject after crs-setup (900999)\nYou want to use 9009999 if you update the global crs-setup.conf.\nBut if you need different settings for different vhosts, then\nkeep crs-setup.conf disabled, and create individual setup files.\n(This could probably be automated in the dialog. And ideally, we'd\nuse skipAfter= or something in conjunction for the override scheme.)", "select": { "5999": "5999", "900999": "900999" } } setvar['fn'] = { "id": "5998", "name": "fn", "description": "Which *.conf file to write back to.", "type": "str", "value": "/etc/modsecurty/crs/crs-setup.conf", "help": "Which *.conf file to write back to.\nIf you want to read out rules from crs-setup.conf, but then\nwrite to a custom location; use this option. Start the dialog\n(File\u2192CRS option) whilst crs-setup.conf is selected, then\nchange the target filename here." } setvar['tx.paranoia_level'] = { "id": "900000", "name": "tx.paranoia_level", "description": "The Paranoia Level (PL) setting allows you to choose the desired level", "type": "select", "value": "1", "help": "The Paranoia Level (PL) setting allows you to choose the desired level\nof rule checks that will add to your anomaly scores.\nWith each paranoia level increase, the CRS enables additional rules\ngiving you a higher level of security. However, higher paranoia levels\nalso increase the possibility of blocking some legitimate traffic due to\nfalse alarms (also named false positives or FPs). If you use higher\nparanoia levels, it is likely that you will need to add some exclusion\nrules for certain requests and applications receiving complex input.\n- A paranoia level of 1 is default. In this level, most core rules\nare enabled. PL1 is advised for beginners, installations\ncovering many different sites and applications, and for setups\nwith standard security requirements.\nAt PL1 you should face FPs rarely. If you encounter FPs, please\nopen an issue on the CRS GitHub site and don't forget to attach your\ncomplete Audit Log record for the request with the issue.\n- Paranoia level 2 includes many extra rules, for instance enabling\nmany regexp-based SQL and XSS injection protections, and adding\nextra keywords checked for code injections. PL2 is advised\nfor moderate to experienced users desiring more complete coverage\nand for installations with elevated security requirements.\nPL2 comes with some FPs which you need to handle.\n- Paranoia level 3 enables more rules and keyword lists, and tweaks\nlimits on special characters used. PL3 is aimed at users experienced\nat the handling of FPs and at installations with a high security\nrequirement.\n- Paranoia level 4 further restricts special characters.\nThe highest level is advised for experienced users protecting\ninstallations with very high security requirements. Running PL4 will\nlikely produce a very high number of FPs which have to be\ntreated before the site can go productive.\nRules in paranoia level 2 or higher will log their PL to the audit log;\nexample: [tag \"paranoia-level/2\"]. This allows you to deduct from the\naudit log how the WAF behavior is affected by paranoia level.\nIt is important to also look into the variable\ntx.enforce_bodyproc_urlencoded (Enforce Body Processor URLENCODED)\ndefined below. Enabling it closes a possible bypass of CRS.\nUncomment this rule to change the default:", "select": { "0": "0 (off)", "1": "1 (standard)", "2": "2 (extended)", "3": "3 (excessive)", "4": "4 (banking sector)", "5": "5 (absurd)" } } setvar['tx.executing_paranoia_level'] = { "id": "900001", "name": "tx.executing_paranoia_level", "description": "It is possible to execute rules from a higher paranoia level but not include", "type": "select", "value": "1", "help": "It is possible to execute rules from a higher paranoia level but not include\nthem in the anomaly scoring. This allows you to take a well-tuned system on\nparanoia level 1 and add rules from paranoia level 2 without having to fear\nthe new rules would lead to false positives that raise your score above the\nthreshold.\nThis optional feature is enabled by uncommenting the following rule and\nsetting the tx.executing_paranoia_level.\nTechnically, rules up to the level defined in tx.executing_paranoia_level\nwill be executed, but only the rules up to tx.paranoia_level affect the\nanomaly scores.\nBy default, tx.executing_paranoia_level is set to tx.paranoia_level.\ntx.executing_paranoia_level must not be lower than tx.paranoia_level.\nPlease notice that setting tx.executing_paranoia_level to a higher paranoia\nlevel results in a performance impact that is equally high as setting\ntx.paranoia_level to said level.", "select": { "0": "0 (off)", "1": "1 (standard)", "2": "2 (extended)", "3": "3 (excessive)", "4": "4 (banking sector)", "5": "5 (absurd)" } } setvar['tx.enforce_bodyproc_urlencoded'] = { "id": "900010", "name": "tx.enforce_bodyproc_urlencoded", "description": "ModSecurity selects the body processor based on the Content-Type request", "type": "bool", "value": "1", "help": "ModSecurity selects the body processor based on the Content-Type request\nheader. But clients are not always setting the Content-Type header for their\nrequest body payloads. This will leave ModSecurity with limited vision into\nthe payload. The variable tx.enforce_bodyproc_urlencoded lets you force the\nURLENCODED body processor in these situations. This is off by default, as it\nimplies a change of the behaviour of ModSecurity beyond CRS (the body\nprocessor applies to all rules, not only CRS) and because it may lead to\nfalse positives already on paranoia level 1. However, enabling this variable\ncloses a possible bypass of CRS so it should be considered.\nUncomment this rule to change the default:" } setvar['tx.critical_anomaly_score'] = { "id": "900100", "name": "tx.critical_anomaly_score", "description": "Each rule in the CRS has an associated severity level.", "type": "select", "value": "5", "help": "Each rule in the CRS has an associated severity level.\nThese are the default scoring points for each severity level.\nThese settings will be used to increment the anomaly score if a rule matches.\nYou may adjust these points to your liking, but this is usually not needed.\n- CRITICAL severity: Anomaly Score of 5.\nMostly generated by the application attack rules (93x and 94x files).\n- ERROR severity: Anomaly Score of 4.\nGenerated mostly from outbound leakage rules (95x files).\n- WARNING severity: Anomaly Score of 3.\nGenerated mostly by malicious client rules (91x files).\n- NOTICE severity: Anomaly Score of 2.\nGenerated mostly by the protocol rules (92x files).\nIn anomaly mode, these scores are cumulative.\nSo it's possible for a request to hit multiple rules.\n(Note: In this file, we use 'phase:1' to set CRS configuration variables.\nIn general, 'phase:request' is used. However, we want to make absolutely sure\nthat all configuration variables are set before the CRS rules are processed.)", "select": { "0": "0 (off)", "1": "1 (standard)", "2": "2 (extended)", "3": "3 (excessive)", "4": "4 (banking sector)", "5": "5 (absurd)" } } setvar['tx.error_anomaly_score'] = { "id": "900100", "name": "tx.error_anomaly_score", "description": "Each rule in the CRS has an associated severity level.", "type": "select", "value": "4", "help": "Each rule in the CRS has an associated severity level.\nThese are the default scoring points for each severity level.\nThese settings will be used to increment the anomaly score if a rule matches.\nYou may adjust these points to your liking, but this is usually not needed.\n- CRITICAL severity: Anomaly Score of 5.\nMostly generated by the application attack rules (93x and 94x files).\n- ERROR severity: Anomaly Score of 4.\nGenerated mostly from outbound leakage rules (95x files).\n- WARNING severity: Anomaly Score of 3.\nGenerated mostly by malicious client rules (91x files).\n- NOTICE severity: Anomaly Score of 2.\nGenerated mostly by the protocol rules (92x files).\nIn anomaly mode, these scores are cumulative.\nSo it's possible for a request to hit multiple rules.\n(Note: In this file, we use 'phase:1' to set CRS configuration variables.\nIn general, 'phase:request' is used. However, we want to make absolutely sure\nthat all configuration variables are set before the CRS rules are processed.)", "select": { "0": "0 (off)", "1": "1 (standard)", "2": "2 (extended)", "3": "3 (excessive)", "4": "4 (banking sector)", "5": "5 (absurd)" } } setvar['tx.warning_anomaly_score'] = { "id": "900100", "name": "tx.warning_anomaly_score", "description": "Each rule in the CRS has an associated severity level.", "type": "select", "value": "3", "help": "Each rule in the CRS has an associated severity level.\nThese are the default scoring points for each severity level.\nThese settings will be used to increment the anomaly score if a rule matches.\nYou may adjust these points to your liking, but this is usually not needed.\n- CRITICAL severity: Anomaly Score of 5.\nMostly generated by the application attack rules (93x and 94x files).\n- ERROR severity: Anomaly Score of 4.\nGenerated mostly from outbound leakage rules (95x files).\n- WARNING severity: Anomaly Score of 3.\nGenerated mostly by malicious client rules (91x files).\n- NOTICE severity: Anomaly Score of 2.\nGenerated mostly by the protocol rules (92x files).\nIn anomaly mode, these scores are cumulative.\nSo it's possible for a request to hit multiple rules.\n(Note: In this file, we use 'phase:1' to set CRS configuration variables.\nIn general, 'phase:request' is used. However, we want to make absolutely sure\nthat all configuration variables are set before the CRS rules are processed.)", "select": { "0": "0 (off)", "1": "1 (standard)", "2": "2 (extended)", "3": "3 (excessive)", "4": "4 (banking sector)", "5": "5 (absurd)" } } setvar['tx.notice_anomaly_score'] = { "id": "900100", "name": "tx.notice_anomaly_score", "description": "Each rule in the CRS has an associated severity level.", "type": "select", "value": "2", "help": "Each rule in the CRS has an associated severity level.\nThese are the default scoring points for each severity level.\nThese settings will be used to increment the anomaly score if a rule matches.\nYou may adjust these points to your liking, but this is usually not needed.\n- CRITICAL severity: Anomaly Score of 5.\nMostly generated by the application attack rules (93x and 94x files).\n- ERROR severity: Anomaly Score of 4.\nGenerated mostly from outbound leakage rules (95x files).\n- WARNING severity: Anomaly Score of 3.\nGenerated mostly by malicious client rules (91x files).\n- NOTICE severity: Anomaly Score of 2.\nGenerated mostly by the protocol rules (92x files).\nIn anomaly mode, these scores are cumulative.\nSo it's possible for a request to hit multiple rules.\n(Note: In this file, we use 'phase:1' to set CRS configuration variables.\nIn general, 'phase:request' is used. However, we want to make absolutely sure\nthat all configuration variables are set before the CRS rules are processed.)", "select": { "0": "0 (off)", "1": "1 (standard)", "2": "2 (extended)", "3": "3 (excessive)", "4": "4 (banking sector)", "5": "5 (absurd)" } } setvar['tx.inbound_anomaly_score_threshold'] = { "id": "900110", "name": "tx.inbound_anomaly_score_threshold", "description": "Here, you can specify at which cumulative anomaly score an inbound request,", "type": "select", "value": "5", "help": "Here, you can specify at which cumulative anomaly score an inbound request,\nor outbound response, gets blocked.\nMost detected inbound threats will give a critical score of 5.\nSmaller violations, like violations of protocol/standards, carry lower scores.\n[ At default value ]\nIf you keep the blocking thresholds at the defaults, the CRS will work\nsimilarly to previous CRS versions: a single critical rule match will cause\nthe request to be blocked and logged.\n[ Using higher values ]\nIf you want to make the CRS less sensitive, you can increase the blocking\nthresholds, for instance to 7 (which would require multiple rule matches\nbefore blocking) or 10 (which would require at least two critical alerts - or\na combination of many lesser alerts), or even higher. However, increasing the\nthresholds might cause some attacks to bypass the CRS rules or your policies.\n[ New deployment strategy: Starting high and decreasing ]\nIt is a common practice to start a fresh CRS installation with elevated\nanomaly scoring thresholds (>100) and then lower the limits as your\nconfidence in the setup grows. You may also look into the Sampling\nPercentage section below for a different strategy to ease into a new\nCRS installation.\n[ Anomaly Threshold / Paranoia Level Quadrant ]\nHigh Anomaly Limit | High Anomaly Limit\nLow Paranoia Level | High Paranoia Level\n-> Fresh Site | -> Experimental Site\n------------------------------------------------------\nLow Anomaly Limit | Low Anomaly Limit\nLow Paranoia Level | High Paranoia Level\n-> Standard Site | -> High Security Site\nUncomment this rule to change the defaults:", "select": { "0": "0 (off)", "1": "1 (standard)", "2": "2 (extended)", "3": "3 (excessive)", "4": "4 (banking sector)", "5": "5 (absurd)" } } setvar['tx.outbound_anomaly_score_threshold'] = { "id": "900110", "name": "tx.outbound_anomaly_score_threshold", "description": "Here, you can specify at which cumulative anomaly score an inbound request,", "type": "select", "value": "4", "help": "Here, you can specify at which cumulative anomaly score an inbound request,\nor outbound response, gets blocked.\nMost detected inbound threats will give a critical score of 5.\nSmaller violations, like violations of protocol/standards, carry lower scores.\n[ At default value ]\nIf you keep the blocking thresholds at the defaults, the CRS will work\nsimilarly to previous CRS versions: a single critical rule match will cause\nthe request to be blocked and logged.\n[ Using higher values ]\nIf you want to make the CRS less sensitive, you can increase the blocking\nthresholds, for instance to 7 (which would require multiple rule matches\nbefore blocking) or 10 (which would require at least two critical alerts - or\na combination of many lesser alerts), or even higher. However, increasing the\nthresholds might cause some attacks to bypass the CRS rules or your policies.\n[ New deployment strategy: Starting high and decreasing ]\nIt is a common practice to start a fresh CRS installation with elevated\nanomaly scoring thresholds (>100) and then lower the limits as your\nconfidence in the setup grows. You may also look into the Sampling\nPercentage section below for a different strategy to ease into a new\nCRS installation.\n[ Anomaly Threshold / Paranoia Level Quadrant ]\nHigh Anomaly Limit | High Anomaly Limit\nLow Paranoia Level | High Paranoia Level\n-> Fresh Site | -> Experimental Site\n------------------------------------------------------\nLow Anomaly Limit | Low Anomaly Limit\nLow Paranoia Level | High Paranoia Level\n-> Standard Site | -> High Security Site\nUncomment this rule to change the defaults:", "select": { "0": "0 (off)", "1": "1 (standard)", "2": "2 (extended)", "3": "3 (excessive)", "4": "4 (banking sector)", "5": "5 (absurd)" } } setvar['tx.crs_exclusions_cpanel'] = { "id": "900130", "name": "tx.crs_exclusions_cpanel", "description": "Modify and uncomment this rule to select which application:", "type": "bool", "value": "1", "help": "Modify and uncomment this rule to select which application:" } setvar['tx.crs_exclusions_drupal'] = { "id": "900130", "name": "tx.crs_exclusions_drupal", "description": "Modify and uncomment this rule to select which application:", "type": "bool", "value": "1", "help": "Modify and uncomment this rule to select which application:" } setvar['tx.crs_exclusions_dokuwiki'] = { "id": "900130", "name": "tx.crs_exclusions_dokuwiki", "description": "Modify and uncomment this rule to select which application:", "type": "bool", "value": "1", "help": "Modify and uncomment this rule to select which application:" } setvar['tx.crs_exclusions_nextcloud'] = { "id": "900130", "name": "tx.crs_exclusions_nextcloud", "description": "Modify and uncomment this rule to select which application:", "type": "bool", "value": "1", "help": "Modify and uncomment this rule to select which application:" } setvar['tx.crs_exclusions_wordpress'] = { "id": "900130", "name": "tx.crs_exclusions_wordpress", "description": "Modify and uncomment this rule to select which application:", "type": "bool", "value": "1", "help": "Modify and uncomment this rule to select which application:" } setvar['tx.crs_exclusions_xenforo'] = { "id": "900130", "name": "tx.crs_exclusions_xenforo", "description": "Modify and uncomment this rule to select which application:", |
︙ | ︙ | |||
345 346 347 348 349 350 351 | } setvar['tx.sampling_percentage'] = { "id": "900400", "name": "tx.sampling_percentage", "description": "Adding the Core Rule Set to an existing productive site can lead to false", "type": "str", "value": "100", | | | | | | | | | | | | | | | | 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 | } setvar['tx.sampling_percentage'] = { "id": "900400", "name": "tx.sampling_percentage", "description": "Adding the Core Rule Set to an existing productive site can lead to false", "type": "str", "value": "100", "help": "Adding the Core Rule Set to an existing productive site can lead to false\npositives, unexpected performance issues and other undesired side effects.\nIt can be beneficial to test the water first by enabling the CRS for a\nlimited number of requests only and then, when you have solved the issues (if\nany) and you have confidence in the setup, to raise the ratio of requests\nbeing sent into the ruleset.\nAdjust the percentage of requests that are funnelled into the Core Rules by\nsetting TX.sampling_percentage below. The default is 100, meaning that every\nrequest gets checked by the CRS. The selection of requests, which are going\nto be checked, is based on a pseudo random number generated by ModSecurity.\nIf a request is allowed to pass without being checked by the CRS, there is no\nentry in the audit log (for performance reasons), but an error log entry is\nwritten. If you want to disable the error log entry, then issue the\nfollowing directive somewhere after the inclusion of the CRS\n(E.g., RESPONSE-999-EXCEPTIONS.conf).\nSecRuleUpdateActionById 901150 \"nolog\"\nATTENTION: If this TX.sampling_percentage is below 100, then some of the\nrequests will bypass the Core Rules completely and you lose the ability to\nprotect your service with ModSecurity.\nUncomment this rule to enable this feature:" } setvar['tx.block_search_ip'] = { "id": "900500", "name": "tx.block_search_ip", "description": "Optionally, you can check the client IP address against the Project Honey Pot", "type": "bool", "value": "1", "help": "Optionally, you can check the client IP address against the Project Honey Pot\nHTTPBL (dnsbl.httpbl.org). In order to use this, you need to register to get a\nfree API key. Set it here with SecHttpBlKey.\nProject Honeypot returns multiple different malicious IP types.\nYou may specify which you want to block by enabling or disabling them below.\nRef: https://www.projecthoneypot.org/httpbl.php\nRef: https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual#wiki-SecHttpBlKey\nUncomment these rules to use this feature:\n#SecHttpBlKey XXXXXXXXXXXXXXXXX" } setvar['tx.block_suspicious_ip'] = { "id": "900500", "name": "tx.block_suspicious_ip", "description": "Optionally, you can check the client IP address against the Project Honey Pot", "type": "bool", "value": "1", "help": "Optionally, you can check the client IP address against the Project Honey Pot\nHTTPBL (dnsbl.httpbl.org). In order to use this, you need to register to get a\nfree API key. Set it here with SecHttpBlKey.\nProject Honeypot returns multiple different malicious IP types.\nYou may specify which you want to block by enabling or disabling them below.\nRef: https://www.projecthoneypot.org/httpbl.php\nRef: https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual#wiki-SecHttpBlKey\nUncomment these rules to use this feature:\n#SecHttpBlKey XXXXXXXXXXXXXXXXX" } setvar['tx.block_harvester_ip'] = { "id": "900500", "name": "tx.block_harvester_ip", "description": "Optionally, you can check the client IP address against the Project Honey Pot", "type": "bool", "value": "1", "help": "Optionally, you can check the client IP address against the Project Honey Pot\nHTTPBL (dnsbl.httpbl.org). In order to use this, you need to register to get a\nfree API key. Set it here with SecHttpBlKey.\nProject Honeypot returns multiple different malicious IP types.\nYou may specify which you want to block by enabling or disabling them below.\nRef: https://www.projecthoneypot.org/httpbl.php\nRef: https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual#wiki-SecHttpBlKey\nUncomment these rules to use this feature:\n#SecHttpBlKey XXXXXXXXXXXXXXXXX" } setvar['tx.block_spammer_ip'] = { "id": "900500", "name": "tx.block_spammer_ip", "description": "Optionally, you can check the client IP address against the Project Honey Pot", "type": "bool", "value": "1", "help": "Optionally, you can check the client IP address against the Project Honey Pot\nHTTPBL (dnsbl.httpbl.org). In order to use this, you need to register to get a\nfree API key. Set it here with SecHttpBlKey.\nProject Honeypot returns multiple different malicious IP types.\nYou may specify which you want to block by enabling or disabling them below.\nRef: https://www.projecthoneypot.org/httpbl.php\nRef: https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual#wiki-SecHttpBlKey\nUncomment these rules to use this feature:\n#SecHttpBlKey XXXXXXXXXXXXXXXXX" } setvar['tx.dos_burst_time_slice'] = { "id": "900700", "name": "tx.dos_burst_time_slice", "description": "Optional DoS protection against clients making requests too quickly.", "type": "str", "value": "60", "help": "Optional DoS protection against clients making requests too quickly.\nWhen a client is making more than 100 requests (excluding static files) within\n60 seconds, this is considered a 'burst'. After two bursts, the client is\nblocked for 600 seconds.\nRequests to static files are not counted towards DoS; they are listed in the\n'tx.static_extensions' setting, which you can change in this file (see\nsection \"HTTP Policy Settings\").\nFor a detailed description, see rule file REQUEST-912-DOS-PROTECTION.conf.\nUncomment this rule to use this feature:" } setvar['tx.dos_counter_threshold'] = { "id": "900700", "name": "tx.dos_counter_threshold", "description": "Optional DoS protection against clients making requests too quickly.", "type": "str", "value": "100", "help": "Optional DoS protection against clients making requests too quickly.\nWhen a client is making more than 100 requests (excluding static files) within\n60 seconds, this is considered a 'burst'. After two bursts, the client is\nblocked for 600 seconds.\nRequests to static files are not counted towards DoS; they are listed in the\n'tx.static_extensions' setting, which you can change in this file (see\nsection \"HTTP Policy Settings\").\nFor a detailed description, see rule file REQUEST-912-DOS-PROTECTION.conf.\nUncomment this rule to use this feature:" } setvar['tx.dos_block_timeout'] = { "id": "900700", "name": "tx.dos_block_timeout", "description": "Optional DoS protection against clients making requests too quickly.", "type": "str", "value": "600", "help": "Optional DoS protection against clients making requests too quickly.\nWhen a client is making more than 100 requests (excluding static files) within\n60 seconds, this is considered a 'burst'. After two bursts, the client is\nblocked for 600 seconds.\nRequests to static files are not counted towards DoS; they are listed in the\n'tx.static_extensions' setting, which you can change in this file (see\nsection \"HTTP Policy Settings\").\nFor a detailed description, see rule file REQUEST-912-DOS-PROTECTION.conf.\nUncomment this rule to use this feature:" } setvar['tx.crs_validate_utf8_encoding'] = { "id": "900950", "name": "tx.crs_validate_utf8_encoding", "description": "The CRS can optionally check request contents for invalid UTF-8 encoding.", "type": "bool", "value": "1", "help": "The CRS can optionally check request contents for invalid UTF-8 encoding.\nWe only want to apply this check if UTF-8 encoding is actually used by the\nsite; otherwise it will result in false positives.\nUncomment this rule to use this feature:" } setvar['tx.do_reput_block'] = { "id": "900960", "name": "tx.do_reput_block", "description": "Blocking based on reputation is permanent in the CRS. Unlike other rules,", "type": "bool", "value": "1", "help": "Blocking based on reputation is permanent in the CRS. Unlike other rules,\nwhich look at the indvidual request, the blocking of IPs is based on\na persistent record in the IP collection, which remains active for a\ncertain amount of time.\nThere are two ways an individual client can become flagged for blocking:\n- External information (RBL, GeoIP, etc.)\n- Internal information (Core Rules)\nThe record in the IP collection carries a flag, which tags requests from\nindividual clients with a flag named IP.reput_block_flag.\nBut the flag alone is not enough to have a client blocked. There is also\na global switch named tx.do_reput_block. This is off by default. If you set\nit to 1 (=On), requests from clients with the IP.reput_block_flag will\nbe blocked for a certain duration.\nVariables\nip.reput_block_flag Blocking flag for the IP collection record\nip.reput_block_reason Reason (= rule message) that caused to blocking flag\ntx.do_reput_block Switch deciding if we really block based on flag\ntx.reput_block_duration Setting to define the duration of a block\nIt may be important to know, that all the other core rules are skipped for\nrequests, when it is clear that they carry the blocking flag in question.\nUncomment this rule to use this feature:" } setvar['tx.reput_block_duration'] = { "id": "900970", "name": "tx.reput_block_duration", "description": "Uncomment this rule to change the blocking time:", "type": "str", "value": "300", "help": "Uncomment this rule to change the blocking time:\nDefault: 300 (5 minutes)" } #-- group def mk_groups(): plugins = {} groups = [ ["global", "module", "CoreRuleSet variables", "Update CRS setvars in\n", "^id|^fn|tx\.paranoia|executing|sampling|score_threshold"], ["allow", "allowdeny", "Allowed/Restricted", "White and blacklist some HTTP parameters", "allowed|restricted|urlencoded|static_ext"], ["args", "args", "Arguments", "GET and POST parameter restrictions", "args|arg_|file_size|utf8"], ["excl", "exclusion", "Exclusions", "Some rules to skip (this should have been tags, but here we are)", "exclusions"], ["class", "classification", "Paranoia level classification", "Assign default levels", "anomaly_score(?!_threshold$)"], ["else", "setvar:else", "Other flags", "RBL blocking and DOS protection", "-"] ] """ "name": "tx.block_search_ip", "name": "tx.block_suspicious_ip", "name": "tx.block_harvester_ip", "name": "tx.block_spammer_ip", "name": "tx.dos_burst_time_slice", |
︙ | ︙ | |||
496 497 498 499 500 501 502 | conf[k] = "" prev = copy.copy(conf) # show save = pluginconf.gui.window( conf, plugin_states, files=[], plugins=plugins, title="mod_security option directives", icon=icons.crs, | | | > > > > | | | 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 | conf[k] = "" prev = copy.copy(conf) # show save = pluginconf.gui.window( conf, plugin_states, files=[], plugins=plugins, title="mod_security option directives", icon=icons.crs, opt_label=True, size=(710,770) ) if not save: return # id,fn id = int(conf["id"]) confn = conf["fn"] del conf["id"], conf["fn"] # combine into SecRule act = [] rem_id = [] for k,v in conf.items(): #print(k, " := ", repr(v), type(v), repr(prev.get(k)), type(prev.get(k))) if v in (None, "\n", "", prev.get(k)): continue elif type(v) is bool: v = "1" if v else "0" if re.search("^\\w+$", v): act.append(f"setvar:{k}={v}") else: act.append(f"setvar:'{k}={v.strip()}'") if utils.conf.get("crsopt_undefine") and id < 100000 and setvar.get(k,{}).get("id") and setvar[k]['id'] not in rem_id: act.append(f" ctl:ruleRemoveById={setvar[k]['id']}") rem_id.append(setvar[k]['id']) act = ", \\\n ".join(act) secrule = f"""SecAction "id:{id},pass,nolog,noauditlog,t:none, \\\n {act}"\n""" print(secrule) # prepare update replace_rx = re.compile(f""" # just โ in case user picks a different secrule id ^[\ \t]* SecAction \s+ \"id:({id}|5999|900999),[^"]+\" .*\\n """, re.X|re.M) |
︙ | ︙ |
Changes to modseccfg/recipe.py.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | # api: modseccfg # encoding: utf-8 # version: 0.0 # type: data # title: recipe # description: Apache/mod_security config examples or conversions # category: config # config: # { name: replace_rules, type: bool, value: 0, description: "try to find replacement spot, else just append" } # # Basically just blobs of text and an editor window. # [Save] will append directives to selected vhost/*.conf file. # from modseccfg import utils, vhosts import PySimpleGUI as sg import re from textwrap import dedent | > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | # api: modseccfg # encoding: utf-8 # version: 0.0 # type: data # title: recipe # description: Apache/mod_security config examples or conversions # category: config # config: # { name: replace_rules, type: bool, value: 0, description: "try to find replacement spot, else just append" } # # Basically just blobs of text and an editor window. # [Save] will append directives to selected vhost/*.conf file. # # Some samples from: # ยท https://wiki.atomicorp.com/wiki/index.php/Mod_security # from modseccfg import utils, vhosts import PySimpleGUI as sg import re from textwrap import dedent |
︙ | ︙ | |||
39 40 41 42 43 44 45 46 47 48 49 | SecRuleRemoveById $id #@wrap </FilesMatch> """ exclude_parameter = """ SecRuleUpdateTargetByID $id "!ARGS:param" """ macros = """ <IfModule mod_alias.c> <Macro SecRuleRemoveByPath $id $path> | > > > > > > > > > > > > > > > > | | 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | SecRuleRemoveById $id #@wrap </FilesMatch> """ exclude_parameter = """ SecRuleUpdateTargetByID $id "!ARGS:param" """ rule_to_detectiononly = """ SecRuleUpdateActionById $id "pass,status:200,log,auditlog" """ url_to_detectiononly = """ SecRule REQUEST_URI "$request_uri" "phase:1,id:$new_id,t:none,t:lowercase,pass,msg:'DetectionOnly for $request_uri',ctl:ruleEngine=DetectionOnly" """ exempt_remote_addr = """ SecRule REMOTE_ADDR "^\\Q$remote_addr\\E$" "phase:1,id:$new_id,t:none,nolog,allow,ctl:ruleEngine=Off,ctl:auditEngine=Off" """ whitelist_file = """ SecRule REMOTE_ADDR "@pmFromFile $confn.whitelist" "phase:1,id:$new_id,t:none,nolog,allow" """ macros = """ <IfModule mod_alias.c> <Macro SecRuleRemoveByPath $id $path> SecRule REQUEST_URI "@eq $request_uri" "id:$new_id,t:none,msg:'Whitelist $request_uri',ctl:removeById=$id" </Macro> </IfModule> """ @staticmethod def has(name): return hasattr(recipe, name) |
︙ | ︙ |