541 lines
22 KiB
Plaintext
541 lines
22 KiB
Plaintext
# ---------------------------------------------------------------
|
|
# Core ModSecurity Rule Set ver.2.2.9
|
|
# Copyright (C) 2006-2012 Trustwave All rights reserved.
|
|
#
|
|
# The OWASP ModSecurity Core Rule Set is distributed under
|
|
# Apache Software License (ASL) version 2
|
|
# Please see the enclosed LICENCE file for full details.
|
|
# ---------------------------------------------------------------
|
|
|
|
|
|
#
|
|
# Some protocol violations are common in application layer attacks.
|
|
# Validating HTTP requests eliminates a large number of application layer attacks.
|
|
#
|
|
# The purpose of this rules file is to enforce HTTP RFC requirements that state how
|
|
# the client is supposed to interact with the server.
|
|
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html
|
|
#
|
|
|
|
#
|
|
# Validate request line against the format specified in the HTTP RFC
|
|
#
|
|
# -=[ Rule Logic ]=-
|
|
#
|
|
# Uses rule negation against the regex for positive security. The regex specifies the proper
|
|
# construction of URI request lines such as:
|
|
#
|
|
# "http:" "//" host [ ":" port ] [ abs_path [ "?" query ]]
|
|
#
|
|
# It also outlines proper construction for CONNECT, OPTIONS and GET requests.
|
|
#
|
|
# -=[ References ]=-
|
|
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.2.1
|
|
# http://capec.mitre.org/data/definitions/272.html
|
|
#
|
|
SecRule REQUEST_LINE "!^(?i:(?:[a-z]{3,10}\s+(?:\w{3,7}?://[\w\-\./]*(?::\d+)?)?/[^?#]*(?:\?[^#\s]*)?(?:#[\S]*)?|connect (?:\d{1,3}\.){3}\d{1,3}\.?(?::\d+)?|options \*)\s+[\w\./]+|get /[^?#]*(?:\?[^#\s]*)?(?:#[\S]*)?)$"\
|
|
"msg:'Invalid HTTP Request Line',\
|
|
severity:'4',\
|
|
id:'960911',\
|
|
ver:'OWASP_CRS/2.2.9',\
|
|
rev:'2',\
|
|
maturity:'9',\
|
|
accuracy:'9',\
|
|
logdata:'%{request_line}',\
|
|
phase:1,\
|
|
block,\
|
|
t:none,\
|
|
tag:'OWASP_CRS/PROTOCOL_VIOLATION/INVALID_REQ',\
|
|
tag:'CAPEC-272',\
|
|
setvar:'tx.msg=%{rule.msg}',\
|
|
setvar:tx.anomaly_score=+%{tx.notice_anomaly_score},\
|
|
setvar:'tx.%{rule.id}-OWASP_CRS/PROTOCOL_VIOLATION/INVALID_REQ-%{matched_var_name}=%{matched_var}'"
|
|
|
|
|
|
#
|
|
# Identify Invalid URIs Blocked by Apache
|
|
#
|
|
# -=[ Rule Logic ]=-
|
|
#
|
|
# There are some request violations that Apache will handle internally, prior to the
|
|
# ModSecurity phase:1 POST-READ-REQUEST hook. For these requests, we can still get
|
|
# visibility by running a check in phase:5 logging to look for the Apache error msg.
|
|
#
|
|
# -=[ References ]=-
|
|
#
|
|
SecRule WEBSERVER_ERROR_LOG "@contains Invalid URI in request" \
|
|
"msg:'Apache Error: Invalid URI in Request.', \
|
|
severity:'4', \
|
|
id:'981227', \
|
|
ver:'OWASP_CRS/2.2.9', \
|
|
rev:'1', \
|
|
maturity:'9', \
|
|
accuracy:'9', \
|
|
logdata:'%{request_line}', \
|
|
phase:5, \
|
|
pass, \
|
|
t:none, \
|
|
tag:'OWASP_CRS/PROTOCOL_VIOLATION/INVALID_REQ', \
|
|
tag:'CAPEC-272', \
|
|
setvar:'tx.msg=%{rule.msg}', \
|
|
setvar:tx.anomaly_score=+%{tx.notice_anomaly_score}, \
|
|
setvar:'tx.%{rule.id}-OWASP_CRS/PROTOCOL_VIOLATION/INVALID_REQ-%{matched_var_name}=%{matched_var}'"
|
|
|
|
#
|
|
# Identify multipart/form-data name evasion attempts
|
|
#
|
|
# There are possible impedance mismatches between how
|
|
# ModSecurity interprets multipart file names and how
|
|
# a destination app server such as PHP might parse the
|
|
# Content-Disposition data:
|
|
#
|
|
# filename-parm := "filename" "=" value
|
|
#
|
|
# -=[ Rule Logic ]=-
|
|
# These rules check for the existence of the ' " ; = meta-characters in
|
|
# either the file or file name variables.
|
|
#
|
|
# -=[ References ]=-
|
|
# https://www.owasp.org/index.php/ModSecurity_CRS_RuleID-960000
|
|
# http://www.ietf.org/rfc/rfc2183.txt
|
|
#
|
|
SecRule FILES_NAMES|FILES "['\";=]" \
|
|
"msg:'Attempted multipart/form-data bypass', \
|
|
severity:'2', \
|
|
id:'960000', \
|
|
ver:'OWASP_CRS/2.2.9', \
|
|
rev:'1', \
|
|
maturity:'9', \
|
|
accuracy:'7', \
|
|
logdata:'%{matched_var}', \
|
|
phase:2, \
|
|
block, \
|
|
t:none,t:urlDecodeUni, \
|
|
tag:'OWASP_CRS/PROTOCOL_VIOLATION/INVALID_REQ', \
|
|
tag:'CAPEC-272', \
|
|
setvar:'tx.msg=%{rule.msg}', \
|
|
setvar:tx.anomaly_score=+%{tx.critical_anomaly_score}, \
|
|
setvar:'tx.%{rule.id}-OWASP_CRS/PROTOCOL_VIOLATION/INVALID_REQ-%{matched_var_name}=%{matched_var}'"
|
|
|
|
|
|
#
|
|
# Verify that we've correctly processed the request body.
|
|
#
|
|
# As a rule of thumb, when failing to process a request body
|
|
# you should reject the request (when deployed in blocking mode)
|
|
# or log a high-severity alert (when deployed in detection-only mode).
|
|
#
|
|
# -=[ Rule Logic ]=-
|
|
# Checks for the existence of the REQBODY_ERROR variable that is created
|
|
# by the request body processor if it encounters errors.
|
|
#
|
|
# -=[ References ]=-
|
|
# https://sourceforge.net/apps/mediawiki/mod-security/index.php?title=Reference_Manual#REQBODY_ERROR
|
|
#
|
|
SecRule REQBODY_ERROR "!@eq 0" \
|
|
"msg:'Failed to parse request body.', \
|
|
severity:'2', \
|
|
id:'960912', \
|
|
ver:'OWASP_CRS/2.2.9', \
|
|
rev:'1', \
|
|
maturity:'9', \
|
|
accuracy:'9', \
|
|
logdata:'%{REQBODY_ERROR_MSG}', \
|
|
phase:2, \
|
|
block, \
|
|
t:none, \
|
|
tag:'OWASP_CRS/PROTOCOL_VIOLATION/INVALID_REQ', \
|
|
tag:'CAPEC-272', \
|
|
setvar:'tx.msg=%{rule.msg}', \
|
|
setvar:tx.anomaly_score=+%{tx.critical_anomaly_score}, \
|
|
setvar:'tx.%{rule.id}-OWASP_CRS/PROTOCOL_VIOLATION/INVALID_REQ-%{matched_var_name}=%{matched_var}'"
|
|
|
|
|
|
#
|
|
# Strict Multipart Parsing Checks
|
|
#
|
|
# -=[ Rule Logic ]=-
|
|
# By default be strict with what we accept in the multipart/form-data
|
|
# request body. If the rule below proves to be too strict for your
|
|
# environment consider changing it to detection-only. You are encouraged
|
|
# _not_ to remove it altogether.
|
|
#
|
|
# -=[ References ]=-
|
|
# https://sourceforge.net/apps/mediawiki/mod-security/index.php?title=Reference_Manual#MULTIPART_STRICT_ERROR
|
|
#
|
|
SecRule MULTIPART_STRICT_ERROR "!@eq 0" \
|
|
"msg:'Multipart request body failed strict validation: \
|
|
PE %{REQBODY_PROCESSOR_ERROR}, \
|
|
BQ %{MULTIPART_BOUNDARY_QUOTED}, \
|
|
BW %{MULTIPART_BOUNDARY_WHITESPACE}, \
|
|
DB %{MULTIPART_DATA_BEFORE}, \
|
|
DA %{MULTIPART_DATA_AFTER}, \
|
|
HF %{MULTIPART_HEADER_FOLDING}, \
|
|
LF %{MULTIPART_LF_LINE}, \
|
|
SM %{MULTIPART_SEMICOLON_MISSING}, \
|
|
IQ %{MULTIPART_INVALID_QUOTING}, \
|
|
IH %{MULTIPART_INVALID_HEADER_FOLDING}, \
|
|
FLE %{MULTIPART_FILE_LIMIT_EXCEEDED}', \
|
|
severity:'2', \
|
|
id:'960914', \
|
|
ver:'OWASP_CRS/2.2.9', \
|
|
rev:'1', \
|
|
maturity:'8', \
|
|
accuracy:'7', \
|
|
phase:2, \
|
|
block, \
|
|
t:none, \
|
|
tag:'OWASP_CRS/PROTOCOL_VIOLATION/INVALID_REQ', \
|
|
tag:'CAPEC-272', \
|
|
setvar:'tx.msg=%{rule.msg}', \
|
|
setvar:tx.anomaly_score=+%{tx.critical_anomaly_score}, \
|
|
setvar:'tx.%{rule.id}-OWASP_CRS/PROTOCOL_VIOLATION/INVALID_REQ-%{matched_var_name}=%{matched_var}'"
|
|
|
|
|
|
#
|
|
# Multipart Unmatched Boundary Check
|
|
#
|
|
# -=[ Rule Logic ]=-
|
|
# Check for the MULTIPART_UNMATCHED_BOUNDARY flag and alert
|
|
#
|
|
# -=[ References ]=-
|
|
# https://sourceforge.net/apps/mediawiki/mod-security/index.php?title=Reference_Manual#MULTIPART_UNMATCHED_BOUNDARY
|
|
#
|
|
SecRule MULTIPART_UNMATCHED_BOUNDARY "!@eq 0" \
|
|
"msg:'Multipart parser detected a possible unmatched boundary.', \
|
|
severity:'2', \
|
|
id:'960915', \
|
|
ver:'OWASP_CRS/2.2.9', \
|
|
rev:'1', \
|
|
maturity:'8', \
|
|
accuracy:'8', \
|
|
phase:2, \
|
|
block, \
|
|
t:none, \
|
|
tag:'OWASP_CRS/PROTOCOL_VIOLATION/INVALID_REQ', \
|
|
tag:'CAPEC-272', \
|
|
setvar:'tx.msg=%{rule.msg}', \
|
|
setvar:tx.anomaly_score=+%{tx.critical_anomaly_score}, \
|
|
setvar:'tx.%{rule.id}-OWASP_CRS/PROTOCOL_VIOLATION/INVALID_REQ-%{matched_var_name}=%{matched_var}'"
|
|
|
|
|
|
#
|
|
# Accept only digits in content length
|
|
#
|
|
# -=[ Rule Logic ]=-
|
|
# This rule uses ModSecurity's rule negation against the regex meaning if the Content-Length header
|
|
# is NOT all digits, then it will match.
|
|
#
|
|
# -=[ References ]=-
|
|
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.13
|
|
#
|
|
SecRule REQUEST_HEADERS:Content-Length "!^\d+$" \
|
|
"msg:'Content-Length HTTP header is not numeric.',\
|
|
severity:'2',\
|
|
id:'960016',\
|
|
ver:'OWASP_CRS/2.2.9',\
|
|
rev:'1',\
|
|
maturity:'9',\
|
|
accuracy:'9',\
|
|
phase:1,\
|
|
block,\
|
|
logdata:'%{matched_var}',\
|
|
t:none,\
|
|
tag:'OWASP_CRS/PROTOCOL_VIOLATION/INVALID_HREQ',\
|
|
tag:'CAPEC-272',\
|
|
setvar:'tx.msg=%{rule.msg}',\
|
|
setvar:tx.anomaly_score=+%{tx.critical_anomaly_score},\
|
|
setvar:'tx.%{rule.id}-OWASP_CRS/PROTOCOL_VIOLATION/INVALID_HREQ-%{matched_var_name}=%{matched_var}'"
|
|
|
|
|
|
#
|
|
# Do not accept GET or HEAD requests with bodies
|
|
# HTTP standard allows GET requests to have a body but this
|
|
# feature is not used in real life. Attackers could try to force
|
|
# a request body on an unsuspecting web applications.
|
|
#
|
|
# -=[ Rule Logic ]=-
|
|
# This is a chained rule that first checks the Request Method. If it is a
|
|
# GET or HEAD method, then it checks for the existence of a Content-Length
|
|
# header. If the header exists and its payload is either not a 0 digit or not
|
|
# empty, then it will match.
|
|
#
|
|
# -=[ References ]=-
|
|
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.3
|
|
#
|
|
SecRule REQUEST_METHOD "^(?:GET|HEAD)$" \
|
|
"msg:'GET or HEAD Request with Body Content.',\
|
|
severity:'2',\
|
|
id:'960011',\
|
|
ver:'OWASP_CRS/2.2.9',\
|
|
rev:'1',\
|
|
maturity:'9',\
|
|
accuracy:'9',\
|
|
phase:1,\
|
|
block,\
|
|
logdata:'%{matched_var}',\
|
|
t:none,\
|
|
tag:'OWASP_CRS/PROTOCOL_VIOLATION/INVALID_HREQ',\
|
|
tag:'CAPEC-272',\
|
|
chain"
|
|
SecRule REQUEST_HEADERS:Content-Length "!^0?$"\
|
|
"t:none,\
|
|
setvar:'tx.msg=%{rule.msg}',\
|
|
setvar:tx.anomaly_score=+%{tx.critical_anomaly_score},\
|
|
setvar:'tx.%{rule.id}-OWASP_CRS/PROTOCOL_VIOLATION/INVALID_HREQ-%{matched_var_name}=%{matched_var}'"
|
|
|
|
|
|
#
|
|
# Require Content-Length to be provided with every POST request.
|
|
#
|
|
# -=[ Rule Logic ]=-
|
|
# This chained rule checks if the request method is POST, if so, it checks that a Content-Length
|
|
# header is also present.
|
|
#
|
|
# -=[ References ]=-
|
|
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.5
|
|
#
|
|
#SecRule REQUEST_METHOD "^POST$" \
|
|
# "msg:'POST request missing Content-Length Header.',\
|
|
# severity:'4',\
|
|
# id:'960012',\
|
|
# ver:'OWASP_CRS/2.2.9',\
|
|
# rev:'1',\
|
|
# maturity:'9',\
|
|
# accuracy:'9',\
|
|
# phase:1,\
|
|
# block,\
|
|
# logdata:'%{matched_var}',\
|
|
# t:none,\
|
|
# tag:'OWASP_CRS/PROTOCOL_VIOLATION/INVALID_HREQ',\
|
|
# tag:'CAPEC-272',\
|
|
# chain"
|
|
# SecRule &REQUEST_HEADERS:Content-Length "@eq 0" \
|
|
# "t:none,\
|
|
# setvar:'tx.msg=%{rule.msg}',\
|
|
# setvar:tx.anomaly_score=+%{tx.notice_anomaly_score},\
|
|
# setvar:'tx.%{rule.id}-OWASP_CRS/PROTOCOL_VIOLATION/INVALID_HREQ-%{matched_var_name}=%{matched_var}'"
|
|
|
|
|
|
#
|
|
# Deny inbound compressed content
|
|
# identity The default (identity) encoding; the use of no transformation whatsoever.
|
|
# This content-coding is used only in the Accept- Encoding header, and SHOULD NOT be
|
|
# used in the Content-Encoding header.
|
|
#
|
|
# -=[ Rule Logic ]=-
|
|
# This rule inspects the Content-Encoding request header to ensure that Identity
|
|
# is not specified.
|
|
#
|
|
# -=[ References ]=-
|
|
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html
|
|
#
|
|
SecRule REQUEST_HEADERS:Content-Encoding "^Identity$" \
|
|
"msg:'Invalid Use of Identity Encoding.',\
|
|
severity:'4',\
|
|
id:'960902',\
|
|
ver:'OWASP_CRS/2.2.9',\
|
|
rev:'2',\
|
|
maturity:'9',\
|
|
accuracy:'9',\
|
|
phase:1,\
|
|
block,\
|
|
logdata:'%{matched_var}',\
|
|
t:none,\
|
|
tag:'OWASP_CRS/PROTOCOL_VIOLATION/INVALID_HREQ',\
|
|
tag:'CAPEC-272',\
|
|
setvar:'tx.msg=%{rule.msg}',\
|
|
setvar:tx.anomaly_score=+%{tx.notice_anomaly_score},\
|
|
setvar:'tx.%{rule.id}-OWASP_CRS/PROTOCOL_VIOLATION/INVALID_HREQ-%{matched_var_name}=%{matched_var}'"
|
|
|
|
|
|
#
|
|
# Expect header is an HTTP/1.1 protocol feature
|
|
# Automated programs and bots often do not obey the HTTP RFC
|
|
#
|
|
# -=[ Rule Logic ]=-
|
|
# This chained rule looks for the Expect request header, and if it is found then it
|
|
# checks the HTTP protocol version supplied by the client. If it is version 1.0, the
|
|
# rule matches.
|
|
#
|
|
# -=[ References ]=-
|
|
# http://www.bad-behavior.ioerror.us/documentation/how-it-works/
|
|
#
|
|
SecRule REQUEST_HEADERS:Expect "@contains 100-continue" \
|
|
"msg:'Expect Header Not Allowed for HTTP 1.0.',\
|
|
severity:'5',\
|
|
id:'960022',\
|
|
ver:'OWASP_CRS/2.2.9',\
|
|
rev:'2',\
|
|
maturity:'7',\
|
|
accuracy:'9',\
|
|
phase:1,\
|
|
block,\
|
|
logdata:'%{matched_var}',\
|
|
t:none,\
|
|
tag:'OWASP_CRS/PROTOCOL_VIOLATION/INVALID_HREQ',\
|
|
tag:'CAPEC-272',\
|
|
chain"
|
|
SecRule REQUEST_PROTOCOL "@streq HTTP/1.0" \
|
|
"t:none,\
|
|
setvar:'tx.msg=%{rule.msg}',\
|
|
setvar:tx.anomaly_score=+%{tx.notice_anomaly_score},\
|
|
setvar:'tx.%{rule.id}-OWASP_CRS/PROTOCOL_VIOLATION/INVALID_HREQ-%{matched_var_name}=%{matched_var}'"
|
|
|
|
|
|
#
|
|
# Pragma Header requires a Cache-Control Header
|
|
# Automated programs and bots often do not obey the HTTP RFC
|
|
#
|
|
# -=[ Rule Logic ]=-
|
|
# This chained rule first checks for the existence of a Pragma request header. If it is found,
|
|
# then it checks for a corresponding Cache-Control header (as the HTTP 1.1 RFC states clients should submit
|
|
# one). If this is also missing, then it verifies the HTTP protocol version. If it is 1.1 then the rule
|
|
# matches.
|
|
#
|
|
# -=[ References ]=-
|
|
# http://www.bad-behavior.ioerror.us/documentation/how-it-works/
|
|
#
|
|
SecRule &REQUEST_HEADERS:Pragma "@eq 1" "chain,phase:2,rev:'2',ver:'OWASP_CRS/2.2.9',maturity:'6',accuracy:'8',t:none,block,msg:'Pragma Header requires Cache-Control Header for HTTP/1.1 requests.',severity:'5',id:'960020',tag:'OWASP_CRS/PROTOCOL_VIOLATION/INVALID_HREQ'"
|
|
SecRule REQUEST_HEADERS:Pragma "@strmatch no-cache" "chain"
|
|
SecRule &REQUEST_HEADERS:Cache-Control "@eq 0" "chain"
|
|
SecRule REQUEST_PROTOCOL "@streq HTTP/1.1" "setvar:'tx.msg=%{rule.msg}',setvar:tx.anomaly_score=+%{tx.notice_anomaly_score},setvar:tx.%{rule.id}-OWASP_CRS/PROTOCOL_VIOLATION/INVALID_HREQ-%{matched_var_name}=%{matched_var}"
|
|
|
|
#
|
|
# Range Header Checks
|
|
#
|
|
# 1. Range Header exists and begins with 0 - normal browsers don't do this.
|
|
# Automated programs and bots often do not obey the HTTP RFC
|
|
#
|
|
# -=[ Rule Logic ]=-
|
|
# This rule inspects the Range request header to see if it starts with 0.
|
|
#
|
|
# -=[ References ]=-
|
|
# http://www.bad-behavior.ioerror.us/documentation/how-it-works/
|
|
#
|
|
# 2. Per RFC 2616 -
|
|
# "If the last-byte-pos value is present, it MUST be greater than or equal to the first-byte-pos in that byte-range-spec,
|
|
# or the byte- range-spec is syntactically invalid."
|
|
# -=[ Rule Logic ]=-
|
|
# This rule compares the first and second byte ranges and flags when the first value is greater than the second.
|
|
#
|
|
# -=[ References ]=-
|
|
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
|
|
# http://seclists.org/fulldisclosure/2011/Aug/175
|
|
#
|
|
# 3. Identifies an excessive number of byte range fields within one request
|
|
#
|
|
SecRule REQUEST_HEADERS:Range "@beginsWith bytes=0-" "phase:2,rev:'2',ver:'OWASP_CRS/2.2.9',maturity:'6',accuracy:'8',t:none,block,msg:'Range: field exists and begins with 0.',logdata:'%{matched_var}',severity:'4',id:'958291',tag:'OWASP_CRS/PROTOCOL_VIOLATION/INVALID_HREQ',setvar:'tx.msg=%{rule.msg}',setvar:tx.anomaly_score=+%{tx.warning_anomaly_score},setvar:tx.%{rule.id}-OWASP_CRS/PROTOCOL_VIOLATION/INVALID_HREQ-%{matched_var_name}=%{matched_var}"
|
|
|
|
SecRule REQUEST_HEADERS:Range|REQUEST_HEADERS:Request-Range "(\d+)\-(\d+)\," "chain,capture,phase:2,rev:'2',ver:'OWASP_CRS/2.2.9',maturity:'6',accuracy:'8',t:none,block,msg:'Range: Invalid Last Byte Value.',logdata:'%{matched_var}',severity:'4',id:'958230',tag:'OWASP_CRS/PROTOCOL_VIOLATION/INVALID_HREQ',setvar:'tx.msg=%{rule.msg}',setvar:tx.anomaly_score=+%{tx.warning_anomaly_score},setvar:tx.%{rule.id}-OWASP_CRS/PROTOCOL_VIOLATION/INVALID_HREQ-%{matched_var_name}=%{matched_var}"
|
|
SecRule TX:2 "!@ge %{tx.1}"
|
|
|
|
SecRule REQUEST_HEADERS:Range|REQUEST_HEADERS:Request-Range "^bytes=(\d+)?\-(\d+)?\,\s?(\d+)?\-(\d+)?\,\s?(\d+)?\-(\d+)?\,\s?(\d+)?\-(\d+)?\,\s?(\d+)?\-(\d+)?\," "phase:2,capture,rev:'2',ver:'OWASP_CRS/2.2.9',maturity:'6',accuracy:'8',t:none,block,msg:'Range: Too many fields',logdata:'%{matched_var}',severity:'4',id:'958231',tag:'OWASP_CRS/PROTOCOL_VIOLATION/INVALID_HREQ',setvar:'tx.msg=%{rule.msg}',setvar:tx.anomaly_score=+%{tx.warning_anomaly_score},setvar:tx.%{rule.id}-OWASP_CRS/PROTOCOL_VIOLATION/INVALID_HREQ-%{matched_var_name}=%{matched_var}"
|
|
|
|
|
|
#
|
|
# Broken/Malicous clients often have duplicate or conflicting headers
|
|
# Automated programs and bots often do not obey the HTTP RFC
|
|
#
|
|
# -=[ Rule Logic ]=-
|
|
# This rule inspects the Connection header and looks for duplicates of the
|
|
# keep-alive and close options.
|
|
#
|
|
# -=[ References ]=-
|
|
# http://www.bad-behavior.ioerror.us/documentation/how-it-works/
|
|
#
|
|
SecRule REQUEST_HEADERS:Connection "\b(keep-alive|close),\s?(keep-alive|close)\b" "phase:2,rev:'2',ver:'OWASP_CRS/2.2.9',maturity:'6',accuracy:'8',t:none,block,msg:'Multiple/Conflicting Connection Header Data Found.',logdata:'%{matched_var}',id:'958295',tag:'OWASP_CRS/PROTOCOL_VIOLATION/INVALID_HREQ',severity:'4',setvar:'tx.msg=%{rule.msg}',setvar:tx.anomaly_score=+%{tx.warning_anomaly_score},setvar:tx.%{rule.id}-OWASP_CRS/PROTOCOL_VIOLATION/INVALID_HREQ-%{matched_var_name}=%{matched_var}"
|
|
|
|
#
|
|
# Check URL encodings
|
|
#
|
|
# -=[ Rule Logic ]=-
|
|
# There are two different chained rules. We need to separate them as we are inspecting two
|
|
# different variables - REQUEST_URI and REQUEST_BODY. For REQUEST_BODY, we only want to
|
|
# run the @validateUrlEncoding operator if the content-type is application/x-www-form-urlencoding.
|
|
#
|
|
# -=[ References ]=-
|
|
# http://www.ietf.org/rfc/rfc1738.txt
|
|
#
|
|
SecRule REQUEST_URI "\%((?!$|\W)|[0-9a-fA-F]{2}|u[0-9a-fA-F]{4})" \
|
|
"chain,phase:2,rev:'2',ver:'OWASP_CRS/2.2.9',maturity:'6',accuracy:'8',t:none,block,msg:'URL Encoding Abuse Attack Attempt',id:'950107',tag:'OWASP_CRS/PROTOCOL_VIOLATION/EVASION',severity:'4'"
|
|
SecRule REQUEST_URI "@validateUrlEncoding" "setvar:'tx.msg=%{rule.msg}',setvar:tx.anomaly_score=+%{tx.warning_anomaly_score},setvar:tx.%{rule.id}-OWASP_CRS/PROTOCOL_VIOLATION/EVASION-%{matched_var_name}=%{matched_var}"
|
|
|
|
SecRule ARGS "\%((?!$|\W)|[0-9a-fA-F]{2}|u[0-9a-fA-F]{4})" \
|
|
"phase:2,rev:'2',ver:'OWASP_CRS/2.2.9',maturity:'6',accuracy:'8',t:none,block,msg:'Multiple URL Encoding Detected',id:'950109',tag:'OWASP_CRS/PROTOCOL_VIOLATION/EVASION',severity:'4',setvar:'tx.msg=%{rule.msg}',setvar:tx.anomaly_score=+%{tx.warning_anomaly_score},setvar:tx.%{rule.id}-OWASP_CRS/PROTOCOL_VIOLATION/EVASION-%{matched_var_name}=%{matched_var}"
|
|
|
|
SecRule REQUEST_HEADERS:Content-Type "^(application\/x-www-form-urlencoded|text\/xml)(?:;(?:\s?charset\s?=\s?[\w\d\-]{1,18})?)??$" \
|
|
"chain,phase:2,rev:'2',ver:'OWASP_CRS/2.2.9',maturity:'6',accuracy:'8',t:none,block,msg:'URL Encoding Abuse Attack Attempt',id:'950108',tag:'OWASP_CRS/PROTOCOL_VIOLATION/EVASION',severity:'4'"
|
|
SecRule REQUEST_BODY|XML:/* "\%((?!$|\W)|[0-9a-fA-F]{2}|u[0-9a-fA-F]{4})" "chain"
|
|
SecRule REQUEST_BODY|XML:/* "@validateUrlEncoding" "setvar:'tx.msg=%{rule.msg}',setvar:tx.anomaly_score=+%{tx.warning_anomaly_score},setvar:tx.%{rule.id}-OWASP_CRS/PROTOCOL_VIOLATION/EVASION-%{matched_var_name}=%{matched_var}"
|
|
|
|
|
|
#
|
|
# Check UTF enconding
|
|
# We only want to apply this check if UTF-8 encoding is actually used by the site, otherwise
|
|
# it will result in false positives.
|
|
#
|
|
# -=[ Rule Logic ]=-
|
|
# This chained rule first checks to see if the admin has set the TX:CRS_VALIDATE_UTF8_ENCODING
|
|
# variable in the modsecurity_crs_10_config.conf file.
|
|
#
|
|
SecRule TX:CRS_VALIDATE_UTF8_ENCODING "@eq 1" "chain,phase:2,rev:'2',ver:'OWASP_CRS/2.2.9',maturity:'6',accuracy:'8',t:none,block,msg:'UTF8 Encoding Abuse Attack Attempt',id:'950801',tag:'OWASP_CRS/PROTOCOL_VIOLATION/EVASION',severity:'4'"
|
|
SecRule REQUEST_FILENAME|ARGS|ARGS_NAMES "@validateUtf8Encoding" "setvar:'tx.msg=%{rule.msg}',setvar:tx.anomaly_score=+%{tx.warning_anomaly_score},setvar:tx.%{rule.id}-OWASP_CRS/PROTOCOL_VIOLATION/EVASION-%{matched_var_name}=%{matched_var}"
|
|
|
|
|
|
#
|
|
# Disallow use of full-width unicode as decoding evasions my be possible.
|
|
#
|
|
# -=[ Rule Logic ]=-
|
|
# This rule looks for full-width encoding by looking for %u following by 2 f characters
|
|
# and then 2 hex characters.
|
|
#
|
|
# -=[ References ]=-
|
|
# http://www.kb.cert.org/vuls/id/739224
|
|
#
|
|
SecRule REQUEST_URI|REQUEST_BODY "\%u[fF]{2}[0-9a-fA-F]{2}" \
|
|
"t:none,phase:2,rev:'2',ver:'OWASP_CRS/2.2.9',maturity:'6',accuracy:'8',block,msg:'Unicode Full/Half Width Abuse Attack Attempt',id:'950116',severity:'4',setvar:'tx.msg=%{rule.msg}',setvar:tx.anomaly_score=+%{tx.warning_anomaly_score},setvar:tx.%{rule.id}-OWASP_CRS/PROTOCOL_VIOLATION/EVASION-%{matched_var_name}=%{matched_var}"
|
|
|
|
#
|
|
# Proxy access attempt
|
|
# NOTE Apache blocks such access by default if not set as a proxy. The rule is
|
|
# included in case Apache proxy is misconfigured.
|
|
# NOTE There are some clients (mobile devices) that will send a full URI even when connecting to
|
|
# your local application and this rule allows it.
|
|
# NOTE Need to have UseCanonicalName On in Apache config to properly set the SERVER_NAME variable.
|
|
# If you have set UseCanonicalName, the you can uncomment this rule.
|
|
#
|
|
# -=[ Rule Logic ]=-
|
|
# This chained rule first inspects the URI to see if a full domain name is specified.
|
|
# If it is, then this data is compared against the Cononical SERVER_NAME. If it does
|
|
# not match, then the client is making a request for an off-site location.
|
|
#
|
|
#SecRule REQUEST_URI_RAW "^\w+:/" "chain,phase:2,rev:'2',ver:'OWASP_CRS/2.2.9',maturity:'6',accuracy:'8',t:none,block,msg:'Proxy access attempt',severity:'3',id:'960014',tag:'OWASP_CRS/PROTOCOL_VIOLATION/PROXY_ACCESS'"
|
|
#SecRule MATCHED_VAR "!@beginsWith http://%{SERVER_NAME}" "setvar:'tx.msg=%{rule.msg}',setvar:tx.anomaly_score=+%{tx.error_anomaly_score},setvar:tx.%{rule.id}-OWASP_CRS/PROTOCOL_VIOLATION/PROXY_ACCESS-%{matched_var_name}=%{matched_var}"
|
|
|
|
|
|
#
|
|
# Restrict type of characters sent
|
|
# NOTE In order to be broad and support localized applications this rule
|
|
# only validates that NULL Is not used.
|
|
#
|
|
# The strict policy version also validates that protocol and application
|
|
# generated fields are limited to printable ASCII.
|
|
#
|
|
# -=[ Rule Logic ]=-
|
|
# This rule uses the @validateByteRange operator to look for Nul Bytes.
|
|
# If you set Paranoid Mode - it will check if your application use the range 32-126 for parameters.
|
|
#
|
|
# -=[ References ]=-
|
|
# http://i-technica.com/whitestuff/asciichart.html
|
|
#
|
|
|
|
SecRule ARGS|ARGS_NAMES|REQUEST_HEADERS|!REQUEST_HEADERS:Referer "@validateByteRange 1-255" \
|
|
"phase:2,rev:'2',ver:'OWASP_CRS/2.2.9',maturity:'9',accuracy:'9',block,msg:'Invalid character in request',id:'960901',tag:'OWASP_CRS/PROTOCOL_VIOLATION/EVASION',severity:'3',t:none,t:urlDecodeUni,setvar:'tx.msg=%{rule.msg}',setvar:tx.anomaly_score=+%{tx.error_anomaly_score},setvar:tx.%{rule.id}-OWASP_CRS/PROTOCOL_VIOLATION/EVASION-%{matched_var_name}=%{matched_var}"
|
|
|
|
SecRule TX:PARANOID_MODE "@eq 1" "chain,phase:2,rev:'2',ver:'OWASP_CRS/2.2.9',maturity:'8',accuracy:'7',block,msg:'Invalid character in request',id:'960018',tag:'OWASP_CRS/PROTOCOL_VIOLATION/EVASION',severity:'3',t:none,t:urlDecodeUni"
|
|
SecRule REQUEST_URI|REQUEST_BODY|REQUEST_HEADERS_NAMES|REQUEST_HEADERS|!REQUEST_HEADERS:Referer|TX:HPP_DATA \
|
|
"@validateByteRange 32-126" \
|
|
"t:urlDecodeUni,setvar:'tx.msg=%{rule.msg}',setvar:tx.anomaly_score=+%{tx.error_anomaly_score},setvar:tx.%{rule.id}-OWASP_CRS/PROTOCOL_VIOLATION/EVASION-%{matched_var_name}=%{matched_var}"
|
|
|