├── LICENSE ├── Makefile ├── README ├── _downloads └── IdNumbering.csv ├── _images └── OWASP.png ├── _static └── trustwave-spiderlabs.jpg ├── _templates └── index-template.html ├── anomaly.rst ├── conf.py ├── configuration.rst ├── exceptions.rst ├── index.rst ├── install.rst ├── make.bat ├── making.rst ├── metadata.rst ├── quickstart.rst ├── ruleid.rst ├── rules.rst ├── support.rst └── testing.rst /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | 181 | Copyright 2016 Chaim Sanders 182 | 183 | Licensed under the Apache License, Version 2.0 (the "License"); 184 | you may not use this file except in compliance with the License. 185 | You may obtain a copy of the License at 186 | 187 | http://www.apache.org/licenses/LICENSE-2.0 188 | 189 | Unless required by applicable law or agreed to in writing, software 190 | distributed under the License is distributed on an "AS IS" BASIS, 191 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 192 | See the License for the specific language governing permissions and 193 | limitations under the License. 194 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | BUILDDIR = _build 9 | 10 | # User-friendly check for sphinx-build 11 | ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) 12 | $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don\'t have Sphinx installed, grab it from http://sphinx-doc.org/) 13 | endif 14 | 15 | # Internal variables. 16 | PAPEROPT_a4 = -D latex_paper_size=a4 17 | PAPEROPT_letter = -D latex_paper_size=letter 18 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 19 | # the i18n builder cannot share the environment and doctrees with the others 20 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 21 | 22 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext 23 | 24 | help: 25 | @echo "Please use \`make ' where is one of" 26 | @echo " html to make standalone HTML files" 27 | @echo " dirhtml to make HTML files named index.html in directories" 28 | @echo " singlehtml to make a single large HTML file" 29 | @echo " pickle to make pickle files" 30 | @echo " json to make JSON files" 31 | @echo " htmlhelp to make HTML files and a HTML help project" 32 | @echo " qthelp to make HTML files and a qthelp project" 33 | @echo " applehelp to make an Apple Help Book" 34 | @echo " devhelp to make HTML files and a Devhelp project" 35 | @echo " epub to make an epub" 36 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 37 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 38 | @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" 39 | @echo " text to make text files" 40 | @echo " man to make manual pages" 41 | @echo " texinfo to make Texinfo files" 42 | @echo " info to make Texinfo files and run them through makeinfo" 43 | @echo " gettext to make PO message catalogs" 44 | @echo " changes to make an overview of all changed/added/deprecated items" 45 | @echo " xml to make Docutils-native XML files" 46 | @echo " pseudoxml to make pseudoxml-XML files for display purposes" 47 | @echo " linkcheck to check all external links for integrity" 48 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 49 | @echo " coverage to run coverage check of the documentation (if enabled)" 50 | 51 | clean: 52 | rm -rf $(BUILDDIR)/* 53 | 54 | html: 55 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 56 | @echo 57 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 58 | 59 | dirhtml: 60 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 61 | @echo 62 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 63 | 64 | singlehtml: 65 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 66 | @echo 67 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 68 | 69 | pickle: 70 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 71 | @echo 72 | @echo "Build finished; now you can process the pickle files." 73 | 74 | json: 75 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 76 | @echo 77 | @echo "Build finished; now you can process the JSON files." 78 | 79 | htmlhelp: 80 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 81 | @echo 82 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 83 | ".hhp project file in $(BUILDDIR)/htmlhelp." 84 | 85 | qthelp: 86 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 87 | @echo 88 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 89 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 90 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/OWASPCRSDocumentation.qhcp" 91 | @echo "To view the help file:" 92 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/OWASPCRSDocumentation.qhc" 93 | 94 | applehelp: 95 | $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp 96 | @echo 97 | @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." 98 | @echo "N.B. You won't be able to view it unless you put it in" \ 99 | "~/Library/Documentation/Help or install it in your application" \ 100 | "bundle." 101 | 102 | devhelp: 103 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 104 | @echo 105 | @echo "Build finished." 106 | @echo "To view the help file:" 107 | @echo "# mkdir -p $$HOME/.local/share/devhelp/OWASPCRSDocumentation" 108 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/OWASPCRSDocumentation" 109 | @echo "# devhelp" 110 | 111 | epub: 112 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 113 | @echo 114 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 115 | 116 | latex: 117 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 118 | @echo 119 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 120 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 121 | "(use \`make latexpdf' here to do that automatically)." 122 | 123 | latexpdf: 124 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 125 | @echo "Running LaTeX files through pdflatex..." 126 | $(MAKE) -C $(BUILDDIR)/latex all-pdf 127 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 128 | 129 | latexpdfja: 130 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 131 | @echo "Running LaTeX files through platex and dvipdfmx..." 132 | $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja 133 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 134 | 135 | text: 136 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 137 | @echo 138 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 139 | 140 | man: 141 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 142 | @echo 143 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 144 | 145 | texinfo: 146 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 147 | @echo 148 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." 149 | @echo "Run \`make' in that directory to run these through makeinfo" \ 150 | "(use \`make info' here to do that automatically)." 151 | 152 | info: 153 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 154 | @echo "Running Texinfo files through makeinfo..." 155 | make -C $(BUILDDIR)/texinfo info 156 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." 157 | 158 | gettext: 159 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale 160 | @echo 161 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." 162 | 163 | changes: 164 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 165 | @echo 166 | @echo "The overview file is in $(BUILDDIR)/changes." 167 | 168 | linkcheck: 169 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 170 | @echo 171 | @echo "Link check complete; look for any errors in the above output " \ 172 | "or in $(BUILDDIR)/linkcheck/output.txt." 173 | 174 | doctest: 175 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 176 | @echo "Testing of doctests in the sources finished, look at the " \ 177 | "results in $(BUILDDIR)/doctest/output.txt." 178 | 179 | coverage: 180 | $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage 181 | @echo "Testing of coverage in the sources finished, look at the " \ 182 | "results in $(BUILDDIR)/coverage/python.txt." 183 | 184 | xml: 185 | $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml 186 | @echo 187 | @echo "Build finished. The XML files are in $(BUILDDIR)/xml." 188 | 189 | pseudoxml: 190 | $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml 191 | @echo 192 | @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." 193 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | **** NOTE: The CRS documentation is no longer maintained at this location, please refer to https://coreruleset.org/ instead. *** 2 | 3 | 4 | Welcome to the OWASP Core Rule Set (CRS) documentation. 5 | This documentation is made in Sphinx and can be compiled on Windows using the make.bat or on Linux using the Makefile. 6 | -------------------------------------------------------------------------------- /_downloads/IdNumbering.csv: -------------------------------------------------------------------------------- 1 | 981020,901100 2 | 981021,901110 3 | 981140,910000 4 | 900050,910100 5 | 900051,910110 6 | 900051,910120 7 | 981138,910130 8 | 981141,910140 9 | 981142,910150 10 | 981143,910160 11 | 981144,910170 12 | 981139,910180 13 | 960032,911100 14 | 981044,912000 15 | 981045,912010 16 | 981046,912020 17 | 981047,912030 18 | 981048,912040 19 | 981049,912100 20 | 990002,913100 21 | 990901,913110 22 | 990902,913120 23 | 960911,920100 24 | 981227,920110 25 | 960000,920120 26 | 960912,920130 27 | 960914,920140 28 | 960915,920150 29 | 960016,920160 30 | 960011,920170 31 | 960012,920180 32 | 958230,920190 33 | 958231,920200 34 | 958295,920210 35 | 950107,920220 36 | 950109,920230 37 | 950108,920240 38 | 950801,920250 39 | 950116,920260 40 | 960901,920270 41 | 960008,920280 42 | 960007,920290 43 | 960015,920300 44 | 960021,920310 45 | 960009,920320 46 | 960006,920330 47 | 960904,920340 48 | 960017,920350 49 | 960209,920360 50 | 960208,920370 51 | 960335,920380 52 | 960341,920390 53 | 960342,920400 54 | 960343,920410 55 | 960010,920420 56 | 960034,920430 57 | 960035,920440 58 | 960038,920450 59 | 950012,921100 60 | 950915,921110 61 | 950910,921120 62 | 950911,921130 63 | 950912,921140 64 | 950913,921150 65 | 950914,921160 66 | 950916,921170 67 | 950103,930100 68 | 950104,930110 69 | 950005,930120 70 | 950117,931100 71 | 950118,931110 72 | 950119,931120 73 | 950120,931130 74 | 950907,932100 75 | 958978,933000 76 | 959151,933100 77 | 958977,933110 78 | 958979,933120 79 | 958980,933130 80 | 973344,941000 81 | 973343,941100 82 | 973336,941110 83 | 973337,941120 84 | 973339,941130 85 | 973338,941140 86 | 973350,941150 87 | 973340,941160 88 | 973341,941170 89 | 973342,941180 90 | 973315,941190 91 | 973326,941200 92 | 973346,941210 93 | 973345,941220 94 | 973324,941230 95 | 973323,941240 96 | 973322,941250 97 | 973348,941260 98 | 973321,941270 99 | 973320,941280 100 | 973318,941290 101 | 973317,941300 102 | 973319,941310 103 | 981261,942100 104 | 981318,942110 105 | 981319,942120 106 | 950901,942130 107 | 981320,942140 108 | 950001,942150 109 | 981272,942160 110 | 981250,942170 111 | 981244,942180 112 | 981255,942190 113 | 981257,942200 114 | 981248,942210 115 | 981277,942220 116 | 981241,942230 117 | 981252,942240 118 | 981256,942250 119 | 981245,942260 120 | 981276,942270 121 | 981254,942280 122 | 981270,942290 123 | 981240,942300 124 | 981249,942310 125 | 981253,942320 126 | 981242,942330 127 | 981246,942340 128 | 981251,942350 129 | 981247,942360 130 | 981243,942370 131 | 950009,943100 132 | 950003,943110 133 | 950000,943120 134 | 981175,949100 135 | 981179,949110 136 | 981180,949120 137 | 981181,949130 138 | 981182,949140 139 | 981183,949150 140 | 981184,949160 141 | 981186,949170 142 | 981187,949180 143 | 981176,949190 144 | 970901,950100 145 | 970013,950110 146 | 970017,950120 147 | 970118,950130 148 | 970004,950140 149 | 970904,950150 150 | 970014,950160 151 | 970017,950170 152 | 970009,950180 153 | 970015,950190 154 | 970902,950200 155 | 970003,951100 156 | 9700010,951110 157 | 9700011,951120 158 | 9700012,951130 159 | 9700013,951140 160 | 9700014,951150 161 | 9700015,951160 162 | 9700016,951170 163 | 9700017,951180 164 | 9700018,951190 165 | 9700019,951200 166 | 9700020,951210 167 | 9700021,951220 168 | 9700022,951230 169 | 9700023,951240 170 | 9700024,951250 171 | 9700025,951260 172 | 981200,959100 173 | 981201,980100 174 | 981202,980110 175 | 981203,980120 176 | 981204,980130 177 | 981205,980140 178 | -------------------------------------------------------------------------------- /_images/OWASP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpiderLabs/OWASP-CRS-Documentation/4354d530b61a58fed47ddbb7832eff37f87a1048/_images/OWASP.png -------------------------------------------------------------------------------- /_static/trustwave-spiderlabs.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpiderLabs/OWASP-CRS-Documentation/4354d530b61a58fed47ddbb7832eff37f87a1048/_static/trustwave-spiderlabs.jpg -------------------------------------------------------------------------------- /_templates/index-template.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | Download 4 | 5 | 6 |
7 |
8 |

