# ------------------------------------------------------------------------
# OWASP ModSecurity Core Rule Set ver.3.3.2
# Copyright (c) 2006-2020 Trustwave and contributors. 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:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:933011,phase:1,pass,nolog,skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP"
SecRule TX:EXECUTING_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.executing_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 "<?" and "<?php".
# http://www.php.net/manual/en/language.basic-syntax.phptags.php
#
# Care is taken to avoid false positives in XML declarations "<?xml..."
#
# Also detects "[php]", "[/php]" and "[\php]" tags used by some applications
# to indicate PHP dynamic content.
#
# Previously, this rule also checked for the PHP close tag '?>', 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|\[(?:\/|\\\\)?php\])" \
    "id:933100,\
    phase:2,\
    block,\
    capture,\
    t:none,t:urlDecodeUni,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',\
    ctl:auditLogParts=+E,\
    ver:'OWASP_CRS/3.3.2',\
    severity:'CRITICAL',\
    setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\
    setvar:'tx.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://www.owasp.org/index.php/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 .*\.(?:php\d*|phtml)\.*$" \
    "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',\
    ctl:auditLogParts=+E,\
    ver:'OWASP_CRS/3.3.2',\
    severity:'CRITICAL',\
    setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\
    setvar:'tx.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:urlDecodeUni,t:normalisePath,t:lowercase,\
    msg:'PHP Injection Attack: Configuration Directive 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',\
    ctl:auditLogParts=+E,\
    ver:'OWASP_CRS/3.3.2',\
    severity:'CRITICAL',\
    chain"
    SecRule MATCHED_VARS "@pm =" \
        "capture,\
        setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\
        setvar:'tx.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,t:lowercase,\
    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',\
    ctl:auditLogParts=+E,\
    ver:'OWASP_CRS/3.3.2',\
    severity:'CRITICAL',\
    setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\
    setvar:'tx.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',\
    ctl:auditLogParts=+E,\
    ver:'OWASP_CRS/3.3.2',\
    severity:'CRITICAL',\
    setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\
    setvar:'tx.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.
#
SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i:zlib|glob|phar|ssh2|rar|ogg|expect|zip)://" \
    "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',\
    ctl:auditLogParts=+E,\
    ver:'OWASP_CRS/3.3.2',\
    severity:'CRITICAL',\
    setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\
    setvar:'tx.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/regexp-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/regexp-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,t:lowercase,\
    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',\
    ctl:auditLogParts=+E,\
    ver:'OWASP_CRS/3.3.2',\
    severity:'CRITICAL',\
    setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\
    setvar:'tx.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 ]
