# ------------------------------------------------------------------------ # OWASP ModSecurity Core Rule Set ver.4.0.0-rc1 # Copyright (c) 2006-2020 Trustwave and contributors. All rights reserved. # Copyright (c) 2021-2022 Core Rule Set project. All rights reserved. # # The OWASP ModSecurity Core Rule Set is distributed under # Apache Software License (ASL) version 2 # Please see the enclosed LICENSE file for full details. # ------------------------------------------------------------------------ # # -= Paranoia Level 0 (empty) =- (apply unconditionally) # SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:933011,phase:1,pass,nolog,skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP" SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:933012,phase:2,pass,nolog,skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP" # # -= Paranoia Level 1 (default) =- (apply only when tx.detection_paranoia_level is sufficiently high: 1 or higher) # # # -=[ PHP Injection Attacks ]=- # # [ References ] # http://rips-scanner.sourceforge.net/ # https://www.owasp.org/index.php/PHP_Top_5#P1:_Remote_Code_Executionh # # # [ PHP Open Tag Found ] # # Detects PHP open tags "', but # this resulted in false positives which were difficult to prevent. # Therefore, that pattern is now checked by rule 933190 in paranoia levels # 3 or higher. # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?:<\?(?:[^x]|x[^m]|xm[^l]|xml[^\s]|xml$|$)|<\?php|\[(?:/|\x5c)?php\])" \ "id:933100,\ phase:2,\ block,\ capture,\ t:none,t:lowercase,\ msg:'PHP Injection Attack: PHP Open Tag Found',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-php',\ tag:'platform-multi',\ tag:'attack-injection-php',\ tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ ver:'OWASP_CRS/4.0.0-rc1',\ severity:'CRITICAL',\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # [ PHP Script Uploads ] # # Block file uploads with filenames ending in PHP related extensions # (.php, .phps, .phtml, .php5 etc). # # Many application contain Unrestricted File Upload vulnerabilities. # https://owasp.org/www-community/vulnerabilities/Unrestricted_File_Upload # # Attackers may use such a vulnerability to achieve remote code execution # by uploading a .php file. If the upload storage location is predictable # and not adequately protected, the attacker may then request the uploaded # .php file and have the code within it executed on the server. # # Also block files with just dot (.) characters after the extension: # https://community.rapid7.com/community/metasploit/blog/2013/08/15/time-to-patch-joomla # # Some AJAX uploaders use the nonstandard request headers X-Filename, # X_Filename, or X-File-Name to transmit the file name to the server; # scan these request headers as well as multipart/form-data file names. # SecRule FILES|REQUEST_HEADERS:X-Filename|REQUEST_HEADERS:X_Filename|REQUEST_HEADERS:X.Filename|REQUEST_HEADERS:X-File-Name "@rx .*\.ph(?:p\d*|tml|ar|ps|t|pt)\.*$" \ "id:933110,\ phase:2,\ block,\ capture,\ t:none,t:lowercase,\ msg:'PHP Injection Attack: PHP Script File Upload Found',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-php',\ tag:'platform-multi',\ tag:'attack-injection-php',\ tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ ver:'OWASP_CRS/4.0.0-rc1',\ severity:'CRITICAL',\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # [ PHP Configuration Directives ] # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@pmFromFile php-config-directives.data" \ "id:933120,\ phase:2,\ block,\ capture,\ t:none,t:normalisePath,\ msg:'PHP Injection Attack: Configuration Directive Found',\ logdata:'Matched Data: %{TX.933120_TX_0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-php',\ tag:'platform-multi',\ tag:'attack-injection-php',\ tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ ver:'OWASP_CRS/4.0.0-rc1',\ severity:'CRITICAL',\ setvar:'tx.933120_tx_0=%{tx.0}',\ chain" SecRule MATCHED_VARS "@pm =" \ "capture,\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # [ PHP Variables ] # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@pmFromFile php-variables.data" \ "id:933130,\ phase:2,\ block,\ capture,\ t:none,t:normalisePath,t:urlDecodeUni,\ msg:'PHP Injection Attack: Variables Found',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-php',\ tag:'platform-multi',\ tag:'attack-injection-php',\ tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ ver:'OWASP_CRS/4.0.0-rc1',\ severity:'CRITICAL',\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # [ PHP I/O Streams ] # # The "php://" syntax can be used to refer to various objects, such as local files (for LFI), # remote urls (for RFI), or standard input/request body. Its occurrence indicates a possible attempt # to either inject PHP code or exploit a file inclusion vulnerability in a PHP web app. # # Examples: # php://filter/resource=./../../../wp-config.php # php://filter/resource=http://www.example.com # php://stdin # php://input # # http://php.net/manual/en/wrappers.php.php # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)php://(?:std(?:in|out|err)|(?:in|out)put|fd|memory|temp|filter)" \ "id:933140,\ phase:2,\ block,\ capture,\ t:none,\ msg:'PHP Injection Attack: I/O Stream Found',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-php',\ tag:'platform-multi',\ tag:'attack-injection-php',\ tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ ver:'OWASP_CRS/4.0.0-rc1',\ severity:'CRITICAL',\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # [ PHP Wrappers ] # # PHP comes with many built-in wrappers for various URL-style protocols for use with the filesystem # functions such as fopen(), copy(), file_exists() and filesize(). Abusing of PHP wrappers like phar:// # could lead to RCE as describled by Sam Thomas at BlackHat USA 2018 (https://bit.ly/2yaKV5X), even # wrappers like zlib://, glob://, rar://, zip://, etc... could lead to LFI and expect:// to RCE. # # Valid PHP wrappers can be found in the PHP documentation here: # https://www.php.net/manual/en/wrappers.php # # Regular expression generated from regex-assembly/933200.ra. # To update the regular expression run the following shell script # (consult https://coreruleset.org/docs/development/regex_assembly/ for details): # crs-toolchain regex update 933200 # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?:bzip2|expect|glob|ogg|(?:ph|r)ar|ssh2(?:.(?:s(?:hell|(?:ft|c)p)|exec|tunnel))?|z(?:ip|lib))://" \ "id:933200,\ phase:2,\ block,\ t:none,t:utf8toUnicode,t:urlDecodeUni,t:removeNulls,t:cmdLine,\ msg:'PHP Injection Attack: Wrapper scheme detected',\ logdata:'Matched Data: %{MATCHED_VAR} found within %{MATCHED_VAR_NAME}',\ tag:'application-multi',\ tag:'language-php',\ tag:'platform-multi',\ tag:'attack-injection-php',\ tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ ver:'OWASP_CRS/4.0.0-rc1',\ severity:'CRITICAL',\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # [ PHP Functions ] # # Detecting PHP function names is useful to block PHP code injection attacks. # There are many PHP functions. We have to strike a balance between robust detection # of PHP code in content, and the risk of false positives. # # The list of PHP functions is divided into four groups of varying attack/false positive risk. # Four separate rules are used to detect these groups of functions: # # - Rule 933150: ~40 words highly common to PHP injection payloads and extremely rare in # natural language or other contexts. # Examples: 'base64_decode', 'file_get_contents'. # These words are detected as a match directly using @pmFromFile. # Function names are defined in php-function-names-933150.data # # - Rule 933160: ~220 words which are common in PHP code, but have a higher chance to cause # false positives in natural language or other contexts. # Examples: 'chr', 'eval'. # To mitigate false positives, a regexp looks for PHP function syntax, e.g. 'eval()'. # Regexp is generated from function names in util/regexp-assemble/data/933160.data # # - Rule 933151: ~1300 words of lesser importance. This includes most PHP functions and keywords. # Examples: 'addslashes', 'array_diff'. # For performance reasons, the @pmFromFile operator is used, and many functions from lesser # used PHP extensions are removed. # To mitigate false positives, we only match when the '(' character is also found. # This rule only runs in paranoia level 2 or higher. # Function names are defined in php-function-names-933151.data # # - Rule 933161: ~200 words with short or trivial names, possibly leading to false positives. # Examples: 'abs', 'cos'. # To mitigate false positives, a regexp matches on function syntax, e.g. 'abs()'. # This rule only runs in paranoia level 3 or higher. # Regexp is generated from function names in util/regexp-assemble/data/933161.data # # # [ PHP Functions: High-Risk PHP Function Names ] # # Rule 933150 contains a small list of function names which are highly indicative of a PHP # injection attack, for example 'base64_decode'. # We block these function names outright, without using a complex regexp or chain. # This could make the detection a bit more robust against possible bypasses. # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* "@pmFromFile php-function-names-933150.data" \ "id:933150,\ phase:2,\ block,\ capture,\ t:none,\ msg:'PHP Injection Attack: High-Risk PHP Function Name Found',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-php',\ tag:'platform-multi',\ tag:'attack-injection-php',\ tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ ver:'OWASP_CRS/4.0.0-rc1',\ severity:'CRITICAL',\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # [ PHP Functions: High-Risk PHP Function Calls ] # # Some PHP function names have a certain risk of false positives, due to short # names, full or partial overlap with common natural language terms, uses in # other contexts, et cetera. Some examples are 'eval', 'exec', 'system'. # # For these function names, we apply a regexp to look for PHP function syntax. # The regexp looks for a word boundary and adjoining parentheses. # For instance, we want to block 'eval()', but we want to allow 'medieval()'. # # We have to be careful of possible bypasses using comment syntax. Examples: # # system(...) # system (...) # system\t(...) # system /*comment*/ (...) # system /*multiline \n comment*/ (...) # system //comment \n (...) # system #comment \n (...) # # This rule is also triggered by the following exploit(s): # [ Apache Struts vulnerability CVE-2017-9791 - Exploit tested: https://www.exploit-db.com/exploits/42324 ] # [ Apache Struts vulnerability CVE-2018-11776 - Exploit tested: https://www.exploit-db.com/exploits/45260 ] # [ SAP CRM Java vulnerability CVE-2018-2380 - Exploit tested: https://www.exploit-db.com/exploits/44292 ] # # Regular expression generated from regex-assembly/933160.ra. # To update the regular expression run the following shell script # (consult https://coreruleset.org/docs/development/regex_assembly/ for details): # crs-toolchain regex update 933160 # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* "@rx (?i)\b\(?[\"']*(?:a(?:rray_(?:(?:diff|intersect)_u(?:assoc|key)|filter|map|reduce|u(?:diff|intersect)(?:_u?assoc)?)|ssert(?:_options)?)|b(?:(?:ase64_en|son_(?:de|en))code|zopen)|c(?:hr|onvert_uuencode|reate_function|url_(?:exec|file_create|init))|(?:debug_backtrac|json_(?:de|en)cod|tmpfil)e|e(?:rror_reporting|scapeshell(?:arg|cmd)|val|x(?:ec|if_(?:imagetype|read_data|t(?:agname|humbnail))))|f(?:i(?:le(?:(?:_exist|perm)s|(?:[acm]tim|inod)e|group)?|nfo_open)|open|(?:pu|unction_exis)ts|tp_(?:connec|ge|nb_(?:ge|pu)|pu)t|write)|g(?:et(?:_(?:c(?:fg_va|urrent_use)r|meta_tags)|(?:cw|lastmo)d|env|imagesize|my(?:[gpu]id|inode))|lob|z(?:compress|(?:(?:defla|wri)t|encod|fil)e|open|read))|h(?:(?:ash_(?:(?:hmac|update)_)?|ighlight_)file|e(?:ader_register_callback|x2bin)|tml(?:_entity_decode|entities|specialchars(?:_decode)?))|i(?:mage(?:2?wbmp|createfrom(?:gif|(?:jpe|pn)g|wbmp|x[bp]m)|g(?:d2?|if)|(?:jpe|pn)g|xbm)|ni_(?:get(?:_all)?|set)|ptcembed|s_(?:dir|(?:(?:execut|read|write?)ab|fi)le)|terator_apply)|m(?:b_(?:ereg(?:_(?:match|replace(?:_callback)?)|i(?:_replace)?)?|parse_str)|(?:d5|ove_uploaded)_file|ethod_exists|kdir|ysql_query)|o(?:b_(?:clean|end_(?:clean|flush)|flush|get_(?:c(?:lean|ontents)|flush)|start)|dbc_(?:connect|exec(?:ute)?|result(?:_all)?)|pendir)|p(?:a(?:rse_(?:ini_file|str)|ssthru)|g_(?:connect|(?:execut|prepar)e|query)|hp(?:_(?:strip_whitespac|unam)e|info|version)|o(?:pen|six_(?:get(?:(?:e[gu]|g)id|login|pwnam)|kill|mk(?:fifo|nod)|ttyname))|r(?:eg_(?:match(?:_all)?|replace(?:_callback(?:_array)?)?|split)|int_r|oc_(?:(?:clos|nic|terminat)e|get_status|open))|utenv)|r(?:awurl(?:de|en)code|e(?:ad(?:_exif_data|dir|(?:gz)?file)|(?:gister_(?:shutdown|tick)|name)_function)|unkit_(?:constant_(?:add|redefine)|(?:function|method)_(?:add|copy|re(?:defin|nam)e)))|s(?:e(?:ssion_s(?:et_save_handler|tart)|t(?:_(?:e(?:rror|xception)_handler|include_path|magic_quotes_runtime)|defaultstub))|h(?:a1_fil|ow_sourc)e|implexml_load_(?:file|string)|ocket_c(?:onnect|reate)|pl_autoload_register|qlite_(?:(?:(?:array|single|unbuffered)_)?query|create_(?:aggregate|function)|exec|p?open)|tr(?:eam_(?:context_create|socket_client)|ipc?slashes|rev)|ystem)|u(?:[ak]?sort|n(?:pack|serialize)|rl(?:de|en)code)|var_dump)(?:/(?:\*.*\*/|/.*)|#.*[\s\v]|\")*[\"']*\)?[\s\v]*\(.*\)" \ "id:933160,\ phase:2,\ block,\ capture,\ t:none,\ msg:'PHP Injection Attack: High-Risk PHP Function Call Found',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-php',\ tag:'platform-multi',\ tag:'attack-injection-php',\ tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ ver:'OWASP_CRS/4.0.0-rc1',\ severity:'CRITICAL',\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # [ PHP Object Injection ] # # PHP Object Injection is an application level vulnerability that could allow # an attacker to perform different kinds of malicious attacks, such as # Code Injection, SQL Injection, Path Traversal and Application Denial of Service, # depending on the context. # # The vulnerability occurs when user-supplied input is not properly sanitized # before being passed to the unserialize() PHP function. Since PHP allows object # serialization, attackers could pass ad-hoc serialized strings to a vulnerable # unserialize() call, resulting in an arbitrary PHP object(s) injection into the # application scope. # # https://www.owasp.org/index.php/PHP_Object_Injection # # In serialized form, PHP objects have the following format: # # O:8:"stdClass":1:{s:1:"a";i:2;} # O:3:"Foo":0:{} # # Also detected are PHP objects with a custom unserializer: # http://www.phpinternalsbook.com/classes_objects/serialization.html # These have the following format: # # C:11:"ArrayObject":37:{x:i:0;a:1:{s:1:"a";s:1:"b";};m:a:0:{}} # C:3:"Foo":23:{s:15:"My private data";} # # HTTP headers are inspected, since PHP object injection vulnerabilities have been # found in applications parsing them: # https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-8562 (User-Agent header) # https://www.exploit-db.com/exploits/39033/ (X-Forwarded-For header) # http://karmainsecurity.com/KIS-2015-10 (Host header) # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_HEADERS|ARGS_NAMES|ARGS|XML:/* "@rx [oOcC]:\d+:\".+?\":\d+:{.*}" \ "id:933170,\ phase:2,\ block,\ capture,\ t:none,\ msg:'PHP Injection Attack: Serialized Object Injection',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-php',\ tag:'platform-multi',\ tag:'attack-injection-php',\ tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ ver:'OWASP_CRS/4.0.0-rc1',\ severity:'CRITICAL',\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # [ PHP Functions: Variable Function Calls ] # # PHP 'variable functions' provide an alternate syntax for calling PHP functions. # http://php.net/manual/en/functions.variable-functions.php # # An attacker may use variable function syntax to evade detection of function # names during exploitation of a remote code execution vulnerability. # An example to use the 'file_get_contents' function while evading rule 933150: # # $fn = 'file_' . 'get_' . 'contents'; # echo $fn('wp-co' . 'nfig.php'); # # Some examples from obfuscated malware: # # $OOO0000O0(...) # @$b374k(...) # $_[@-_]($_[@!+_] ) # # A breakdown of the regular expression: # # \$+ # The variable's '$' char, or multiple '$' for 'variable variables': # http://php.net/manual/en/language.variables.variable.php # (?:[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*|\s*{.+}) # One of the following: # - A variable name; regexp from http://php.net/language.variables.basics # - A nonempty expression for variable variables: ${'fn'} or $ {'fn'} # (?:\s|\[.+\]|{.+}|/\*.*\*/|//.*|#.*)* # Optional whitespace, array access, or comments # \(.*\) # Parentheses optionally containing function parameters # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* "@rx \$+(?:[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*|\s*{.+})(?:\s|\[.+\]|{.+}|/\*.*\*/|//.*|#.*)*\(.*\)" \ "id:933180,\ phase:2,\ block,\ capture,\ t:none,\ msg:'PHP Injection Attack: Variable Function Call Found',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-php',\ tag:'platform-multi',\ tag:'attack-injection-php',\ tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ ver:'OWASP_CRS/4.0.0-rc1',\ severity:'CRITICAL',\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # [ PHP Functions: Variable Function Prevent Bypass ] # # Referring to https://www.secjuice.com/php-rce-bypass-filters-sanitization-waf/ # Regex test on https://regex101.com/r/x1tfXG/1 # the rule 933180 could be bypassed by using the following payloads: # # - (system)('uname'); # - (sy.(st).em)('uname'); # - (string)"system"('uname'); # - define('x', 'sys' . 'tem');(x)/* comment */('uname'); # - $y = 'sys'.'tem';($y)('uname'); # - define('z', [['sys' .'tem']]);(z)[0][0]('uname'); # - (system)(ls); # - (/**/system)(ls/**/); # - (['system'])[0]('uname'); # - (++[++system++][++0++])++{/*dsasd*/0}++(++ls++); # # This rule blocks all payloads above and avoids to block values like: # # - [ACME] this is a test (just a test) # - Test (with two) rounded (brackets) # # Regular expression generated from regex-assembly/933210.ra. # To update the regular expression run the following shell script # (consult https://coreruleset.org/docs/development/regex_assembly/ for details): # crs-toolchain regex update 933210 # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* "@rx (?:\((?:.+\)(?:[\"'][\-0-9A-Z_a-z]+[\"'])?\(.+|[^\)]*string[^\)]*\)[\s\v\"'\--\.0-9A-\[\]_a-\{\}]+\([^\)]*)|(?:\[[0-9]+\]|\{[0-9]+\}|\$[^\(-\),\.-/;\x5c]+|[\"'][\-0-9A-Z\x5c_a-z]+[\"'])\(.+)\);" \ "id:933210,\ phase:2,\ block,\ capture,\ t:none,t:urlDecode,t:replaceComments,t:removeWhitespace,\ msg:'PHP Injection Attack: Variable Function Call Found',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-php',\ tag:'platform-multi',\ tag:'attack-injection-php',\ tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ ver:'OWASP_CRS/4.0.0-rc1',\ severity:'CRITICAL',\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:933013,phase:1,pass,nolog,skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP" SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:933014,phase:2,pass,nolog,skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP" # # -= Paranoia Level 2 =- (apply only when tx.detection_paranoia_level is sufficiently high: 2 or higher) # # # [ PHP Functions: Medium-Risk PHP Function Names ] # # In paranoia level 2, we add additional checks for most PHP functions. # # The size of the PHP function list is considerable. # Even after excluding the more obscure PHP extensions, 1300+ functions remain. # For performance and maintenance reasons, this rule does not use a regexp, # but uses a phrase file (@pmFromFile), and additionally looks for an '(' character # in the matched variable. # # This approach carries some risk for false positives. Therefore, the function list # has been curated to remove words closely matching natural language and terms often # used in other contexts. # # This rule is a stricter sibling of rule 933150. # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* "@pmFromFile php-function-names-933151.data" \ "id:933151,\ phase:2,\ block,\ capture,\ t:none,\ msg:'PHP Injection Attack: Medium-Risk PHP Function Name Found',\ logdata:'Matched Data: %{TX.933151_TX_0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-php',\ tag:'platform-multi',\ tag:'attack-injection-php',\ tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ tag:'paranoia-level/2',\ ver:'OWASP_CRS/4.0.0-rc1',\ severity:'CRITICAL',\ setvar:'tx.933151_tx_0=%{tx.0}',\ chain" SecRule MATCHED_VARS "@pm (" \ "capture,\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:933015,phase:1,pass,nolog,skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP" SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:933016,phase:2,pass,nolog,skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP" # # -= Paranoia Level 3 =- (apply only when tx.detection_paranoia_level is sufficiently high: 3 or higher) # # # [ PHP Variables: Common Variable Indexes ] # # In paranoia level 3, we add additional checks for parameters to many PHP variables. # # # One of the more common variables used within attacks on PHP is $_SERVER. Because # of how many different ways PHP has for executing variables (variable variables, # etc) often just looking for $_SERVER will be less effective than looking for the # various indexes within $_SERVER. This rule checks for these indexes. # This rule is located in PL 3 because often developers will use these names as # parameter names or values and this will lead to false positives. # Because this list is not expected to change and it is limited in size we use a # regex in this case to look for these values whereas in its sibling rule we use # @pmFromFile for flexibility and performance. # # Regular expression generated from regex-assembly/933131.ra. # To update the regular expression run the following shell script # (consult https://coreruleset.org/docs/development/regex_assembly/ for details): # crs-toolchain regex update 933131 # # This rule is a stricter sibling of rule 933130. SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx AUTH_TYPE|HTTP_(?:ACCEPT(?:_(?:CHARSET|ENCODING|LANGUAGE))?|CONNECTION|(?:HOS|USER_AGEN)T|KEEP_ALIVE|(?:REFERE|X_FORWARDED_FO)R)|ORIG_PATH_INFO|PATH_(?:INFO|TRANSLATED)|QUERY_STRING|REQUEST_URI" \ "id:933131,\ phase:2,\ block,\ capture,\ t:none,t:normalisePath,t:urlDecodeUni,\ msg:'PHP Injection Attack: Variables Found',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-php',\ tag:'platform-multi',\ tag:'attack-injection-php',\ tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ tag:'paranoia-level/3',\ ver:'OWASP_CRS/4.0.0-rc1',\ severity:'CRITICAL',\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.inbound_anomaly_score_pl3=+%{tx.critical_anomaly_score}'" # # [ PHP Functions: Low-Value PHP Function Calls ] # # In paranoia level 3, we add additional checks for the remaining PHP functions. # # Most of these function names are likely to cause false positives in natural text # or common parameter values, such as 'abs', 'copy', 'date', 'key', 'max', 'min'. # Therefore, these function names are not scanned in lower paranoia levels. # # To mitigate the risk of false positives somewhat, a regexp is used to look for # PHP function syntax. (See rule 933160 for a description.) # # This rule is a stricter sibling of rule 933160. # # This rule is also triggered by the following exploit(s): # [ Apache Struts vulnerability CVE-2018-11776 - Exploit tested: https://www.exploit-db.com/exploits/45262 ] # [ SAP CRM Java vulnerability CVE-2018-2380 - Exploit tested: https://www.exploit-db.com/exploits/44292 ] # # Regular expression generated from regex-assembly/933161.ra. # To update the regular expression run the following shell script # (consult https://coreruleset.org/docs/development/regex_assembly/ for details): # crs-toolchain regex update 933161 # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* "@rx (?i)\b(?:a(?:bs|cosh?|r(?:ray|sort)|s(?:inh?|(?:o|se)rt)|tan[2h]?)|b(?:asename|indec)|c(?:eil|h(?:dir|eckdate|mod|o(?:p|wn)|root)|lose(?:dir|log)|o(?:(?:mpac|(?:nsta|u)n)t|py|sh?)|(?:ryp|urren)t)|d(?:ate|e(?:coct|fined?)|i(?:(?:skfreespac)?e|r(?:name)?)|(?:oubleva)?l)|e(?:a(?:ch|ster_da(?:te|ys))|cho|mpty|nd|r(?:egi?|ror_log)|x(?:(?:i|trac)t|p(?:lode)?))|f(?:close|eof|gets|ile(?:owner|pro|(?:siz|typ)e)|l(?:o(?:atval|ck|or)|ush)|(?:mo|rea)d|stat|t(?:ell|ok)|unction)|g(?:et(?:date|t(?:ext|ype))|mdate)|h(?:ash|e(?:ader(?:s_(?:lis|sen)t)?|brev)|ypot)|i(?:conv|(?:dat|mplod)e|n(?:(?:clud|vok)e|t(?:div|val))|s(?:_(?:a(?:rray)?|bool|(?:calla|dou)ble|f(?:inite|loat)|in(?:finite|t(?:eger)?)|l(?:ink|ong)|n(?:an|u(?:ll|meric))|object|re(?:al|source)|s(?:calar|tring))|set))|join|k(?:ey|sort)|l(?:(?:cfirs|sta)t|evenshtein|i(?:nk(?:info)?|st)|o(?:caltime|g(?:1[0p])?)|trim)|m(?:a(?:i[ln]|x)|b(?:ereg|split)|etaphone|hash|i(?:crotime|n)|y?sql)|n(?:atsor|ex)t|o(?:ctdec|penlog|rd)|p(?:a(?:ck|thinfo)|close|i|o[sw]|r(?:ev|intf?))|quotemeta|r(?:an(?:d|ge)|e(?:adlin[ek]|(?:cod|nam|quir)e|set|wind)|ound|sort|trim)|s(?:(?:candi|ubst)r|(?:e(?:rializ|ttyp)|huffl)e|i(?:milar_text|nh?|zeof)|leep|o(?:rt|undex)|p(?:liti?|rintf)|qrt|rand|t(?:at|r(?:coll|(?:le|sp)n))|y(?:mlink|slog))|t(?:a(?:int|nh?)|e(?:mpnam|xtdomain)|ime|ouch|rim)|u(?:cfirst|mask|n(?:iqid|link|(?:se|tain)t)|s(?:leep|ort))|virtual|wordwrap)(?:[\s\v]|/(?:\*.*\*/|/.*)|#.*)*\(.*\)" \ "id:933161,\ phase:2,\ block,\ capture,\ t:none,\ msg:'PHP Injection Attack: Low-Value PHP Function Call Found',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-php',\ tag:'platform-multi',\ tag:'attack-injection-php',\ tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ tag:'paranoia-level/3',\ ver:'OWASP_CRS/4.0.0-rc1',\ severity:'CRITICAL',\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.inbound_anomaly_score_pl3=+%{tx.critical_anomaly_score}'" # # [ PHP Script Uploads: Superfluous extension ] # # Block file uploads with PHP related extensions (.php, .phps, .phtml, # .php5 etc) anywhere in the name, followed by a dot. # # Example: index.php.tmp # # Uploading of such files can lead to remote code execution if # Apache is configured with AddType and MultiViews, as Apache will # automatically do a filename match when the extension is unknown. # This configuration is fortunately not common in modern installs. # # Blocking these file names might lead to more false positives. # # Some AJAX uploaders use the nonstandard request headers X-Filename, # X_Filename, or X-File-Name to transmit the file name to the server; # scan these request headers as well as multipart/form-data file names. # # This rule is a stricter sibling of rule 933110. # SecRule FILES|REQUEST_HEADERS:X-Filename|REQUEST_HEADERS:X_Filename|REQUEST_HEADERS:X.Filename|REQUEST_HEADERS:X-File-Name "@rx .*\.(?:php\d*|phtml)\..*$" \ "id:933111,\ phase:2,\ block,\ capture,\ t:none,t:lowercase,\ msg:'PHP Injection Attack: PHP Script File Upload Found',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-php',\ tag:'platform-multi',\ tag:'attack-injection-php',\ tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ tag:'paranoia-level/3',\ ver:'OWASP_CRS/4.0.0-rc1',\ severity:'CRITICAL',\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.inbound_anomaly_score_pl3=+%{tx.critical_anomaly_score}'" # [ PHP Closing Tag Found ] # # http://www.php.net/manual/en/language.basic-syntax.phptags.php # # This check was extracted from 933100 (paranoia level 1), since the # checked sequence '?>' commonly causes false positives. # See issue #654 for discussion. # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@pm ?>" \ "id:933190,\ phase:2,\ block,\ capture,\ t:none,t:urlDecodeUni,\ msg:'PHP Injection Attack: PHP Closing Tag Found',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-php',\ tag:'platform-multi',\ tag:'attack-injection-php',\ tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ tag:'paranoia-level/3',\ ver:'OWASP_CRS/4.0.0-rc1',\ severity:'CRITICAL',\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.inbound_anomaly_score_pl3=+%{tx.critical_anomaly_score}'" # [ PHP Functions: Variable Function Prevent Bypass ] # # This rule is a stricter sibling of 933210. # Unlike 933210, this rule will also match "this is a 'dog' (not a cat)", because the semi-colon at the end of the string is optional. # This is useful for PHP evals where the semi-colon is already hardcoded: # # # Any potential function calls not at the end of a string will require a semi-colon to form valid PHP, which is automatically covered by 933210. # # Regular expression generated from regex-assembly/933211.ra. # To update the regular expression run the following shell script # (consult https://coreruleset.org/docs/development/regex_assembly/ for details): # crs-toolchain regex update 933211 # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* "@rx (?:\((?:.+\)(?:[\"'][\-0-9A-Z_a-z]+[\"'])?\(.+|[^\)]*string[^\)]*\)[\s\v\"'\--\.0-9A-\[\]_a-\{\}]+\([^\)]*)|(?:\[[0-9]+\]|\{[0-9]+\}|\$[^\(-\),\.-/;\x5c]+|[\"'][\-0-9A-Z\x5c_a-z]+[\"'])\(.+)\)(?:;|$)?" \ "id:933211,\ phase:2,\ block,\ capture,\ t:none,t:urlDecode,t:replaceComments,t:removeWhitespace,\ msg:'PHP Injection Attack: Variable Function Call Found',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-php',\ tag:'platform-multi',\ tag:'attack-injection-php',\ tag:'paranoia-level/3',\ tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ ver:'OWASP_CRS/4.0.0-rc1',\ severity:'CRITICAL',\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.inbound_anomaly_score_pl3=+%{tx.critical_anomaly_score}'" SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:933017,phase:1,pass,nolog,skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP" SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:933018,phase:2,pass,nolog,skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP" # # -= Paranoia Level 4 =- (apply only when tx.detection_paranoia_level is sufficiently high: 4 or higher) # # # -= Paranoia Levels Finished =- # SecMarker "END-REQUEST-933-APPLICATION-ATTACK-PHP"