9 | The OWASP ModSecurity CRS is a set of web application defence rules for the open source, cross-platform ModSecurity Web Application Firewall (WAF). 10 |

11 | 12 |

Get Help

13 |

Get help, learn about new releases, and find out about interesting projects

14 |

Subscribe to our mailing list

15 | 16 |

Quick Links

17 | 23 |
24 | 25 |


-------------------------------------------------------------------------------- /anomaly.rst: -------------------------------------------------------------------------------- 1 | ==================== 2 | Anomaly Scoring Mode 3 | ==================== 4 | 5 | OWASP CRS version 3.x allows users to quickly switch between Traditional and Anomaly Scoring detection modes. The default starting with CRS 3.x is Anomaly Scoring mode. Within the csr-setup.conf.example file there are two settings to control which mode your CRS instance will work in. Within this file, you can also control the following related CRS items: 6 | 7 | * Anomaly Scoring Severity Levels 8 | * Anomaly Scoring Threshold Levels (Blocking) 9 | * Enable/Disable Blocking 10 | * Choose the default logging actions 11 | * and much more! 12 | 13 | 14 | Traditional Detection Mode 15 | ========================== 16 | 17 | Traditional Detection Mode (or IDS/IPS mode) is the old default operating mode. This is the most basic operating mode where all of the rules are “self-contained”. In this mode there is no intelligence is shared between rules and each rule has no information about any previous rule matches. That is to say, in this mode, if a rule triggers, it will execute any disruptive/logging actions specified on the current rule. 18 | 19 | Configuring Traditional Mode 20 | ---------------------------- 21 | 22 | If you want to run the CRS in Traditional mode, you can do this easily by modifying the SecDefaultAction directive in the csr-setup.conf file to use a disruptive action other than the default 'pass', such as deny: 23 | 24 | .. code-block:: bash 25 | 26 | # Default (Anamoly Mode) 27 | SecDefaultAction "phase:2,pass,log" 28 | 29 | .. code-block:: bash 30 | 31 | # Updated To Enable Traditional Mode 32 | SecDefaultAction "phase:2,deny,status:403,log" 33 | 34 | Pros and Cons of Traditional Detection Mode 35 | ------------------------------------------- 36 | 37 | Pros 38 | 39 | * The functionality of this mode is much easier for a new user to understand. 40 | * Better performance (lower latency/resources) as the first disruptive match will stop further processing. 41 | 42 | Cons 43 | 44 | * Not all rules that could have triggered will be logged, only the first 45 | * Not every site has the same risk tolerance 46 | * Lower severity alerts may not trigger traditional mode 47 | * Single low severity alerts may not be deemed critical enough to block, but multiple lower severity alerts in aggregate could be 48 | 49 | Anamoly Scoring Mode 50 | ==================== 51 | 52 | Within anamoly scoring mode we are implementing the concept of Collaborative Detection and Delayed Blocking. This is to say that we have changed the rules logic by decoupling the inspection/detection from the blocking functionality. The individual rules can be run so that the detection remains, however instead of applying any disruptive action at that point, the rules will contribute to a transactional anomaly score collection. In addition, each rule will also store meta-data about each rule match (such as the Rule ID, Attack Category, Matched Location and Matched Data) for later logging. 53 | 54 | Configuring Anomaly Scoring Mode 55 | -------------------------------- 56 | 57 | The default mode in CRS 3.x is Anomaly Scoring mode, you can verify this is your mode by checking that the SecDefaultAction line in the csr-setup.conf file usees the pass action: 58 | 59 | .. code-block:: bash 60 | 61 | SecDefaultAction "phase:2,pass,log" 62 | 63 | In this mode, each matched rule will not block, but rather will increment anomaly scores using ModSecurity's setvar action. Here is an example of an SQL Injection CRS rule that is using setvar actions to increase both the overall anomaly score and the SQL Injection sub-category score: 64 | 65 | .. code-block:: bash 66 | 67 | SecRule ARGS|REQUEST_COOKIES|QUERY_STRING|REQUEST_FILENAME "@detectSQLi" \ 68 | "msg:'SQL Injection Attack Detected via LibInjection',\ 69 | id:942100,\ 70 | rev:'1',\ 71 | ver:'OWASP_CRS/3.0.0',\ 72 | maturity:'1',\ 73 | accuracy:'8',\ 74 | phase:request,\ 75 | block,\ 76 | multiMatch,\ 77 | t:none,t:utf8toUnicode,t:urlDecodeUni,t:removeNulls,t:removeComments,\ 78 | capture,\ 79 | logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ 80 | tag:'application-multi',\ 81 | tag:'language-multi',\ 82 | tag:'platform-multi',\ 83 | tag:'attack-sqli',\ 84 | tag:'OWASP_CRS/WEB_ATTACK/SQL_INJECTION',\ 85 | tag:'WASCTC/WASC-19',\ 86 | tag:'OWASP_TOP_10/A1',\ 87 | tag:'OWASP_AppSensor/CIE1',\ 88 | tag:'PCI/6.5.2',\ 89 | setvar:tx.anomaly_score=+%{tx.critical_anomaly_score},\ 90 | setvar:tx.sql_injection_score=+%{tx.critical_anomaly_score},\ 91 | setvar:'tx.msg=%{rule.msg}',setvar:tx.%{rule.id}-OWASP_CRS/WEB_ATTACK/SQL_INJECTION-%{matched_var_name}=%{matched_var}" 92 | 93 | Anomaly Scoring Severity Levels 94 | ------------------------------- 95 | 96 | Each rule has a severity level specified. We have updated the rules to allow for the anomaly score collection incrementation to use macro expansion. Below is a snippet from the above rule (id:942100) where that occurs: 97 | 98 | .. code-block:: bash 99 | 100 | setvar:tx.anomaly_score=+%{tx.critical_anomaly_score},\ 101 | setvar:tx.sql_injection_score=+%{tx.critical_anomaly_score},\ 102 | 103 | This adds a variable amount, tx.critical_anomaly_score, to the current anomaly scores. The user can configure what each score represents from within the csr-setup.conf file and these scores will be propagated out for use in the rules by using macro expansion. The following is an excerpt from csr-setup.conf where that configuration is set: 104 | 105 | .. code-block:: bash 106 | 107 | 108 | # 109 | # -=[ Anomaly Scoring Severity Levels ]=- 110 | # 111 | # These are the default scoring points for each severity level. You may 112 | # adjust these to you liking. These settings will be used in macro expansion 113 | # in the rules to increment the anomaly scores when rules match. 114 | # 115 | # These are the default Severity ratings (with anomaly scores) of the individual rules - 116 | # 117 | # - 2: Critical - Anomaly Score of 5. 118 | # Is the highest severity level possible without correlation. It is 119 | # normally generated by the web attack rules (40 level files). 120 | # - 3: Error - Anomaly Score of 4. 121 | # Is generated mostly from outbound leakage rules (50 level files). 122 | # - 4: Warning - Anomaly Score of 3. 123 | # Is generated by malicious client rules (35 level files). 124 | # - 5: Notice - Anomaly Score of 2. 125 | # Is generated by the Protocol policy and anomaly files. 126 | # 127 | setvar:tx.critical_anomaly_score=5, \ 128 | setvar:tx.error_anomaly_score=4, \ 129 | setvar:tx.warning_anomaly_score=3, \ 130 | setvar:tx.notice_anomaly_score=2" 131 | 132 | This configuration would mean that every CRS rule that has a Severity rating of "Critical" would increase the transactional anomaly score by 5 points per rule match. When we have a rule match, you can see how the anomaly scoring works from within the modsec_debug.log file: 133 | 134 | .. code-block:: bash 135 | 136 | ... 137 | Setting variable: tx.sql_injection_score=+%{tx.critical_anomaly_score} 138 | Recorded original collection variable: tx.sql_injection_score = "0" 139 | Resolved macro %{tx.critical_anomaly_score} to: 5 140 | Relative change: sql_injection_score=0+5 141 | Set variable "tx.sql_injection_score" to "5". 142 | Setting variable: tx.anomaly_score=+%{tx.critical_anomaly_score} 143 | Recorded original collection variable: tx.anomaly_score = "0" 144 | Resolved macro %{tx.critical_anomaly_score} to: 5 145 | Relative change: anomaly_score=0+5 146 | Set variable "tx.anomaly_score" to "5". 147 | ... 148 | 149 | Now that we have the capability to do anomaly scoring, the next step is to set our thresholds. This is the score value at which, if the current transactional score is above, it will be denied. We have various different anomaly scoring thresholds to set for both specific vulnerability types and generic requests/response levels. These will be evaluated in two different files. Inbound request are evaluated at the end of phase:2 in the rules/REQUEST-49-BLOCKING-EVALUATION.conf file and outbound responses are evaluated at the end of phase:4 in the rules/RESPONSE-59-BLOCKING-EVALUATION.conf file. The thresholds are configured in the csr-setup.conf file. 150 | 151 | 152 | .. code-block:: bash 153 | 154 | SecAction \ 155 | "id:'900003',\ 156 | phase:1,\ 157 | nolog,\ 158 | pass,\ 159 | t:none,\ 160 | setvar:tx.sql_injection_score_threshold=15,\ 161 | setvar:tx.xss_score_threshold=15,\ 162 | setvar:tx.rfi_score_threshold=5,\ 163 | setvar:tx.lfi_score_threshold=5,\ 164 | setvar:tx.rce_score_threshold=5,\ 165 | setvar:tx.command_injection_score_threshold=5,\ 166 | setvar:tx.php_injection_score_threshold=5,\ 167 | setvar:tx.http_violation_score_threshold=5,\ 168 | setvar:tx.trojan_score_threshold=5,\ 169 | setvar:tx.session_fixation_score_threshold=5,\ 170 | setvar:tx.inbound_anomaly_score_threshold=5,\ 171 | setvar:tx.outbound_anomaly_score_threshold=4" 172 | 173 | 174 | With these current default settings, anomaly scoring mode will act similarly to traditional mode from a blocking perspective. Since all critical level rules increase the anomaly score by 5 points, this means that even 1 critical level rule match will cause a block. If you want to adjust the anomaly score so that you have a lower chance of blocking non-malicious clients (false positives) you could raise the tx.inbound_anomaly_score_level settings to something higher like 10 or 15. This would mean that two or more critical severity rules have matched before you decide to block. Another advantage of this approach is that you could aggregate multiple lower severity rule matches and then decide to block. So, one lower severity rule match (such as missing a Request Header such as Accept) would not result in a block but if multiple anomalies are triggered then the request would be blocked. 175 | 176 | Enable/Disable Blocking 177 | ----------------------- 178 | 179 | You are probably familiar with the SecRuleEngine directive which allows you to control blocking mode (On) vs. Detection mode (DetectionOnly). With the Anomaly Scoring mode, if you want to allow blocking, you should set the SecRueEngine to On and then uncomment the following SecAction in the csr-setup.conf file. Note: this is done by default in CRS 3.x: 180 | 181 | 182 | .. code-block:: bash 183 | 184 | SecAction \ 185 | "id:'900004',\ 186 | phase:1,\ 187 | nolog,\ 188 | pass,\ 189 | t:none,\ 190 | setvar:tx.anomaly_score_blocking=on" 191 | 192 | 193 | 194 | When this rule is enabled, The rule within the rules/REQUEST-49-BLOCKING-EVALUATION.conf and rules/RESPONSE-59-BLOCKING-EVALUATION.conf files will evaluate the anomaly scores at the end of the request/response phases and will block the request if it exceeds a given anomaly threshold. An example of such a rule is as follows: 195 | 196 | .. code-block:: bash 197 | 198 | SecRule TX:ANOMALY_SCORE "@ge %{tx.inbound_anomaly_score_threshold}" \ 199 | "msg:'Inbound Anomaly Score Exceeded (Total Score: %{TX.ANOMALY_SCORE}, Last Matched Message: %{tx.msg}',\ 200 | severity:CRITICAL,\ 201 | phase:request,\ 202 | id:949190,\ 203 | t:none,\ 204 | deny,\ 205 | log,\ 206 | tag:'application-multi',\ 207 | tag:'language-multi',\ 208 | tag:'platform-multi',\ 209 | tag:'attack-generic',\ 210 | setvar:tx.inbound_tx_msg=%{tx.msg},\ 211 | setvar:tx.inbound_anomaly_score=%{tx.anomaly_score},\ 212 | chain" 213 | SecRule TX:ANOMALY_SCORE_BLOCKING "@streq on" chain 214 | SecRule TX:/^\d+\-/ "(.*)" 215 | 216 | Notice that there is an explicit deny within this rule. This explitly listed disruptive action will override the default action of pass (within anomaly mode)and block the transaction. If you would like a different action to occur you would set it within the two BLOCKING-EVALUATION files. 217 | 218 | Pros and Cons of Anomaly Scoring Detection Mode 219 | ----------------------------------------------- 220 | 221 | Pros 222 | 223 | * An increased confidence in blocking - since more detection rules contribute to the anomaly score, the higher the score, the more confidence you can have in blocking malicious transactions. 224 | * Allows users to set a threshold that is appropriate for them - different sites may have different thresholds for blocking. 225 | * Allows several low severity events to trigger alerts while individual ones are suppressed. 226 | * One correlated event helps alert management. 227 | * Exceptions may be handled by either increasing the overall anomaly score threshold, or by adding local custom exceptions file 228 | 229 | Cons 230 | 231 | * More complex for the average user. 232 | * Log monitoring scripts may need to be updated for proper analysis 233 | 234 | -------------------------------------------------------------------------------- /conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # OWASP CRS Documentation documentation build configuration file, created by 4 | # sphinx-quickstart on Tue Dec 29 11:08:29 2015. 5 | # 6 | # This file is execfile()d with the current directory set to its 7 | # containing dir. 8 | # 9 | # Note that not all possible configuration values are present in this 10 | # autogenerated file. 11 | # 12 | # All configuration values have a default; values that are commented out 13 | # serve to show the default. 14 | 15 | import sys 16 | import os 17 | 18 | # If extensions (or modules to document with autodoc) are in another directory, 19 | # add these directories to sys.path here. If the directory is relative to the 20 | # documentation root, use os.path.abspath to make it absolute, like shown here. 21 | #sys.path.insert(0, os.path.abspath('.')) 22 | 23 | # -- General configuration ------------------------------------------------ 24 | 25 | # If your documentation needs a minimal Sphinx version, state it here. 26 | #needs_sphinx = '1.0' 27 | 28 | # Add any Sphinx extension module names here, as strings. They can be 29 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 30 | # ones. 31 | extensions = [ 32 | 'sphinx.ext.pngmath', 33 | 'sphinx.ext.ifconfig', 34 | 'sphinx.ext.viewcode', 35 | ] 36 | 37 | # Add any paths that contain templates here, relative to this directory. 38 | templates_path = ['_templates'] 39 | 40 | # The suffix(es) of source filenames. 41 | # You can specify multiple suffix as a list of string: 42 | # source_suffix = ['.rst', '.md'] 43 | source_suffix = '.rst' 44 | 45 | # The encoding of source files. 46 | #source_encoding = 'utf-8-sig' 47 | 48 | # The master toctree document. 49 | master_doc = 'index' 50 | 51 | # General information about the project. 52 | project = u'OWASP CRS Documentation' 53 | copyright = u'2015, OWASP CRS Documentation' 54 | author = u'OWASP CRS Documentation' 55 | 56 | # The version info for the project you're documenting, acts as replacement for 57 | # |version| and |release|, also used in various other places throughout the 58 | # built documents. 59 | # 60 | # The short X.Y version. 61 | version = u'3.0.0-rc1' 62 | # The full version, including alpha/beta/rc tags. 63 | release = u'3.0.0-rc1' 64 | 65 | # The language for content autogenerated by Sphinx. Refer to documentation 66 | # for a list of supported languages. 67 | # 68 | # This is also used if you do content translation via gettext catalogs. 69 | # Usually you set "language" from the command line for these cases. 70 | language = None 71 | 72 | # There are two options for replacing |today|: either, you set today to some 73 | # non-false value, then it is used: 74 | #today = '' 75 | # Else, today_fmt is used as the format for a strftime call. 76 | #today_fmt = '%B %d, %Y' 77 | 78 | # List of patterns, relative to source directory, that match files and 79 | # directories to ignore when looking for source files. 80 | exclude_patterns = ['_build'] 81 | 82 | # The reST default role (used for this markup: `text`) to use for all 83 | # documents. 84 | #default_role = None 85 | 86 | # If true, '()' will be appended to :func: etc. cross-reference text. 87 | #add_function_parentheses = True 88 | 89 | # If true, the current module name will be prepended to all description 90 | # unit titles (such as .. function::). 91 | #add_module_names = True 92 | 93 | # If true, sectionauthor and moduleauthor directives will be shown in the 94 | # output. They are ignored by default. 95 | #show_authors = False 96 | 97 | # The name of the Pygments (syntax highlighting) style to use. 98 | pygments_style = 'sphinx' 99 | 100 | # A list of ignored prefixes for module index sorting. 101 | #modindex_common_prefix = [] 102 | 103 | # If true, keep warnings as "system message" paragraphs in the built documents. 104 | #keep_warnings = False 105 | 106 | # If true, `todo` and `todoList` produce output, else they produce nothing. 107 | todo_include_todos = False 108 | 109 | 110 | # -- Options for HTML output ---------------------------------------------- 111 | 112 | # The theme to use for HTML and HTML Help pages. See the documentation for 113 | # a list of builtin themes. 114 | html_theme = 'alabaster' 115 | 116 | # Theme options are theme-specific and customize the look and feel of a theme 117 | # further. For a list of options available for each theme, see the 118 | # documentation. 119 | #html_theme_options = {} 120 | 121 | # Add any paths that contain custom themes here, relative to this directory. 122 | #html_theme_path = [] 123 | 124 | # The name for this set of Sphinx documents. If None, it defaults to 125 | # " v documentation". 126 | #html_title = None 127 | 128 | # A shorter title for the navigation bar. Default is the same as html_title. 129 | #html_short_title = None 130 | 131 | # The name of an image file (relative to this directory) to place at the top 132 | # of the sidebar. 133 | html_logo = "_images/OWASP.png" 134 | 135 | # The name of an image file (within the static path) to use as favicon of the 136 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 137 | # pixels large. 138 | #html_favicon = None 139 | 140 | # Add any paths that contain custom static files (such as style sheets) here, 141 | # relative to this directory. They are copied after the builtin static files, 142 | # so a file named "default.css" will overwrite the builtin "default.css". 143 | html_static_path = ['_static'] 144 | 145 | # Add any extra paths that contain custom files (such as robots.txt or 146 | # .htaccess) here, relative to this directory. These files are copied 147 | # directly to the root of the documentation. 148 | #html_extra_path = [] 149 | 150 | # If not None, a 'Last updated on:' timestamp is inserted at every page 151 | # bottom, using the given strftime format. 152 | # The empty string is equivalent to '%b %d, %Y'. 153 | #html_last_updated_fmt = None 154 | 155 | # If true, SmartyPants will be used to convert quotes and dashes to 156 | # typographically correct entities. 157 | #html_use_smartypants = True 158 | 159 | # Custom sidebar templates, maps document names to template names. 160 | #html_sidebars = {} 161 | html_sidebars = {'*': ['index-template.html','searchbox.html']} 162 | 163 | # Additional templates that should be rendered to pages, maps page names to 164 | # template names. 165 | #html_additional_pages = {} 166 | 167 | # If false, no module index is generated. 168 | #html_domain_indices = True 169 | 170 | # If false, no index is generated. 171 | #html_use_index = True 172 | 173 | # If true, the index is split into individual pages for each letter. 174 | #html_split_index = False 175 | 176 | # If true, links to the reST sources are added to the pages. 177 | html_show_sourcelink = False 178 | 179 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. 180 | #html_show_sphinx = True 181 | 182 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. 183 | #html_show_copyright = True 184 | 185 | # If true, an OpenSearch description file will be output, and all pages will 186 | # contain a tag referring to it. The value of this option must be the 187 | # base URL from which the finished HTML is served. 188 | #html_use_opensearch = '' 189 | 190 | # This is the file name suffix for HTML files (e.g. ".xhtml"). 191 | #html_file_suffix = None 192 | 193 | # Language to be used for generating the HTML full-text search index. 194 | # Sphinx supports the following languages: 195 | # 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' 196 | # 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr' 197 | #html_search_language = 'en' 198 | 199 | # A dictionary with options for the search language support, empty by default. 200 | # Now only 'ja' uses this config value 201 | #html_search_options = {'type': 'default'} 202 | 203 | # The name of a javascript file (relative to the configuration directory) that 204 | # implements a search results scorer. If empty, the default will be used. 205 | #html_search_scorer = 'scorer.js' 206 | 207 | # Output file base name for HTML help builder. 208 | htmlhelp_basename = 'OWASPCRSDocumentationdoc' 209 | 210 | # -- Options for LaTeX output --------------------------------------------- 211 | 212 | latex_elements = { 213 | # The paper size ('letterpaper' or 'a4paper'). 214 | #'papersize': 'letterpaper', 215 | 216 | # The font size ('10pt', '11pt' or '12pt'). 217 | #'pointsize': '10pt', 218 | 219 | # Additional stuff for the LaTeX preamble. 220 | #'preamble': '', 221 | 222 | # Latex figure (float) alignment 223 | #'figure_align': 'htbp', 224 | } 225 | 226 | # Grouping the document tree into LaTeX files. List of tuples 227 | # (source start file, target name, title, 228 | # author, documentclass [howto, manual, or own class]). 229 | latex_documents = [ 230 | (master_doc, 'OWASPCRSDocumentation.tex', u'OWASP CRS Documentation Documentation', 231 | u'OWASP CRS Documentation', 'manual'), 232 | ] 233 | 234 | # The name of an image file (relative to this directory) to place at the top of 235 | # the title page. 236 | #latex_logo = None 237 | 238 | # For "manual" documents, if this is true, then toplevel headings are parts, 239 | # not chapters. 240 | #latex_use_parts = False 241 | 242 | # If true, show page references after internal links. 243 | #latex_show_pagerefs = False 244 | 245 | # If true, show URL addresses after external links. 246 | #latex_show_urls = False 247 | 248 | # Documents to append as an appendix to all manuals. 249 | #latex_appendices = [] 250 | 251 | # If false, no module index is generated. 252 | #latex_domain_indices = True 253 | 254 | 255 | # -- Options for manual page output --------------------------------------- 256 | 257 | # One entry per manual page. List of tuples 258 | # (source start file, name, description, authors, manual section). 259 | man_pages = [ 260 | (master_doc, 'owaspcrsdocumentation', u'OWASP CRS Documentation Documentation', 261 | [author], 1) 262 | ] 263 | 264 | # If true, show URL addresses after external links. 265 | #man_show_urls = False 266 | 267 | 268 | # -- Options for Texinfo output ------------------------------------------- 269 | 270 | # Grouping the document tree into Texinfo files. List of tuples 271 | # (source start file, target name, title, author, 272 | # dir menu entry, description, category) 273 | texinfo_documents = [ 274 | (master_doc, 'OWASPCRSDocumentation', u'OWASP CRS Documentation Documentation', 275 | author, 'OWASPCRSDocumentation', 'One line description of project.', 276 | 'Miscellaneous'), 277 | ] 278 | 279 | # Documents to append as an appendix to all manuals. 280 | #texinfo_appendices = [] 281 | 282 | # If false, no module index is generated. 283 | #texinfo_domain_indices = True 284 | 285 | # How to display URL addresses: 'footnote', 'no', or 'inline'. 286 | #texinfo_show_urls = 'footnote' 287 | 288 | # If true, do not generate a @detailmenu in the "Top" node's menu. 289 | #texinfo_no_detailmenu = False 290 | -------------------------------------------------------------------------------- /configuration.rst: -------------------------------------------------------------------------------- 1 | ===================== 2 | Configuring OWASP CRS 3 | ===================== 4 | -------------------------------------------------------------------------------- /exceptions.rst: -------------------------------------------------------------------------------- 1 | ================================ 2 | Adding Exceptions and Tuning CRS 3 | ================================ 4 | 5 | Modifying Rules 6 | =============== 7 | 8 | OWASP Core Rule Set (CRS) as a rule set for ModSecurity has no context into what your web application is doing and how it is designed. As a result, often legitimate requests might seem to CRS to be attacks. This term is often called a **False Positive**. While the CRS team does its best to prevent these from happening, they are somewhat inevitable due to the blacklist nature of the rules. A quick example might illustrate the problem better. 9 | 10 | Imagine you are running the popular Wordpress CMS engine. As part of this engine the capability exists to add both HTML (and JavaScript if you're an administrator) to your blog posts. Now Wordpress has rules around which tags can be used and their whitelist of tags has generally been studied pretty heavily by the security community. However, ModSecurity will only has visibility akin to www.mywordpressblog.com?wp_post=