#
# Regexp generated from util/regexp-assemble/regexp-933160.data using Regexp::Assemble.
# See https://coreruleset.org/20190826/optimizing-regular-expressions/ for usage.
#
# Note that after assemble, PHP function syntax pre/postfix is added to the Regexp::Assemble
# output. Example: "@rx (?i)\bASSEMBLE_OUTPUT_HERE(?:\s|/\*.*\*/|//.*|#.*)*\(.*\)"
#
SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* "@rx (?i)\b(?:s(?:e(?:t(?:_(?:e(?:xception|rror)_handler|magic_quotes_runtime|include_path)|defaultstub)|ssion_s(?:et_save_handler|tart))|qlite_(?:(?:(?:unbuffered|single|array)_)?query|create_(?:aggregate|function)|p?open|exec)|tr(?:eam_(?:context_create|socket_client)|ipc?slashes|rev)|implexml_load_(?:string|file)|ocket_c(?:onnect|reate)|h(?:ow_sourc|a1_fil)e|pl_autoload_register|ystem)|p(?:r(?:eg_(?:replace(?:_callback(?:_array)?)?|match(?:_all)?|split)|oc_(?:(?:terminat|clos|nic)e|get_status|open)|int_r)|o(?:six_(?:get(?:(?:e[gu]|g)id|login|pwnam)|mk(?:fifo|nod)|ttyname|kill)|pen)|hp(?:_(?:strip_whitespac|unam)e|version|info)|g_(?:(?:execut|prepar)e|connect|query)|a(?:rse_(?:ini_file|str)|ssthru)|utenv)|r(?:unkit_(?:function_(?:re(?:defin|nam)e|copy|add)|method_(?:re(?:defin|nam)e|copy|add)|constant_(?:redefine|add))|e(?:(?:gister_(?:shutdown|tick)|name)_function|ad(?:(?:gz)?file|_exif_data|dir))|awurl(?:de|en)code)|i(?:mage(?:createfrom(?:(?:jpe|pn)g|x[bp]m|wbmp|gif)|(?:jpe|pn)g|g(?:d2?|if)|2?wbmp|xbm)|s_(?:(?:(?:execut|write?|read)ab|fi)le|dir)|ni_(?:get(?:_all)?|set)|terator_apply|ptcembed)|g(?:et(?:_(?:c(?:urrent_use|fg_va)r|meta_tags)|my(?:[gpu]id|inode)|(?:lastmo|cw)d|imagesize|env)|z(?:(?:(?:defla|wri)t|encod|fil)e|compress|open|read)|lob)|a(?:rray_(?:u(?:intersect(?:_u?assoc)?|diff(?:_u?assoc)?)|intersect_u(?:assoc|key)|diff_u(?:assoc|key)|filter|reduce|map)|ssert(?:_options)?)|h(?:tml(?:specialchars(?:_decode)?|_entity_decode|entities)|(?:ash(?:_(?:update|hmac))?|ighlight)_file|e(?:ader_register_callback|x2bin))|f(?:i(?:le(?:(?:[acm]tim|inod)e|(?:_exist|perm)s|group)?|nfo_open)|tp_(?:nb_(?:ge|pu)|connec|ge|pu)t|(?:unction_exis|pu)ts|write|open)|o(?:b_(?:get_(?:c(?:ontents|lean)|flush)|end_(?:clean|flush)|clean|flush|start)|dbc_(?:result(?:_all)?|exec(?:ute)?|connect)|pendir)|m(?:b_(?:ereg(?:_(?:replace(?:_callback)?|match)|i(?:_replace)?)?|parse_str)|(?:ove_uploaded|d5)_file|ethod_exists|ysql_query|kdir)|e(?:x(?:if_(?:t(?:humbnail|agname)|imagetype|read_data)|ec)|scapeshell(?:arg|cmd)|rror_reporting|val)|c(?:url_(?:file_create|exec|init)|onvert_uuencode|reate_function|hr)|u(?:n(?:serialize|pack)|rl(?:de|en)code|[ak]?sort)|(?:json_(?:de|en)cod|debug_backtrac|tmpfil)e|b(?:(?:son_(?:de|en)|ase64_en)code|zopen)|var_dump)(?:\s|/\*.*\*/|//.*|#.*)*\(.*\)" \
    "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',\
    ctl:auditLogParts=+E,\
    ver:'OWASP_CRS/3.3.2',\
    severity:'CRITICAL',\
    setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\
    setvar:'tx.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',\
    ctl:auditLogParts=+E,\
    ver:'OWASP_CRS/3.3.2',\
    severity:'CRITICAL',\
    setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\
    setvar:'tx.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',\
    ctl:auditLogParts=+E,\
    ver:'OWASP_CRS/3.3.2',\
    severity:'CRITICAL',\
    setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\
    setvar:'tx.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/
# 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)
#
SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* "@rx (?:(?:\(|\[)[a-zA-Z0-9_.$\"'\[\](){}/*\s]+(?:\)|\])[0-9_.$\"'\[\](){}/*\s]*\([a-zA-Z0-9_.$\"'\[\](){}/*\s].*\)|\([\s]*string[\s]*\)[\s]*(?:\"|'))" \
    "id:933210,\
    phase:2,\
    block,\
    capture,\
    t:none,t:urlDecode,t:replaceComments,t:compressWhitespace,\
    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',\
    ctl:auditLogParts=+E,\
    ver:'OWASP_CRS/3.3.2',\
    severity:'CRITICAL',\
    setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\
    setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'"

SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:933013,phase:1,pass,nolog,skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP"
SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:933014,phase:2,pass,nolog,skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP"
#
# -= Paranoia Level 2 =- (apply only when tx.executing_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,t:lowercase,\
    msg:'PHP Injection Attack: Medium-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:'OWASP_CRS',\
    tag:'capec/1000/152/242',\
    tag:'paranoia-level/2',\
    ctl:auditLogParts=+E,\
    ver:'OWASP_CRS/3.3.2',\
    severity:'CRITICAL',\
    chain"
    SecRule MATCHED_VARS "@pm (" \
        "capture,\
        setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\
        setvar:'tx.anomaly_score_pl2=+%{tx.critical_anomaly_score}'"




SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:933015,phase:1,pass,nolog,skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP"
SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:933016,phase:2,pass,nolog,skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP"
#
# -= Paranoia Level 3 =- (apply only when tx.executing_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.
#
# To rebuild the regexp:
#   cd util/regexp-assemble
#   ./regexp-assemble.pl < regexp-933131.data
#
# This rule is a stricter sibling of rule 933130.
SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?:HTTP_(?:ACCEPT(?:_(?:ENCODING|LANGUAGE|CHARSET))?|(?:X_FORWARDED_FO|REFERE)R|(?:USER_AGEN|HOS)T|CONNECTION|KEEP_ALIVE)|PATH_(?:TRANSLATED|INFO)|ORIG_PATH_INFO|QUERY_STRING|REQUEST_URI|AUTH_TYPE)" \
    "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',\
    ctl:auditLogParts=+E,\
    ver:'OWASP_CRS/3.3.2',\
    severity:'CRITICAL',\
    setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\
    setvar:'tx.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 ]
