WAF owasp检测原理与规则解析
一 规则原理
1.1 规则模式
OWASP V3版本核心规则集目前支持两种配置模式:
异常评分模式(默认)和 独自控制模式
独自控制模式,此模式是V2版本规则集的默认模式,它的工作方式是,只要有一条规则匹配成功,便拦截此次访问,审计日志中也只会记录第一次检测到威胁的规则信息。(wafnginx使用异常评分模式,在此不做展开)
异常评分模式,也可称为”协同检测模式”,在此模式下,当检测到威胁时,并不会直接阻断此次请求,而是向下继续进行规则匹配,每个匹配成功的规则都会增加”异常分数”,在对请求数据检测结束时,以及对返回数据检测结束时,都会对异常分数的总和进行判断,如果大于设置的阈值,才会进行阻断动作,并向客户端返回403代码,审计日志中也会记录此次访问中所有匹配成功的规则信息。
1.1.1 CRS 中的异常评分模式的工作原理如下:
1、执行所有请求规则
2、使用入站异常分数阈值做出阻止决策
3、执行所有响应规则
4、使用出站异常分数阈值做出阻止决策
使用异常评分模式时,可以配置以下设置:
异常分数阈值、严重性级别、早期阻止
owasp crs应用于waf时,通过crs-setup.conf或REQUEST-901-INITIALIZATION.conf
文件进行配置。
1.1.2 阈值配置
严重性默认评分
Severity Level |
Default Anomaly Score |
CRITICAL |
5 |
ERROR |
4 |
WARNING |
3 |
NOTICE |
2 |
CRS使用可配置的异常计分模型,每条触发的规则都会增加异常分数,如果分数超过配置的异常阈值,则事务被阻塞,异常级别如下:
Critical:异常得分5,表示可能应用程序攻击,主要由93x 94x文件生成。
Error:异常得分4,表示可能数据泄露,主要有95x文件生成,暂不支持nginx和nginx plus。
Warning:异常得分3,表示可能恶意客户端,主要由91x文件生成的。
Notice:异常得分2,表示可能违反协议,主要由92x文件生成。
默认情况下,CRS阻塞所有异常值为5或更高的入站流量,意味着任何引发事务的关键规则都将被丢弃,三次或更多的通知级违规也会导致事务被阻塞。
1.2 Paranoia level
偏执等级(paranoia level)定义了检测规则的激进程度,越高级别出现误报的可能性越高,但恶意攻击检测率越高。较高的偏执级别使攻击者更难不被发现,然而,这是以更多的误报和资源消耗为代价的。
PL等级 |
描述 |
1 |
基线安全性,只需最少地消除误报。这是适用于在 Internet 上运行的大部分HTTP 服务。 |
2 |
当涉及真实用户数据时,这些规则是足够的。例如一个在线商店,预计会遇到误报并学习如何消除它们。 |
3 |
网上银行级别的安全性,有很多误报。从项目的角度来看,这里接受和预期会出现误报,因此学习如何编写规则排除项非常重要。 |
4 |
最高级别保护。使用风险自负:准备好面对大量误报。 |
PL等级和 CRS 异常评分(CRS 异常阈值/限制)是两个完全不同的东西,没有直接联系。PL级别控制启用的规则数量,而异常阈值定义在阻止请求之前可以触发的规则数量
1.3 误报处理
|
排除整个规则/标记 |
从规则/标记中排除特定变量 |
配置时 |
SecRuleRemoveById* SecRuleRemoveByTag |
SecRuleUpdateTargetById SecRuleUpdateTargetByTag |
运行时 |
ctl:ruleRemoveById** ctl:ruleRemoveByTag |
ctl:ruleRemoveTargetById ctl:ruleRemoveTargetByTag |
大多数 configure-time 规则排除指令都对使用正则表达式提供了一定程度的支持。例如,这样就可以从规则中排除动态命名的变量。支持正则表达式的指令包括:
-
SecRuleRemoveByTag
-
正则表达式用于标签匹配。例如,将同时匹配 “attack-injection-generic” 和 “attack-injection-php”。SecRuleRemoveByTag "injection"
-
SecRuleRemoveByMsg
-
正则表达式用于消息匹配。例如,将同时匹配“OS File Access Attempt”和“Restricted File Access Attempt”。SecRuleRemoveByMsg "File Access"
-
SecRuleUpdateTargetById、SecRuleUpdateTargetByTag SecRuleUpdateTargetByMsg
-
可以选择在目标规范中使用正则表达式,方法是将正则表达式括在正斜杠中。这对于处理动态命名的变量很有用,如下所示:
-
SecRuleUpdateTargetById 942440 "!REQUEST_COOKIES:/^uid_.*/".
-
此示例将从规则 942440 中排除名为“uid_0123456”、“uid_6543210”等的请求 Cookie。
二 id分类
2.1 id范围
ID 范围 |
预留对象 |
1-99,999 |
保留供本地 (内部) 使用。按需使用,但不要将此范围用于分发给其他人的规则。 |
100,000–199,999 |
保留用于 Oracle 发布的规则 |
200,000–299,999 |
保留用于已发布的规则 Comodo |
300,000-399,999 |
保留用于在 gotroot.com 上发布的规则 |
400,000–419,999 |
未使用(可预订) |
420,000-429,999 |
保留给 ScallyWhack |
430,000–439,999 |
保留给 Flameeye 发布的规则 |
440,000-599,999 |
未使用(可预订) |
600,000-699,999 |
预留对象Akamai 使用 |
700,000-799,999 |
保留给 Ivan Ristic |
900,000-999,999 |
保留用于 OWASP CRS 项目 |
1,000,000-1,009,999 |
保留用于 Redhat 安全团队发布的规则 |
1,010,000-1,999,999 |
未使用(可预订) |
2,000,000-2,999,999 |
保留给 Trustwave 的 SpiderLab 研究团队的规则 |
3,000,000-3,999,999 |
保留供 Akamai 使用 |
4,000,000-4,099,999 |
由 AviNetworks 使用时保留 |
4,100,000-4,199,999 |
Fastly 正在使用的保留 |
4,200,000-8,999,999 |
未使用(可预订) |
9,000,000-9,999,999 |
保留用于 OWASP CRS 项目 |
10,000,000-89,999,999 |
未使用(可预订) |
99,000,000-99,099,999 |
预留对象由 Microsoft 使用 |
2.2 crs(core rule set)规则
2.2.1 检测规则功能分类
CRS使用可配置的异常计分模型,每条触发的规则都会增加异常分数,如果分数超过配置的异常阈值,则事务被阻塞,异常级别如下:
Critical:异常得分5,表示可能应用程序攻击,主要由93x 94x文件生成。
Error:异常得分4,表示可能数据泄露,主要有95x文件生成,暂不支持nginx和nginx plus。
Warning:异常得分3,表示可能恶意客户端,主要由91x文件生成的。
Notice:异常得分2,表示可能违反协议,主要由92x文件生成。
默认情况下,CRS阻塞所有异常值为5或更高的入站流量,意味着任何引发事务的关键规则都将被丢弃,三次或更多的通知级违规也会导致事务被阻塞。
Rule File |
Description |
REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example |
添加例外 |
REQUEST-901-INITIALIZATION.conf |
初始化 |
REQUEST-903.9001-DRUPAL-EXCLUSION-RULES.conf |
消除DRUPAL安装时误报 |
REQUEST-903.9002-WORDPRESS-EXCLUSION-RULES.conf |
消除WORDPRESS安装时误报 |
REQUEST-903.9003-NEXTCLOUD-EXCLUSION-RULES.conf |
消除NEXTCLOUD安装时误报 |
REQUEST-903.9004-DOKUWIKI-EXCLUSION-RULES.conf |
消除DOKUWIKI安装时误报 |
REQUEST-903.9005-CPANEL-EXCLUSION-RULES.conf |
消除CPANEL安装时误报 |
REQUEST-903.9006-XENFORO-EXCLUSION-RULES.conf |
消除XENFORO安装时误报 |
REQUEST-910-IP-REPUTATION.conf |
检测本地站点或全球站点上参与恶意活动的 IP 的流量 |
REQUEST-912-DOS-PROTECTION.conf |
dos攻击检测 |
REQUEST-913-SCANNER-DETECTION.conf |
扫描检测 |
REQUEST-920-PROTOCOL-ENFORCEMENT.conf |
非法请求检测 |
REQUEST-921-PROTOCOL-ATTACK.conf |
针对 HTTP 协议本身的特定攻击检测 |
REQUEST-930-APPLICATION-ATTACK-LFI.conf |
|
REQUEST-931-APPLICATION-ATTACK-RFI.conf |
这些规则尝试检测用户何时尝试将远程资源包含到将要执行的 Web 应用程序中。利用此类攻击可能会导致 Web 应用程序或服务器受到威胁。 |
REQUEST-932-APPLICATION-ATTACK-RCE.conf |
远程命令执行检测 |
REQUEST-933-APPLICATION-ATTACK-PHP.conf |
PHP注入检测 |
REQUEST-934-APPLICATION-ATTACK-NODEJS.conf |
不安全的反序列化与RCE签名检测 |
REQUEST-941-APPLICATION-ATTACK-XSS.conf |
xss攻击检测 |
REQUEST-942-APPLICATION-ATTACK-SQLI.conf |
sql注入检测 |
REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION.conf |
会话固定攻击 |
REQUEST-944-APPLICATION-ATTACK-JAVA.conf |
JAVA相关漏洞利用检测 |
REQUEST-949-BLOCKING-EVALUATION.conf |
这些规则为给定请求提供基于异常的阻止 |
RESPONSE-950-DATA-LEAKAGES.conf |
这些规则可以防止通常可能发生的数据泄漏 |
RESPONSE-951-DATA-LEAKAGES-SQL.conf |
这些规则可以防止后端 SQL Server 可能发生的数据泄漏。通常,这些表示存在 SQL 注入问题。 |
RESPONSE-952-DATA-LEAKAGES-JAVA.conf |
这些规则可以防止由于 Java 而可能发生的数据泄漏 |
RESPONSE-953-DATA-LEAKAGES-PHP.conf |
这些规则可以防止由于 PHP 而可能发生的数据泄漏 |
RESPONSE-954-DATA-LEAKAGES-IIS.conf |
这些规则可防止由于 Microsoft IIS 而可能发生的数据泄漏 |
RESPONSE-959-BLOCKING-EVALUATION.conf |
异常检测阻断 |
RESPONSE-980-CORRELATION.conf |
出入站相关性检测 |
RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf.example |
添加例外 |
2.2.2 crs规则语法
SecRule VARIABLES "OPERATOR" "TRANSFORMATIONS,ACTIONS"
例子:
SecRule REQUEST_URI "@streq /index.php" "id:1,phase:1,t:lowercase,deny"
SecRule 由 4 个部分组成:
-
变量(Variables) - 指示 ModSecurity 在何处查找(有时称为 Targets)
-
运算符(Operators) - 指示 ModSecurity 何时触发匹配
-
转换(Transformations) - 指示 ModSecurity 如何规范化变量数据
-
动作(Actions) - 指示 ModSecurity 在规则匹配时如何响应
有 6 个不同类别的105 个变量,一些例子 包括:
-
请求变量 - ARGS、REQUEST_HEADERS REQUEST_COOKIES
-
响应变量 - RESPONSE_HEADERS、RESPONSE_BODY
-
服务器变量 - REMOTE_ADDR、AUTH_TYPE
-
时间变量 - TIME、TIME_EPOCH TIME_HOUR
-
集合变量 - TX、IP、SESSION、GEO
-
其他变量 - HIGHEST_SEVERITY、MATCHED_VAR
有 4 个不同类别的36 个运算符,一些示例 包括:
-
字符串运算符 - rx、pm、beginsWith、contains、endsWith、 streq,within
-
数值运算符 - eq、ge、gt、le、lt
-
验证运算符 - validateByteRange、validateUrlEncoding、 validateSchema
-
其他运算符 - rbl、geoLookup、inspectFile、verifyCC
有 6 个不同类别的35 个变换函数, 一些示例包括:
-
防规避函数 - lowercase、normalisePath、removeNulls、 replaceComments, compressWhitespace
-
解码函数 - base64Decode、hexDecode、jsDecode、 urlDecodeUni
-
编码函数 - base64Encode、hexEncode
-
哈希函数 - sha1、md5
有 6 个不同类别的47 个动作,一些例子 包括:
-
破坏性操作 - block、drop、deny、proxy
-
流操作 - chain、skip、skipAfter
-
元数据操作 - phase、id、msg、severity、tag
-
变量操作 - capture、setvar、initcol
-
日志记录操作 - log、auditlog、nolog、sanitiseArg
-
其他操作 - ctl、multiMatch、exec、pause、append/prepend
三 libinjection使用
libinjection基于c写的开源库用于检测sql注入和xss攻击,sql注入检测通过对用户输入进行词法分析生成指纹规则,然后通过二分查找算法,在特征库中进行匹配。
Modsecurity已集成libinjection库,涉及sql注入检测、xss检测会使用此库。
使用方法:在规则的运算部分(operators)使用@detectSQLi、@detectXSS
例如:
SecRule REQUEST_URI "@detectSQLi" "id:152"
SecRule REQUEST_BODY "@detectXSS" "id:12345,log,deny"
3.1 sql注入检测
从流程图上看,libinjection首先是初始化issqlii变量,接着设置数据结构并初始化变量state,libinjection_sqli_init()函数将初始化SQL检测所需的结构体,之后通过libinjection_is_sqli()函数进行具体分析,如果存在issqli,则将SQL注入识别特征复制进fingerprint变量并返回,如果不存在则将fingerprint变量设置为空并返回。
libinjection_sqli_init()函数的主要工作是将SQL注入识别特征码(指纹)加载进结构体,并完成各种内置变量的初始化。libinjection_is_sqli()的处理流程如下:
1.判断用户输入的字符串长度是否合法,为零则返回FALSE。(即没有发现SQL注入)
2.执行SQL注入识别函数(libinjection_sqli_fingerprint,无引号,标准SQL语法),获取字符串识别特征码
3.执行结构体内的查询函数(这里为libinjection_sqli_lookup_word,二分查找算法),对比第二步获取的识别特征是否与SQL注入识别特征匹配。
4.如果第三步发现SQL注入特征匹配结果为真,则返回true,并将SQL注入识别特征匹配到的fingerprint写入结构体,
5.如果检测失败,则调用reparse_as_mysql()函数判断是否存在“(dash-dash-[notwhite]) 注释”或“'#' 运算符号”,如果存在则再次执行SQL识别函数(libinjection_sqli_fingerprint,无引号,MYSQL语法),
6. 同时执行结构体的分析函数(libinjection_sqli_lookup_word,二分查找算法)进行特征匹配检测,如果结果为真,则返回true,并将SQL注入识别特征匹配到的fingerprint写入结构体。
7.如果前面的判断没有返回结果,将扫描参数(即用户输入的字符串)查找是否存在单引号。如果为真接着重复上述检测步骤。
8.如果前面的判断依旧没有返回结果,将扫描参数(即用户输入的字符串)查找是否存
在双引号。如果为真则接着执行SQL注入识别函数(libinjection_sqli_fingerprint,双引号,MYSQL语法)同时执行结构体的分析函数(libinjection_sqli_lookup_word,二分查找算法)进行特征匹配检测结果为真,则返回true,并将SQL注入识别特征匹配到的fingerprint写入结构体。
3.2 xss检测
src/operators/detect_xss.cc
通过libinjection_xss接口调用libinjection库做检测,具体检测逻辑如下:
src/libinjection_xss.c
int libinjection_xss(const char* s, size_t len)
判断字符串s是不是xss语句,返回1是xss攻击,返回0不是。从5个角度进行判断
libinjection_is_xss(s, len, DATA_STATE)
libinjection_is_xss(s, len, VALUE_NO_QUOTE)
libinjection_is_xss(s, len, VALUE_SINGLE_QUOTE)
libinjection_is_xss(s, len, VALUE_DOUBLE_QUOTE)
libinjection_is_xss(s, len, VALUE_BACK_QUOTE)
判断流程:
libinjection_h5_init 初始化阶段
libinjection_h5_next 核心处理阶段 内置回调函数 给匹配串打标签
h5.token_type == DOCTYPE --> 1
h5.token_type == TAG_NAME_OPEN --> is_black_tag 触发黑标签-->1
h5.token_type == ATTR_NAME --> is_black_attr 还需继续判断 触发黑属性
h5.token_type == ATTR_VALUE -->
TYPE_BLACK --> 1
TYPE_STYLE --> 1
TYPE_BLACK --> is_black_url 触发黑URL —>1
TYPE_ATTR_INDIRECT --> is_black_attr 不是 TYPE_NONE—>1
h5.token_type == TAG_COMMENT -->
` --> 1
[if || xml --> 1
IMPORT || ENTITY --> 1
四 REQUEST-941-APPLICATION-ATTACK-XSS 规则解读
4.1 什么是xss
XSS (Cross-site scripting)攻击,即跨站脚本攻击。攻击者通过在受害者的浏览器中注入恶意代码,攻击受害者的登录凭证、盗取敏感信息或控制受害者的会话等。
XSS攻击可以分为三种类型:反射型XSS攻击、存储型XSS攻击以及DOM型XSS攻击。
反射型XSS攻击是将攻击脚本注入到URL中,服务器解析时将注入代码反射到浏览器中,从而实现攻击目的。
存储型XSS攻击是攻击者将恶意脚本代码提交到受害网站的数据库中,当其他用户浏览包含该恶意脚本链接的页面时,就会执行该脚本,从而导致攻击者的目的得以实现。
DOM 型 XSS 攻击则是一种利用 DOM 基于 HTML 解析过程中的安全漏洞进行的跨站攻击,攻击者通过篡改网页中的 DOM 元素和属性,注入恶意代码从而窃取用户的敏感信息或实施其他违法操作。
4.2 检测原理
REQUEST-941-APPLICATION-ATTACK-XSS 规则集专注于识别和防御跨站脚本(XSS)攻击。XSS 攻击允许攻击者将恶意脚本注入到正常的页面中,这些脚本可以访问浏览器中的 cookie、session tokens 或其他敏感网站信息,以及进行恶意跳转等行为。
主要分为两个PL级别的检测:
941100: PL1 : REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|
REQUEST_COOKIES_NAMES|REQUEST_HEADERS:User-Agent|
ARGS_NAMES|ARGS|XML:/*
941101: PL2 : REQUEST_HEADERS:Referer
PL1检测起始id为941100,检测项为请求体中cookies、cookies name、User-Agent请求头、请求参数名称、请求参数、xml,PL2起始id为941101,检测项为referer请求头,PL2级别检测项包含PL1。
REQUEST-941-APPLICATION-ATTACK-XSS.conf 文件包含了一系列规则,这些规则旨在检测并阻止 XSS 攻击。下面是一些典型的规则及其解析:
检测特定标签和属性:
规则可能会查找常见的用于 XSS 攻击的 HTML 标签,如 <script>, <iframe>, <link> 等,以及 JavaScript 事件处理器属性,如 onclick, onerror, onload 等。
检测 JavaScript URI:
JavaScript URI(如 javascript:)是一种在 HTML 或其他文档中嵌入 JavaScript 代码的方法。规则会检查 URL 或其他属性值中是否包含此类 URI。
检测混淆和编码:
攻击者可能会使用混淆或编码技术来绕过简单的过滤。规则会尝试解码或解释混淆的代码,以发现潜在的 XSS 攻击。
检测异常字符模式:
某些字符模式(如过多的尖括号 <> 或引号 ")可能表明存在注入尝试。规则会分析这些模式来识别潜在的攻击。
特定上下文的 XSS 攻击:
XSS 攻击可能针对特定的 HTML 上下文,如 HTML 注释、属性值、JavaScript 代码块等。规则会针对这些上下文进行特定的检查。
异常请求大小:
非常大的请求体可能包含大量的注入尝试。规则可能会设置请求体大小的上限,并超过此上限的请求视为潜在的攻击。
每条规则都有一个唯一的 ID、一个描述性的消息、一个严重性级别和一个动作(如“阻止”请求)。这些规则是基于正则表达式的,允许它们灵活地匹配各种模式和攻击变体。
4.3 规则列表
id |
严重度 |
变量名称 |
检测方法 |
请求阶段 |
动作 |
Paranoia Level 2 |
|||||
941100 |
CRITICAL |
cookies cookies name User-Agent请求头 请求参数名称 请求参数 xml |
Libinjection |
2 (请求体) |
block |
941110 |
检查<script>标签 |
||||
941120 |
检查onerror、onload关键字 |
||||
941130 |
根据regexp-941130.data生成正则 |
||||
941140 |
Javascript uri、tag检测 |
||||
941160 |
regexp-941160.data生成正则 |
||||
941170 |
属性注入检测 |
||||
941180 |
Node-Validator 关键词黑名单 |
||||
941190941200941210941220941230941240941250941260941270941280941290941300 |
ie浏览器xss特征检测 |
||||
941310 |
US-ASCII编码传输绕过检测 |
||||
941350 |
IE浏览器UTF-7编码检测 |
||||
941360 |
针对JSFuck和Hieroglyphy的js混淆做检测 |
||||
941370 |
JavaScript全局变量检测 |
||||
Paranoia Level 2 |
|||||
941101 |
CRITICAL |
请求头referer |
用libinjection检测请求头referer |
2 (请求体) |
block |
941150 |
cookies cookies name User-Agent请求头 请求参数名称 请求参数 xml |
Html属性中关键词src、style、href检查 |
|||
941320941330941340 |
CVE-2018-2380漏洞利用检测 |
||||
941380 |
AngularJS客户端模板注入检测 |
||||
Paranoia Level 3 |
|||||
无 |
|||||
Paranoia Level 4 |
|||||
无 |
|||||
END-REQUEST-941-APPLICATION-ATTACK-XSS |