Welcome+To+My+Blog

. In this instance OWASP CRS sees HTML Injection, because that is what's there. ModSecurity will have no knowledge that this problem is mitigated server side and as a result may block the request. It is therefore necessary sometimes to add an exception. 11 | 12 | The most common issues when adding exceptions to OWASP CRS is that if done 'inline' it will be clobbered by the next update. The ModSecurity team has developed sophisticated methods for dealing with this problem that are quite versatile. 13 | 14 | Exceptions versus Whitelist 15 | --------------------------- 16 | There are two generally different methods for modifying rules. Exceptions, which will remove or modify the rule from startup time and whitelist modifications which can modify a rule based on the content of a transaction. In general whitelist rules are slightly more powerful but also more expensive as they must be evaluated every time a transaction comes in. 17 | 18 | Within CRS 3.x two files are provided to help you add these different rule modifications, they are: rules/REQUEST-00-LOCAL-WHITELIST.conf.example and rules/RESPONSE-99-EXCEPTIONS.conf.example. As is noted in the :doc:`install` documentation, the .example extension is provided specifically so that when these files are renamed, future updates will not overwrite these files. As is listed within the :doc:`install` documentation, before adding a whitelist or exception modification you should rename these files to end in the .conf exception. 19 | 20 | The naming of these files is also not an accident. Due to the transactional nature of the whitelist modifications, they need to take place BEFORE the rules they are affecting, since they are processed on every transaction. Conversely, the exceptions file contains directives that are evaluated on startup. As a result, these need to be some of the last rules included in your configuration such that data structures that store the rules are populated and it can modify them. 21 | 22 | Writing Exceptions 23 | ------------------ 24 | 25 | Exceptions come in a few different forms which are all outlined in detail within the `Reference Manual `_. The following directives can be used to modify a rule at startup without touching the actual rule: 26 | 27 | * `SecRuleRemoveById `_ 28 | * `SecRuleRemoveByMsg `_ 29 | * `SecRuleRemoveByTag `_ 30 | * `SecRuleUpdateActionById `_ 31 | * `SecRuleUpdateTargetById `_ 32 | * `SecRuleUpdateTargetByMsg `_ 33 | * `SecRuleUpdateTargetByTag `_ 34 | 35 | You'll notice that there are two types of exceptions, those that remove, and those that change (or update) rules. General usage of the SecRuleRemove* rules is fairly straight forward: 36 | 37 | .. code-block:: bash 38 | 39 | SecRule ARGS "@detectXSS" "id:123,deny,status:403" 40 | SecRuleRemoveById SecRuleRemoveByID 123 41 | 42 | The above rule will remove rule 123. When ModSecurity starts up it will add rule 123 into its internal data structures and when it processes SecRuleRemoveById it will then remove it from it's internal data structures. The rule will not be processed for any transaction as by the time ModSecurity reaches the point where it's processing requests, the rule simply no longer exists. 43 | 44 | The SecRuleUpdate* modifications are a bit more complicated. They have the capability to update a target or action based on some identifier. The update target rule is perhaps the simpler of the two to use. Modifying Targets (Variables) is easy, you can either append or replace. To append you simply only list one argument after SecRuleUpdateTargetBy*. This is great for adding exceptions as you can restrict a certain index of a collection from being inspected 45 | 46 | .. code-block:: bash 47 | 48 | SecRule ARGS "@detectXSS" "id:123,deny,status:403" 49 | SecRuleUpdateTargetById 123 !ARGS:wp_post 50 | 51 | It is also possible to replace a target (variable). To do this you must first list the variable you want to replace with, followed by the variable you want to replace. So in the below example we replace the ARGS variable with ARGS_POST. 52 | 53 | .. code-block:: bash 54 | 55 | SecRule ARGS "@detectXSS" "id:123,deny,status:403" 56 | SecRuleUpdateTargetById 123 ARGS_POST ARGS 57 | 58 | 59 | Updating an action becomes a little more tricky as there are default actions and actions types of which only one can exist per rule. In general, transformations and actions that are not already included will be appended. There is one big exception to this rule and that is disruptive actions (pass, deny, etc) will always replace each other, there may only ever be one disruptive action. Additionally, certain logging actions will replace each other, for instance nolog would overwrite the log action. This functionality has the same rules as using `SecDefaultAction `_. 60 | 61 | .. code-block:: bash 62 | 63 | SecRule "@detectXSS" attack "phase:2,id:12345,t:lowercase,log,pass,msg:'Message text'" 64 | SecRuleUpdateActionById 12345 "t:none,t:compressWhitespace,deny,status:403,msg:'New message text'" 65 | 66 | # Results in the following rule 67 | SecRule ARGS "@detectXSS "phase:2,id:12345,t:lowercase,t:none,t:compressWhitespace,log,deny,status:403,msg:'New Message text'" 68 | 69 | In general updating a rule to remove just the false positive is preferred over removing the entire rule. It should be noted that both actions should be taken with care as they do open a potential security hole. Before you add an exception within any rules you should make sure that the area where you are adding the exception is indeed a false positive and not vulnerable to the issue. 70 | 71 | You may notice that it is not possible to change the operator of the rule via these exception Directives. To change the functionality of a rule you must use whitelist modifications OR remove the rule and add a new one. 72 | 73 | Writing Whitelist Modifications 74 | ------------------------------- 75 | 76 | Whitelisting is more complicated than exceptions because the rules can be more varied. In some ways they are less powerful than exceptions, but in others they are far more powerful. Whitelist rules use the `ctl `_ action to change the state of the engine on a per transaction basis. This can be as simple as turning off the ruleEngine when a certain IP hits. Note, the ruleEngine will return to state from the configuration file for the next transaction. 77 | 78 | .. code-block:: bash 79 | 80 | SecRule REMOTE_ADDR "@IPMatch 1.2.3.4" "id:1,ctl:ruleEngine=Off" 81 | 82 | You can also use this rule to avoid certain rules in some cases, this effectively allows you to modify operators. In the following example we have a rule that will block the entire 129.21.x.x subnet (class B). We add a ctl modification before hand such that if we get a particular IP address in that range we remove the rule, effectively adding an exception 83 | 84 | .. code-block:: bash 85 | 86 | SecRule REMOTE_ADDR "@IPMatch 129.21.3.17" "id:3,ctl:ruleRemoveById=4" 87 | SecRule REMOTE_ADDR "@IPMatch 129.21.0.0/24" "id:4,deny,status:403" 88 | 89 | The `ctl `_ action can also change the configuration of certain directives which can lead to more efficient rules. It is recommended that you investigate its full potential. 90 | 91 | 92 | Tuning CRS 93 | ========== 94 | 95 | CRS 3.x is designed to make it easy to remove rules that are not relevant to your configuration. Not only are Rules organized into files that are titled with general categories but we have also renumbered according to a scheme such that rule IDs can be used to quickly remove entire unwanted configurations files by using `SecRuleRemoveById `_. The following example removes all XSS rules which are located in the REQUEST-41-APPLICATION-ATTACK-XSS.conf file. Notice that all OWASP CRS rules are prefixed with '9' and then the next two digits represent the rules file. 96 | 97 | .. code-block:: bash 98 | 99 | SecRuleRemoveById "941000-941999" 100 | 101 | The CRS rules also features tags to identify what their functionality is. It is therefore easy to remove an entire category that doesn't apply to your environment. In the following example we remove all IIS rules using `SecRuleRemoveByTag `_. 102 | 103 | .. code-block:: bash 104 | 105 | SecRuleRemoveByTag "platform-iis" 106 | 107 | -------------------------------------------------------------------------------- /index.rst: -------------------------------------------------------------------------------- 1 | OWASP Core Rule Set: Documentation 2 | =================================================== 3 | 4 | Deployment: 5 | 6 | .. toctree:: 7 | :maxdepth: 1 8 | 9 | quickstart 10 | install 11 | configuration 12 | rules 13 | exceptions 14 | testing 15 | anomaly 16 | support 17 | making 18 | metadata 19 | 20 | 21 | Development: 22 | 23 | .. toctree:: 24 | :maxdepth: 1 25 | 26 | ruleid 27 | 28 | 29 | Overview 30 | ======== 31 | The OWASP (Open Web Application Security Project) CRS (Core Rule Set) for ModSecurity™ is an open source collection of rules that work with the ModSecurity™ WAF (Web Application Firewall). These rules were designed to provide, easy to use, generic attack detection capabilities to your web application as part of a well balanced defence-in-depth solution. 32 | 33 | Licensing 34 | ========= 35 | OWASP ModSecurity CRS is free to use. It is licensed under the Apache Software License version 2 (ASLv2), so you can copy, distribute and transmit the work, and you can adapt it, and use it commercially, but all provided that you attribute the work and if you alter, transform, or build upon this work, you may distribute the resulting work only under the same or similar license to this one. 36 | -------------------------------------------------------------------------------- /install.rst: -------------------------------------------------------------------------------- 1 | ===================== 2 | Installing OWASP CRS 3 | ===================== 4 | 5 | We are glad you chose OWASP CRS the premier free ModSecurity ruleset. Below you should find all the information you need to properly install CRS. If you are having problems feel free to reach out to our mailing list. You can signup at: https://lists.owasp.org/mailman/listinfo/owasp-modsecurity-core-rule-set 6 | 7 | Prerequisites 8 | ============= 9 | 10 | Installing the CRS isn't very hard but it does have one major requirement, ModSecurity. If ModSecurity isn't working properly you will likely run into problems running the CRS. In order to run the 3.x branch you require AT MINIMUM ModSecurity 2.8 or above, preferably version 3.x or above. 11 | 12 | Finding where to edit in your configuration 13 | =========================================== 14 | 15 | ModSecurity comes in MANY different version with support for a multitude of Operating Systems (OS) and Web Servers. The installation locations may differ greatly between these different options so please be aware that the following are just some of the more common configurations. 16 | 17 | Microsoft IIS with ModSecurity 2.x 18 | ---------------------------------- 19 | 20 | The most common deployment of ModSecurity for IIS is via the pre-packaged MSI installer, available at https://www.modsecurity.org/download.html. If you compiled or are looking to compile ModSecurity for IIS this documentation isn't for you. If you used this package to install ModSecurity 2.x on IIS (tested on IIS 7-10), than your configuration files are located within C:\\Program Files\\ModSecurity IIS\\ (or Program Files(x86) depending on your configuration). The inital configuration file, that is the one that the remainder are included from, is modsecurity_iis.conf. This file will be parsed by the ModSecurity for both ModSecurity and 'Include' directives. 21 | 22 | By default all installations of ModSecurity without `SecRuleEngine `_ declared will start in DetectionOnly mode. IIS, by default, explitcly declares `SecRuleEngine `_ to be DetectionOnly within the included modsecurity.conf file. As a result any rule we make will only show up in the Windows Event Viewer by default. For our example we're going to turn on disruptive actions. To test we should add the following to the end of our modsecurity_iis.conf: 23 | 24 | .. code-block:: bash 25 | 26 | SecRuleEngine On 27 | SecRule ARGS:testparam "@contains test" "id:1234,deny,status:403,msg:'Our test rule has triggered'" 28 | 29 | This rule will be triggered when you go to your web page and pass the testparam (via either GET or POST) with the test value. This typically will looks similar to the following: http://localhost/?testparam=test. If all went well you should see an HTTP 403 Forbidden in your browser when you navigate to the site in question. Additionally, in your Event Viewer, under 'Windows Logs'->'Application', we should see a new log that looks like the following: 30 | 31 | 32 | 33 | If you have gotten to this step ModSecurity is functioning on IIS and you now know where to place new directives. 34 | 35 | Apache 2.x with ModSecurity 2.x Compiled 36 | ---------------------------------------- 37 | Compiling ModSecurity is easy, but slightly outside the scope of this document. If you are interested in learning how to compile ModSecurity please go to the ModSecurity documentation. Having compiled ModSecurity there is a simple test to see if your installation is working. If you have compiled from source you would have needed to include 'LoadModule security2_module modules/mod_security2.so' either in httpd.conf (apache2.conf on Debian) or in some file included from this file. Anywhere after you load your module you may add the following ModSecurity directives. 38 | 39 | .. code-block:: bash 40 | 41 | SecRuleEngine On 42 | SecRule ARGS:testparam "@contains test" "id:1234,deny,status:403,msg:'Our test rule has triggered'" 43 | 44 | If you restart Apache you may now navigate to any page on your web server passing the parameter 'testparam' with the value 'test' (via post or get) and you should receive a 403. This request will typically appear similar to as follows: http://localhost/?testparam=test. 45 | 46 | If you obtained a 403 status code your ModSecurity instance is functioning correctly with Apache and you now know where to place directives. 47 | 48 | 49 | Apache 2.x with ModSecurity 2.x Packaged (RHEL) 50 | ----------------------------------------------- 51 | 52 | Many operating systems provide package managers in order to aid in the install of software packages and their associated dependencies. Even though ModSecurity is relatively straight forward to install, some people prefer using package managers due to their ease. It should be noted here that many package managers do not up date their releases very frequently, as a result it is quite likely that your distribution may be missing required features or possibly even have security vulnerabilities. Additionally, depending on your package/package manager your ModSecurity configuration will be laid out slightly different. 53 | 54 | On Fedora we will find that when you use 'dnf install mod_security' you will receive the base ModSecurity package. Apache's configuration files are split out within this environment such that there are different folders for the base config (etc/httpd/config/), user configuration (etc/httpd/conf.d/, and module configuration (/etc/httpd/conf.modules.d/). The Fedora ModSecurity 2.x package places the LoadModule and associated 'Include's within /etc/httpd/conf.modules.d/10-mod_security.conf. Additionally, it places some of the reccomended default rules in /etc/httpd/conf.d/mod_security.conf. It is this secondary configuration file that will setup the locations where you should add your rules. By default it reads in all config files from the /etc/httpd/modsecurity.d/ and /etc/httpd/modsecurity.d/activated_rules/ folder. To keep order I would reccomend testing this configuration by placing a rules.conf file within the activiated_rules folder. Within this rules.conf file add the following: 55 | 56 | .. code-block:: bash 57 | 58 | SecRuleEngine On 59 | SecRule ARGS:testparam "@contains test" "id:1234,deny,status:403,msg:'Our test rule has triggered'" 60 | 61 | Upon saving and restarting Apache (systemctl restart httpd.service) you should be able to navigate to a your local webserver. Once this is accomplished try passing the 'testparam' paramater with the value 'test' such as via the following URL:http://localhost/?testparam=test. You should receive a 403 Forbidden status. If you do congratulations, ModSecurity is ready for the OWASP CRS rules. 62 | 63 | Nginx with ModSecurity 2.x Compiled 64 | ----------------------------------- 65 | ModSecurity 2.x currently doesn't support the new Nginx loadable modules. As a result, it is required that you compile Nginx from source with ModSecurity. For more information on how to do this see the ModSecurity documentaiton. Once ModSecurity is compiled in you will have to specify both 'ModSecurityEnabled' and 'ModSecurityConfig' within any location block where you want ModSecurity enabled. An example would look similar to below. 66 | 67 | .. code-block:: bash 68 | 69 | location / { 70 | ModSecurityEnabled on; 71 | ModSecurityConfig modsec_includes.conf; 72 | } 73 | 74 | Within this modsec_includes you may use the Include directive to include other files or any ModSecurity directives. For our testing purpose we will add the following to our modsec_includes.conf: 75 | 76 | .. code-block:: bash 77 | 78 | SecRuleEngine On 79 | SecRule ARGS:testparam "@contains test" "id:1234,deny,status:403,msg:'Our test rule has triggered'" 80 | 81 | Upon saving and restarting Nginx (./nginx -s reload) you should be able to navigate to a your local webserver. Once this is accomplished try passing the 'testparam' paramater with the value 'test' such as via the following URL:http://localhost/?testparam=test. You should receive a 403 Forbidden status. If you do congratulations, ModSecurity is ready for the OWASP CRS rules. 82 | 83 | 84 | Nginx with ModSecurity 3.x (libmodsecurity) Compiled 85 | ---------------------------------------------------- 86 | At current time of writing ModSecurity v3 is still in development. Please stay tuned for more information or visit the ModSecurity v3 repository at https://github.com/SpiderLabs/ModSecurity/tree/libmodsecurity 87 | 88 | Downloading OWASP CRS 89 | ===================== 90 | 91 | Now that you know where your rules belong typically we'll want to download the OWASP CRS. The best place to get the latest copy of the ruleset will be from our Github: https://github.com/SpiderLabs/owasp-modsecurity-crs. Be careful to determine if there are any more relevant branches in development that can take advantage of the version of ModSecurity you are using. You can do this by checking the different branches on the site and looking throughout this documentation. To download a repository you can either click the '`Download Zip `_' button or your can use git clone. For instance, 92 | 93 | .. code-block:: bash 94 | 95 | git clone https://github.com/SpiderLabs/owasp-modsecurity-crs 96 | 97 | Typically you'll end up with a folder named something similar to 'owasp-modsecurity-crs'. From here the process is surprisingly simple. Because OWASP CRS is, at its core, a set of ModSecurity configuration files (\*.conf files) all you have to do is tell ModSecurity where these CRS configuration files reside and it will do MOST of the remaining work. To do this you must use the 'Include' directive. This include directive can be used in similar places to where we used our SecRule earlier. It should be noted that OWASP CRS should be included AFTER the ModSecurity configuration rules which are available via the ModSecurity repo (at https://github.com/SpiderLabs/ModSecurity/blob/master/modsecurity.conf-recommended) which should have been configured during your inital installation. These rules will configure ModSecurity options, such as SecRuleEngine that we used earlier. This configuration file should be reveiwed and modified as desired. 98 | 99 | Setup OWASP CRS 100 | ===================== 101 | OWASP CRS contains one setup file that should be reviewed prior to completing setup. The setup file is the only configuration file within the root 'owasp-crs-modsecurity' folder and is named csr-setup.conf.example. Going through the configuration file (csr-setup.conf.example) and reading what the different options are is HIGHLY recommended. At minimum you should keep in mind the following. 102 | 103 | * CRS does not configure ModSecurity features such as the rule engine, the audit engine, logging etc. This task is part of the ModSecurity initial setup.If you haven't done this yet please check out the recommended ModSecurity configuration at https://github.com/SpiderLabs/ModSecurity/blob/master/modsecurity.conf-recommended 104 | * By default (`SecDefaultAction `_) CRS will redirect to your local domain when an alert is triggered. This may cause redirect loops depending on your configuration. Take some time to decide what you want ModSecurity it do (drop the packet, return a status:403, go to a custom page etc.) when it detects malicious activity. 105 | * Make sure to configure your anomaly scoring thresholds for more information see :doc:`anomaly` 106 | * By default ModSecurity looks for lots of issues with different databases and languages, if you are running a specific environment, you probably want to limit this behaviour for performance reasons. 107 | * ModSecurity supports Project Honeypot (http://www.projecthoneypot.org/index.php) blacklists. This is a great project and all you need to do to leverage it is sign up for an API key (http://www.projecthoneypot.org/httpbl_api.php) 108 | * Do make sure you have added any methods, static resources, content types, or file extensions that your site needs beyond the basic ones listed. 109 | 110 | For more information please see the page on :doc:`configuration`. Once you have reviewed and configured CRS you should rename the file suffix from .example to .conf 111 | 112 | .. code-block:: bash 113 | 114 | mv csr-setup.conf.example csr-setup.conf 115 | 116 | In addition to csr-setup.conf.example there are two other .example files within our repository. These files are: rules/REQUEST-00-LOCAL-WHITELIST.conf.example and rules/RESPONSE-99-EXCEPTIONS.conf.example. These files are designed to provide the rule maintainer the capability to modify rules (see :doc:`exceptions`) without breaking forward compatability with updates. As such you should rename these two files, removing the .example suffix. This will make it so that even when updates are installed they do not overwrite your custom updates. To rename the files in Linux one would use a command similar to the following: 117 | 118 | .. code-block:: bash 119 | 120 | mv rules/REQUEST-00-LOCAL-WHITELIST.conf.example rules/REQUEST-00-LOCAL-WHITELIST.conf 121 | mv rules/RESPONSE-99-EXCEPTIONS.conf.example rules/RESPONSE-99-EXCEPTIONS.conf 122 | 123 | 124 | 125 | Proceeding with the Install 126 | =========================== 127 | Both ModSecurity 2.x (via APR) and ModSecurity 3.x support the Include directive and what it tells the ModSecurity core to do is parse the additional files for ModSecurity directives. But where do you place this folder for it to be included? 128 | If you were to look at the CRS files, you'd note there are quite a few .conf files. While the names attempt to do a good job at describing what each file does additional information is available in the :doc:`rules` section. 129 | 130 | Includes for Apache 131 | ------------------- 132 | Apache will include from the Apache Root directory (/etc/httpd/, /etc/apache2/, or /usr/local/apache2/ depending on the envirovment). Typically we reccomend following the Fedora practice of creating a folder specificlly for ModSecurity rules. In our example we have named this modsecurity.d and placed in within the root Apache directory. When using Apache we can use the wildcard notation to vastly simplify our rules. Simply copying our cloned directory to our modsecurity.d folder and specifying the appropertie include directives will allow us to install OWASP CRS. In the example below we have also included our modsecurity.conf file which includes reccomended configurations for ModSecurity 133 | 134 | .. code-block:: bash 135 | 136 | 137 | Include modsecurity.d/modsecurity.conf 138 | Include modsecurity.d/owasp-modsecurity-crs/csr-setup.conf 139 | Include modsecurity.d/owsp-modsecurity-crs/rules/*.conf 140 | 141 | 142 | Includes for Nginx 143 | ------------------- 144 | Nginx will include from the Nginx conf directory (/usr/local/nginx/conf/ depending on the envirovment). Because only one 'ModSecurityConfig' directive can be specified within nginx.conf we reccomend naming that file modsec_includes.conf and including additional files from there. In the example below we copied our cloned owasp-modsecurity-crs folder into our Nginx configuration directory. From there we specifying the appropertie include directives which will include OWASP CRS when the server is restarted. In the example below we have also included our modsecurity.conf file which includes reccomended configurations for ModSecurity 145 | 146 | .. code-block:: bash 147 | 148 | include modsecurity.conf 149 | include owasp-modsecurity-crs/csr-setup.conf 150 | include owasp-modsecurity-crs/rules/REQUEST-00-LOCAL-WHITELIST.conf 151 | include owasp-modsecurity-crs/rules/REQUEST-01-COMMON-EXCEPTIONS.conf 152 | include owasp-modsecurity-crs/rules/REQUEST-10-IP-REPUTATION.conf 153 | include owasp-modsecurity-crs/rules/REQUEST-11-METHOD-ENFORCEMENT.conf 154 | include owasp-modsecurity-crs/rules/REQUEST-12-DOS-PROTECTION.conf 155 | include owasp-modsecurity-crs/rules/REQUEST-13-SCANNER-DETECTION.conf 156 | include owasp-modsecurity-crs/rules/REQUEST-20-PROTOCOL-ENFORCEMENT.conf 157 | include owasp-modsecurity-crs/rules/REQUEST-21-PROTOCOL-ATTACK.conf 158 | include owasp-modsecurity-crs/rules/REQUEST-30-APPLICATION-ATTACK-LFI.conf 159 | include owasp-modsecurity-crs/rules/REQUEST-31-APPLICATION-ATTACK-RFI.conf 160 | include owasp-modsecurity-crs/rules/REQUEST-32-APPLICATION-ATTACK-RCE.conf 161 | include owasp-modsecurity-crs/rules/REQUEST-33-APPLICATION-ATTACK-PHP.conf 162 | include owasp-modsecurity-crs/rules/REQUEST-41-APPLICATION-ATTACK-XSS.conf 163 | include owasp-modsecurity-crs/rules/REQUEST-42-APPLICATION-ATTACK-SQLI.conf 164 | include owasp-modsecurity-crs/rules/REQUEST-43-APPLICATION-ATTACK-SESSION-FIXATION.conf 165 | include owasp-modsecurity-crs/rules/REQUEST-49-BLOCKING-EVALUATION.conf 166 | include owasp-modsecurity-crs/rules/RESPONSE-50-DATA-LEAKAGES-IIS.conf 167 | include owasp-modsecurity-crs/rules/RESPONSE-50-DATA-LEAKAGES-JAVA.conf 168 | include owasp-modsecurity-crs/rules/RESPONSE-50-DATA-LEAKAGES-PHP.conf 169 | include owasp-modsecurity-crs/rules/RESPONSE-50-DATA-LEAKAGES.conf 170 | include owasp-modsecurity-crs/rules/RESPONSE-51-DATA-LEAKAGES-SQL.conf 171 | include owasp-modsecurity-crs/rules/RESPONSE-59-BLOCKING-EVALUATION.conf 172 | include owasp-modsecurity-crs/rules/RESPONSE-80-CORRELATION.conf 173 | include owasp-modsecurity-crs/rules/RESPONSE-99-EXCEPTIONS.conf 174 | 175 | Setting up automated updated 176 | ============================ 177 | todo: 178 | The OWASP Core Rule Set is designed with the capability to be frequently updated in mind. New threats and techniques and updates are provided frequently as part of the rule set and as a result, in order to combat the latest threats effectivly it is imperative that constant updates should be part of your strategy. 179 | 180 | An update script 181 | ---------------- 182 | As part of our continuing effort to provide the most user friendly rule set available we provide an example script that you can use for updating your ruleset: 183 | 184 | .. code-block:: python 185 | 186 | # -*- coding: utf-8 -*- 187 | """ 188 | This script is designed to allow users to automatically 189 | update their ModSecurity OWASP Core Rule Set. It can 190 | be called by a cronjob or scheduled task in order to 191 | allow for automation. Note that it can either replace 192 | the whole CRS directory or just update the rules folder, 193 | which is the default. 194 | """ 195 | 196 | from __future__ import print_function 197 | import argparse 198 | import os 199 | import uuid 200 | import shutil 201 | import logging 202 | 203 | try: 204 | from git import Repo 205 | except ImportError: 206 | print("This script requires the GitPython module (pip install gitpython).") 207 | 208 | __author__ = "Chaim Sanders" 209 | __copyright__ = "Copyright 2016, Trustwave Inc" 210 | __credits__ = ["Chaim Sanders"] 211 | __license__ = "ASL 2.0" 212 | __version__ = "1.0" 213 | __maintainer__ = "Chaim Sanders" 214 | __git__ = "csanders-git" 215 | __status__ = "Production" 216 | 217 | def check_arguments(logger): 218 | """Control arguments and set args variable""" 219 | example_string = "Examples: python %(prog)s --full -p ./owasp-modsecurity-crs/" \ 220 | " or python %(prog)s --folder=util/ --path=./owasp-modsecurity-crs/util" \ 221 | " or python %(prog)s" 222 | parser = argparse.ArgumentParser(description='Update OWASP CRS rules', 223 | formatter_class=argparse.ArgumentDefaultsHelpFormatter, 224 | epilog=example_string) 225 | parser.add_argument('-b', '--branch', default="v3.0.0-rc1", type=str, 226 | required=False, help='The GitHub branch you want to download.') 227 | parser.add_argument('-r', '--repo', 228 | default="https://github.com/SpiderLabs/owasp-modsecurity-crs", 229 | type=str, required=False, help='The GitHub repository you want to use.') 230 | parser.add_argument('-p', '--path', default="./owasp-modsecurity-crs/rules/", type=str, 231 | required=False, help='The path where the rules files should be placed') 232 | group = parser.add_mutually_exclusive_group(required=False) 233 | group.add_argument('--full', action='store_true', 234 | required=False, 235 | help='Copy the whole repo to the path specified instead of just the rules') 236 | group.add_argument('--folder', default="rules/", type=str, 237 | required=False, 238 | help='The toplevel folder within the repo to copy. Can\'t be used with full') 239 | parser.add_argument('-d', '--debug', action='store_true', 240 | required=False, help='Display debug logging.') 241 | args = parser.parse_args() 242 | if args.debug: 243 | logger.setLevel(logging.DEBUG) 244 | logger.debug("Debugging mode has been enabled.") 245 | logger.debug("The following arguments were assigned: " + str(args) + ".") 246 | return args 247 | 248 | def download_rules(args, logger): 249 | """Download and replace our rules""" 250 | if args.path[-1] != os.path.sep: 251 | dst_dir = args.path + os.path.sep 252 | else: 253 | dst_dir = args.path 254 | logger.debug("The final path was set to " + str(dst_dir) + ".") 255 | rand_fold = "./" + str(uuid.uuid4()) 256 | logger.debug("The temporary repo folder was set to " + str(rand_fold) + ".") 257 | # If the user wants the whole directory set that otherwise just rules/ 258 | if args.full: 259 | copy_fold = rand_fold 260 | else: 261 | copy_fold = rand_fold + os.path.sep + args.folder 262 | logger.debug("Set the folder to be copied to " + copy_fold + ".") 263 | Repo.clone_from(args.repo, rand_fold, branch=(args.branch)) 264 | logger.debug("Cloned the repo successfully.") 265 | for src_dir, _, files in os.walk(copy_fold): 266 | for file_ in files: 267 | if file_[-8:] != ".example": 268 | src_file = os.path.join(src_dir, file_) 269 | # If its the full copy we need the new prefix path 270 | if args.full: 271 | copy_path = src_file.replace(rand_fold, "")[1:] 272 | else: 273 | # Remove the overlap in folders 274 | copy_path = src_file.replace(os.path.join(rand_fold, args.folder), "") 275 | dst_file = os.path.join(dst_dir, copy_path) 276 | cwd = os.path.dirname(dst_file) 277 | # Check if the directory structure exists 278 | if not os.path.exists(cwd): 279 | os.makedirs(cwd) 280 | if os.path.exists(dst_file): 281 | os.remove(dst_file) 282 | logger.debug("Removed existing " + dst_file + ".") 283 | try: 284 | shutil.move(src_file, cwd) 285 | except shutil.Error as exc: 286 | print(exc) 287 | logger.debug("Moved " + file_ + " to " + cwd + ".") 288 | logger.debug("Copying completed successfully") 289 | shutil.rmtree(rand_fold) 290 | logger.debug("Deleted the temporary folder.") 291 | 292 | def main(): 293 | """Initiate logging and run subroutines""" 294 | logging.basicConfig(level=logging.INFO) 295 | logger = logging.getLogger(os.path.basename(__file__)) 296 | args = check_arguments(logger) 297 | download_rules(args, logger) 298 | 299 | if __name__ == "__main__": 300 | main() 301 | 302 | Problems with installation 303 | ========================== 304 | 305 | Apache Line Continuation 306 | ------------------------ 307 | In Apache 2.4.x before 2.4.11 there is a bug where the use of line continuations in a config size may cause the line continuation to be truncated. This will lead to an error similar to the following: 308 | 309 | .. code-block:: bash 310 | 311 | Syntax error on line 24 of /etc/httpd/modsecurity.d/activated_rules/RESPONSE-50-DATA-LEAKAGES-PHP.conf: 312 | Error parsing actions: Unknown action: \ 313 | 314 | This is not an error with ModSecurity or OWASP CRS. In order to fix this issue you can simply add a space before the continuation on the offending line. For more information see https://bz.apache.org/bugzilla/show_bug.cgi?id=55910 315 | 316 | Anamoly Mode Doesn't Work 317 | ------------------------- 318 | Sometimes on IIS or Nginx users run into an instance where anamoly mode doesn't work as expected. In fact upon careful inspection of logs one would notice that rules don't fire in the order we would expect. In general this is a result of using the '*' operator within these envivornments as it does not act the same way as in Apache. In general within both Apache and IIS one should expliticly include the various files present within the OWASP CRS instead of using the '*'. 319 | 320 | Webserver returns error after CRS install 321 | ----------------------------------------- 322 | This is likley due to a rule triggering. For instance in some cases a rule is enabled that prohibits access via an IP address. Depending on your `SecDefaultAction `_ and `SecRuleEngine `_ configurations, this may result in a redirect loop or a status code. If this is the problem you are experiencing you should consult your error.log (or event viewer for IIS). From this location you can determine the offending rule and add an exception if neccessary see :doc:`exceptions`. 323 | 324 | 325 | 326 | 327 | -------------------------------------------------------------------------------- /make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | REM Command file for Sphinx documentation 4 | 5 | if "%SPHINXBUILD%" == "" ( 6 | set SPHINXBUILD=sphinx-build 7 | ) 8 | set BUILDDIR=_build 9 | set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . 10 | set I18NSPHINXOPTS=%SPHINXOPTS% . 11 | if NOT "%PAPER%" == "" ( 12 | set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% 13 | set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% 14 | ) 15 | 16 | if "%1" == "" goto help 17 | 18 | if "%1" == "help" ( 19 | :help 20 | echo.Please use `make ^` where ^ is one of 21 | echo. html to make standalone HTML files 22 | echo. dirhtml to make HTML files named index.html in directories 23 | echo. singlehtml to make a single large HTML file 24 | echo. pickle to make pickle files 25 | echo. json to make JSON files 26 | echo. htmlhelp to make HTML files and a HTML help project 27 | echo. qthelp to make HTML files and a qthelp project 28 | echo. devhelp to make HTML files and a Devhelp project 29 | echo. epub to make an epub 30 | echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter 31 | echo. text to make text files 32 | echo. man to make manual pages 33 | echo. texinfo to make Texinfo files 34 | echo. gettext to make PO message catalogs 35 | echo. changes to make an overview over all changed/added/deprecated items 36 | echo. xml to make Docutils-native XML files 37 | echo. pseudoxml to make pseudoxml-XML files for display purposes 38 | echo. linkcheck to check all external links for integrity 39 | echo. doctest to run all doctests embedded in the documentation if enabled 40 | echo. coverage to run coverage check of the documentation if enabled 41 | goto end 42 | ) 43 | 44 | if "%1" == "clean" ( 45 | for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i 46 | del /q /s %BUILDDIR%\* 47 | goto end 48 | ) 49 | 50 | 51 | REM Check if sphinx-build is available and fallback to Python version if any 52 | %SPHINXBUILD% 1>NUL 2>NUL 53 | if errorlevel 9009 goto sphinx_python 54 | goto sphinx_ok 55 | 56 | :sphinx_python 57 | 58 | set SPHINXBUILD=python -m sphinx.__init__ 59 | %SPHINXBUILD% 2> nul 60 | if errorlevel 9009 ( 61 | echo. 62 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 63 | echo.installed, then set the SPHINXBUILD environment variable to point 64 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 65 | echo.may add the Sphinx directory to PATH. 66 | echo. 67 | echo.If you don't have Sphinx installed, grab it from 68 | echo.http://sphinx-doc.org/ 69 | exit /b 1 70 | ) 71 | 72 | :sphinx_ok 73 | 74 | 75 | if "%1" == "html" ( 76 | %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html 77 | if errorlevel 1 exit /b 1 78 | echo. 79 | echo.Build finished. The HTML pages are in %BUILDDIR%/html. 80 | goto end 81 | ) 82 | 83 | if "%1" == "dirhtml" ( 84 | %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml 85 | if errorlevel 1 exit /b 1 86 | echo. 87 | echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. 88 | goto end 89 | ) 90 | 91 | if "%1" == "singlehtml" ( 92 | %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml 93 | if errorlevel 1 exit /b 1 94 | echo. 95 | echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. 96 | goto end 97 | ) 98 | 99 | if "%1" == "pickle" ( 100 | %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle 101 | if errorlevel 1 exit /b 1 102 | echo. 103 | echo.Build finished; now you can process the pickle files. 104 | goto end 105 | ) 106 | 107 | if "%1" == "json" ( 108 | %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json 109 | if errorlevel 1 exit /b 1 110 | echo. 111 | echo.Build finished; now you can process the JSON files. 112 | goto end 113 | ) 114 | 115 | if "%1" == "htmlhelp" ( 116 | %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp 117 | if errorlevel 1 exit /b 1 118 | echo. 119 | echo.Build finished; now you can run HTML Help Workshop with the ^ 120 | .hhp project file in %BUILDDIR%/htmlhelp. 121 | goto end 122 | ) 123 | 124 | if "%1" == "qthelp" ( 125 | %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp 126 | if errorlevel 1 exit /b 1 127 | echo. 128 | echo.Build finished; now you can run "qcollectiongenerator" with the ^ 129 | .qhcp project file in %BUILDDIR%/qthelp, like this: 130 | echo.^> qcollectiongenerator %BUILDDIR%\qthelp\OWASPCRSDocumentation.qhcp 131 | echo.To view the help file: 132 | echo.^> assistant -collectionFile %BUILDDIR%\qthelp\OWASPCRSDocumentation.ghc 133 | goto end 134 | ) 135 | 136 | if "%1" == "devhelp" ( 137 | %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp 138 | if errorlevel 1 exit /b 1 139 | echo. 140 | echo.Build finished. 141 | goto end 142 | ) 143 | 144 | if "%1" == "epub" ( 145 | %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub 146 | if errorlevel 1 exit /b 1 147 | echo. 148 | echo.Build finished. The epub file is in %BUILDDIR%/epub. 149 | goto end 150 | ) 151 | 152 | if "%1" == "latex" ( 153 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex 154 | if errorlevel 1 exit /b 1 155 | echo. 156 | echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. 157 | goto end 158 | ) 159 | 160 | if "%1" == "latexpdf" ( 161 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex 162 | cd %BUILDDIR%/latex 163 | make all-pdf 164 | cd %~dp0 165 | echo. 166 | echo.Build finished; the PDF files are in %BUILDDIR%/latex. 167 | goto end 168 | ) 169 | 170 | if "%1" == "latexpdfja" ( 171 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex 172 | cd %BUILDDIR%/latex 173 | make all-pdf-ja 174 | cd %~dp0 175 | echo. 176 | echo.Build finished; the PDF files are in %BUILDDIR%/latex. 177 | goto end 178 | ) 179 | 180 | if "%1" == "text" ( 181 | %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text 182 | if errorlevel 1 exit /b 1 183 | echo. 184 | echo.Build finished. The text files are in %BUILDDIR%/text. 185 | goto end 186 | ) 187 | 188 | if "%1" == "man" ( 189 | %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man 190 | if errorlevel 1 exit /b 1 191 | echo. 192 | echo.Build finished. The manual pages are in %BUILDDIR%/man. 193 | goto end 194 | ) 195 | 196 | if "%1" == "texinfo" ( 197 | %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo 198 | if errorlevel 1 exit /b 1 199 | echo. 200 | echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. 201 | goto end 202 | ) 203 | 204 | if "%1" == "gettext" ( 205 | %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale 206 | if errorlevel 1 exit /b 1 207 | echo. 208 | echo.Build finished. The message catalogs are in %BUILDDIR%/locale. 209 | goto end 210 | ) 211 | 212 | if "%1" == "changes" ( 213 | %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes 214 | if errorlevel 1 exit /b 1 215 | echo. 216 | echo.The overview file is in %BUILDDIR%/changes. 217 | goto end 218 | ) 219 | 220 | if "%1" == "linkcheck" ( 221 | %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck 222 | if errorlevel 1 exit /b 1 223 | echo. 224 | echo.Link check complete; look for any errors in the above output ^ 225 | or in %BUILDDIR%/linkcheck/output.txt. 226 | goto end 227 | ) 228 | 229 | if "%1" == "doctest" ( 230 | %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest 231 | if errorlevel 1 exit /b 1 232 | echo. 233 | echo.Testing of doctests in the sources finished, look at the ^ 234 | results in %BUILDDIR%/doctest/output.txt. 235 | goto end 236 | ) 237 | 238 | if "%1" == "coverage" ( 239 | %SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage 240 | if errorlevel 1 exit /b 1 241 | echo. 242 | echo.Testing of coverage in the sources finished, look at the ^ 243 | results in %BUILDDIR%/coverage/python.txt. 244 | goto end 245 | ) 246 | 247 | if "%1" == "xml" ( 248 | %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml 249 | if errorlevel 1 exit /b 1 250 | echo. 251 | echo.Build finished. The XML files are in %BUILDDIR%/xml. 252 | goto end 253 | ) 254 | 255 | if "%1" == "pseudoxml" ( 256 | %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml 257 | if errorlevel 1 exit /b 1 258 | echo. 259 | echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. 260 | goto end 261 | ) 262 | 263 | :end 264 | -------------------------------------------------------------------------------- /making.rst: -------------------------------------------------------------------------------- 1 | ===================== 2 | Making Rules 3 | ===================== 4 | 5 | The Basic Synatax 6 | ================= 7 | 8 | A `SecRule `_ is a directive like any other understood by ModSecurity. The difference is that this directive is way more powerful in what it is capable of representing. Generally, a SecRule is made up of 4 parts: 9 | * Variables - Instructs ModSecurity *where* to look (sometimes called Targets) 10 | * Operators - Instructs ModSecurity *when* to trigger a match 11 | * Transformations - Instructs ModSecurity *how* it should normalize variable data 12 | * Actions - Instructs ModSecurity *what* to do if a rule matches 13 | 14 | The structure of the rule is as follows: 15 | 16 | .. code-block:: bash 17 | 18 | SecRule VARIABLES "OPERATOR" "TRANSFORMATIONS,ACTIONS" 19 | 20 | A very basic rule looks as follows: 21 | 22 | .. code-block:: bash 23 | 24 | SecRule REQUEST_URI "@streq /index.php" "id:1,phase:1,t:lowercase,deny" 25 | 26 | The preceding rule will take each HTTP Request and obtain just the URI portion. From there is will transform the URI value to lowercase. Subsequently it will check to see if that transformed value is equal to exactly '/index.php'. If it is Modsecurity will deny the request, that is, it will stop processing further rules and intercept the request. 27 | 28 | As can be seen from the previous explaination, one of the unique things about the SecRule directive is that each SecRule listed in your configuration is evaluated on each transaction. All the other ModSecurity directives are only evaluated at startup. 29 | 30 | Clearly, if this was all there was to SecRules it wouldn't be very powerful. In fact, there is a lot more. So much more that it is in fact a full fledged language. The best place to find out about all the possible capabilities is via the `ModSecurity Reference Manual `_. The following is just a glimpse of its capabilities: 31 | 32 | There are ~105 **variables** in 6 different categories, some examples include: 33 | 34 | * **Request Variables** - ARGS, REQUEST_HEADERS, REQUEST_COOKIES 35 | * **Response Variables** - RESPONSE_HEADERS, RESPONSE_BODY 36 | * **Server Variables** - REMOTE_ADDR, AUTH_TYPE 37 | * **Time Variables** - TIME, TIME_EPOCH, TIME_HOUR 38 | * **Collection Variables** - TX, IP, SESSION, GEO 39 | * **Miscellaneous Variables** - HIGHEST_SEVERITY, MATCHED_VAR 40 | 41 | There are ~36 **operators** in 4 different categories, some examples include: 42 | 43 | * **String Operators** - rx, pm, beginsWith, contains, endsWith, streq, within 44 | * **Numerical Operators** - eq, ge, gt, le, lt 45 | * **Validation Operators** - validateByteRange, validateUrlEncoding, validateSchema 46 | * **Miscellaneous Operators** - rbl, geoLookup, inspectFile, verifyCC 47 | 48 | 49 | There are ~35 **transformation** functions in 6 different categories, some examples include: 50 | 51 | * **Anti-Evasion Functions** - lowercase, normalisePath, removeNulls, replaceComments, compressWhitespace 52 | * **Decoding Functions** - base64Decode, hexDecode, jsDecode, urlDecodeUni 53 | * **Encoding Functions** - base64Encode, hexEncode 54 | * **Hashing Functions** - sha1, md5 55 | 56 | There are ~47 **actions** in 6 different categories, some examples include: 57 | 58 | * **Disruptive Actions** - block, drop, deny, proxy 59 | * **Flow Actions** - chain, skip, skipAfter 60 | * **Metadata Actions** - phase, id, msg, severity, tag 61 | * **Variable Actions** - capture, setvar, initcol 62 | * **Logging Actions** - log, auditlog, nolog, sanitiseArg 63 | * **Miscellaneous Actions** - ctl, multiMatch, exec, pause, append/prepend 64 | 65 | While there are a lot of options available there are a few basic things to remember. 66 | 67 | 1. Every SecRule must have a VARIABLE 68 | 2. Every SecRule must have an OPERATOR, if none is listed @rx is implied. 69 | 3. Every SecRule must have an ACTION. The only required action is id, however, several actions are implied by SecDefaultAction (default phase:2,log,auditlog,pass) 70 | 4. Every SecRule must have an phase ACTION, this tells the rule when to fire. If no phase is included the default is phase:2. 71 | 5. Every SecRule must have a disruptive ACTION. This is an action that describes what to do with the transaction if triggered. If no disruptive action is included the default is pass 72 | 6. Transformations are optional but should be used to prevent your rule from being bypassed 73 | 74 | 75 | Advanced Variable Usage 76 | ======================= 77 | 78 | Variables themselves are quite easy to access as our earlier rules have shown. There are a couple of corner cases though. Not all variables are strings. Some variables, like ARGS_GET are **Collections**. A collection is very similar to a dictionary in Python, it is a key value pair of information. For instance if our request URI was http://www.example.com?x=test&y=test2 our collection might look like ARGS_GET = {"x" : "test", "y" : "test2"}. When we request an VARIABLE that is a collection, ModSecurity will iterate over each value in the collection, applying transformations and checking against the operator, until it finds a match. If it finds a match it will stop processing the rule and undertake any actions specified. 79 | 80 | .. code-block:: bash 81 | 82 | SecRule ARGS_GET "@contains test" "id:1,phase:1,t:lowercase,deny" 83 | 84 | It is possible to access just an index of a collection as well. This makes addressing specific variable very easy. To do this within the VARIABLE area of a SecRule you use the ':' (colon). 85 | 86 | .. code-block:: bash 87 | 88 | SecRule ARGS_GET:username "@contains admin" "id:1,phase:1,t:lowercase,deny" 89 | 90 | One operator is nice but what if I have to apply one operator on multiple rules, for instance I want to check GET parameters and COOKIES. ModSecurity provides a way for you to do this. You can use the '|' (pipe) to combine two VARIABLES into one rule. This pipe can be applied as many times as you want. In the example below we combine both GET and POST arguments. In fact, this is not necessary in reality as there is a built in ARGS collections that already does this. 91 | 92 | .. code-block:: bash 93 | 94 | SecRule ARGS_GET|ARGS_POST|REQUEST_COOKIES "@rx hello\s\d{1,3}" "id:1,phase:2,t:lowercase,deny" 95 | 96 | If you are having a problem where one of your variables is causing false positives or you just don't want to look there you can also remove an index of a collection using the '!' (exclamation mark). This almost always used in conjunction with the pipe and an index, ModSecurity will understand that this means remove this index from the collection 97 | 98 | .. code-block:: bash 99 | 100 | SecRule ARGS|!ARGS:password "@rx (admin|administrator)" "id:1,phase:2,t:lowercase,deny" 101 | 102 | Advanced Transformation Usage 103 | ============================= 104 | The concept of transformations is very intuitive and thanks to ModSecurity's open source nature there are quite a few to choose from. An issue arises in that the proper application of transformations often takes knowledge about how the threat you are trying to stop can manifest itself. Imagine the following example - you are trying to detect an XSS (Cross Site Scripting) attack. 105 | 106 | Your first attempt looks like the following: 107 | 108 | .. code-block:: bash 109 | 110 | SecRule ARGS "@contains . So we can apply a transformation: 113 | 114 | .. code-block:: bash 115 | 116 | SecRule ARGS "@contains . So we need more transformations: 119 | 120 | .. code-block:: bash 121 | 122 | SecRule ARGS "@contains . 125 | 126 | .. code-block:: bash 127 | 128 | SecRule ARGS "@contains