#
# Regexp generated from util/regexp-assemble/regexp-933161.data using Regexp::Assemble.
# See https://coreruleset.org/20190826/optimizing-regular-expressions/ for usage.
#
# Note that after assemble, PHP function syntax pre/postfix is added to the Regexp::Assemble
# output. Example: "@rx (?i)\bASSEMBLE_OUTPUT_HERE(?:\s|/\*.*\*/|//.*|#.*)*\(.*\)"
#
SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* "@rx (?i)\b(?:i(?:s(?:_(?:in(?:t(?:eger)?|finite)|n(?:u(?:meric|ll)|an)|(?:calla|dou)ble|s(?:calar|tring)|f(?:inite|loat)|re(?:source|al)|l(?:ink|ong)|a(?:rray)?|object|bool)|set)|n(?:(?:clud|vok)e|t(?:div|val))|(?:mplod|dat)e|conv)|s(?:t(?:r(?:(?:le|sp)n|coll)|at)|(?:e(?:rializ|ttyp)|huffl)e|i(?:milar_text|zeof|nh?)|p(?:liti?|rintf)|(?:candi|ubst)r|y(?:mlink|slog)|o(?:undex|rt)|leep|rand|qrt)|f(?:ile(?:(?:siz|typ)e|owner|pro)|l(?:o(?:atval|ck|or)|ush)|(?:rea|mo)d|t(?:ell|ok)|unction|close|gets|stat|eof)|c(?:h(?:o(?:wn|p)|eckdate|root|dir|mod)|o(?:(?:(?:nsta|u)n|mpac)t|sh?|py)|lose(?:dir|log)|(?:urren|ryp)t|eil)|e(?:x(?:(?:trac|i)t|p(?:lode)?)|a(?:ster_da(?:te|ys)|ch)|r(?:ror_log|egi?)|mpty|cho|nd)|l(?:o(?:g(?:1[0p])?|caltime)|i(?:nk(?:info)?|st)|(?:cfirs|sta)t|evenshtein|trim)|d(?:i(?:(?:skfreespac)?e|r(?:name)?)|e(?:fined?|coct)|(?:oubleva)?l|ate)|r(?:e(?:(?:quir|cod|nam)e|adlin[ek]|wind|set)|an(?:ge|d)|ound|sort|trim)|m(?:b(?:split|ereg)|i(?:crotime|n)|a(?:i[ln]|x)|etaphone|y?sql|hash)|u(?:n(?:(?:tain|se)t|iqid|link)|s(?:leep|ort)|cfirst|mask)|a(?:s(?:(?:se|o)rt|inh?)|r(?:sort|ray)|tan[2h]?|cosh?|bs)|t(?:e(?:xtdomain|mpnam)|a(?:int|nh?)|ouch|ime|rim)|h(?:e(?:ader(?:s_(?:lis|sen)t)?|brev)|ypot|ash)|p(?:a(?:thinfo|ck)|r(?:intf?|ev)|close|o[sw]|i)|g(?:et(?:t(?:ext|ype)|date)|mdate)|o(?:penlog|ctdec|rd)|b(?:asename|indec)|n(?:atsor|ex)t|k(?:sort|ey)|quotemeta|wordwrap|virtual|join)(?:\s|/\*.*\*/|//.*|#.*)*\(.*\)" \
    "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',\
    ctl:auditLogParts=+E,\
    ver:'OWASP_CRS/3.3.2',\
    severity:'CRITICAL',\
    setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\
    setvar:'tx.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',\
    ctl:auditLogParts=+E,\
    ver:'OWASP_CRS/3.3.2',\
    severity:'CRITICAL',\
    setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\
    setvar:'tx.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',\
    ctl:auditLogParts=+E,\
    ver:'OWASP_CRS/3.3.2',\
    severity:'CRITICAL',\
    setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\
    setvar:'tx.anomaly_score_pl3=+%{tx.critical_anomaly_score}'"


SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:933017,phase:1,pass,nolog,skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP"
SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:933018,phase:2,pass,nolog,skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP"
#
# -= Paranoia Level 4 =- (apply only when tx.executing_paranoia_level is sufficiently high: 4 or higher)
#



#
# -= Paranoia Levels Finished =-
#
SecMarker "END-REQUEST-933-APPLICATION-ATTACK-PHP"
