# easy_ngx_waf_rule **Repository Path**: chleniang/easy_ngx_waf_rule ## Basic Information - **Project Name**: easy_ngx_waf_rule - **Description**: 适配 easy_ngx_waf 的规则仓库。 - **Primary Language**: Unknown - **License**: MulanPSL-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2023-05-16 - **Last Updated**: 2023-09-08 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## 简介 > 本项目 [`easy_ngx_waf_rule`](https://gitee.com/chleniang/easy_ngx_waf_rule) 作为 [`easy_ngx_waf`](https://gitee.com/chleniang/easy_ngx_waf) 的主规则库单独维护。 > > 可直接将本项目内容复制到 `easy_ngx_waf/rules/` 主规则目录下(覆盖原文件即可)。 > > 规则文件分为两种: > > - 常规规则文件(文档中无特殊说明,所说的 `"规则"` / `"规则文件"` 就是指此类规则/规则文件) > - 简单规则文件 > ### 常规规则文件 1. 本项目根目录下以 `.rule` 结尾的文件。 > `easy_ngx_waf` 会扫描所有 `.rule` 文件加载规则。 2. 常规规则文件是 `json` 格式的数组,每一个规则作为数组中的一个元素。 > 理论上可以将所有规则数组写在一个文件中,但为了方便管理,还是建议按规则分类写到各自规则文件中; > > 规则文件格式,请参见 [常规规则文件格式](#常规规则文件格式) 章节; ### 简单规则文件 > 为兼容历史规则文件书写方式以及简化常见规则的书写,在 `./simple/` 目录下有多个 `"简单规则文件"` 。 1. "简单规则文件" 中都是以 `行` 为单位的规则值,这些规则值通常都会按正则匹配进行校验。 2. "简单规则文件" 各个 `"文件名"` **不得更改**。 ### 注释 - 所有规则文件中,以 `##` 开头的行是注释行,不作为规则内容。 - 不支持行内注释,注释必须以新行开始。 ``` ## 简单规则文件中: 这是注释行 \.\. ## 常规规则文件中: 这也是注释行 { ## 这是规则名称(我是注释行) "name": "sql-inject-1001100", "var": ["args", "post"], ... } ``` ## 目录结构 > 根目录下所有 `.rule` 结尾文件都会被 `easy_ngx_waf` 加载。 > > `CRS-REQUEST-XXX.rule` 此类规则是从 [OWASP® ModSecurity Core Rule Set (CRS)](https://coreruleset.org) 项目中改写来的。 ``` ./easy_ngx_waf_rule/ # 规则根目录 | CRS-REQUEST-913-SCANNER.rule | CRS-REQUEST-920-PROTOCOL.rule | CRS-REQUEST-921-PROTOCOL.rule | CRS-REQUEST-930-LFI.rule | CRS-REQUEST-931-RFI.rule | CRS-REQUEST-932-RCE.rule | CRS-REQUEST-933-PHP.rule | CRS-REQUEST-934-NODEJS.rule | CRS-REQUEST-941-XSS.rule | CRS-REQUEST-942-SQLI.rule | CRS-REQUEST-943-SESSION.rule | CRS-REQUEST-944-JAVA.rule | LICENSE | README.md | demo.rule # 一个演示规则文件 | +---simple/ # 简单规则文件目录 | args # get参数校验 | cookie # cookie校验 | ip_black # ip黑名单(IPv4 IPv6 CIDR 格式) | ip_white # ip白名单 | post # post参数校验 | url # url校验 | url_white # url白名单 | user_agent # ua校验 | user_agent_white # ua白名单 | \---spider/ # 蜘蛛数据目录(文件格式说明详见目录下README) 360.data baidu.data bing.data README.md ...... ``` ## 常规规则文件格式 > - 每个 `.rule` 规则文件中须用一对中括号 `[ ]` 将规则包围起来(即使只有一条规则) > > - 规则中 `键名` 以及 `值` 都需要用 `双引号` 包围; > > - 规则中每一个 `键值对` 都需要从新行开始,否则可能造成解析时出错; > > ```json > ## 某个 .rule 文件 > [ > ## 一个规则示例 > { > "name": "xx1", > "var": "user_agent", > "op": "re", > "value": "curl|webt", > "act": "next", > "log": "on", > "msg": "规则日志信息" > } > ] > ``` ### 常规规则参数 #### name - 规则名称 > 作为该规则的标识,推荐 规则类别+编号 > > - 类型:字符串 ```json ## 示例 { "name": "sql-inject-100022", ... } ``` #### var - 变量 > WAF要检测的内容,不区分大小写 (类似 `ModSecurity` 的 变量) > > - 类型:字符串 / 数组 > > 可用变量有: > > - `"IP"` 来访客户端 `IP`。 > - `"USER_AGENT"` `HEADER` 中的 `USER-AGENT`。 > - `"COOKIE"` `HEADER` 中的 `COOKIE`。 > - `"ARGS_GET"` 或者 `"ARGS"` 查询字符串参数值。 > - `"ARGS_GET_NAMES"` 仅包含查询字符串参数的名称。 > - `"QUERY_STRING"` 包含请求URI的查询字符串部分。 `QUERY_STRING` 中的值始终是原始提供的,不进行URL解码。 > - `"ARGS_POST"` 或者 `"POST"` 来自 `POST` 请求体的参数。 > - `"ARGS_POST_NAMES"` 仅包含 `POST` 请求体参数的名称。 > - `"REQUEST_BODY"` 包含原始请求体。当检测到 `application/x-www-form-urlencoded` 内容类型时。 > - `"REQUEST_COOKIES"` 或者 `"COOKIE"` 所有请求 `cookie` 的集合(仅包含值)。 > - `"REQUEST_COOKIES_NAMES"` 所有请求 `cookie` 的名称的集合。 > - `"REQUEST_FILENAME"` 包含不带查询字符串部分的相对请求URL。 > - `"REQUEST_URI"` 包含查询字符串数据在内的完整请求URL(例如,`/index.php?p=X`)。但是,它永远不会包含域名,即使它是在请求行上提供的。 > - `"REQUEST_URI_RAW"` 与 `REQUEST_URI` 相同,但如果在请求行上提供了域名,则包含域名(例如,`http://www.example.com/index.php?p=X` )。 > - `"FILES"` 包含原始文件名的集合(因为它们是在远程用户的文件系统上调用的)。仅适用于检查通过 `multipart/form-data` 形式上传的请求。 > - `"FILES_NAMES"` 包含用于文件上载的表单字段列表。仅适用于检查通过 `multipart/form-data` 形式上传的请求。 > - `"REQUEST_HEADERS"` 或者 `"HEADER"` 可以用作所有请求头的集合。 > - `"REQUEST_HEADERS_NAMES"` 所有请求头的名称的集合。 ```json ## 示例 可以是多个,每一项 "var" 都会用 "op" 检测 "value" { "var": [ "ARGS_GET", "REQUEST_HEADERS" ], ... } ``` #### op - 操作符 > 检测时用的匹配方法,成功匹配后做相应的动作 > > - 类型:字符串 > > 可选操作运算符有: > > - `"re"` 正则匹配 (规则值:字符数组/字符串) > > - `"eq"` 相等 (规则值:字符串/数值) > > - `"gt"` 大于 (规则值:字符串/数值) > > - `"lt"` 小于 (规则值:字符串/数值) > > - `"startwith"` 字符串以...开头 (忽略大小写; 规则值:字符串) > > - `"endwith"` 字符串以...结尾 (忽略大小写; 规则值:字符串) > > - `"contain"` 字符串包含... (忽略大小写; 规则值:字符串) > > - `"in"` 只要是规则值中的一个(相等)即可 (忽略大小写; 规则值:字符数组) > > - `"ip_match"` IP地址在指定规则值的网段内(规则值:字符数组/字符串 CIDR格式) > > - `"ip_region"` IP地址所属国家地区码在指定规则值内(区分大小写; 规则值:字符数组/字符串 如:`["CN", "MO", "TW", "PRIVATE"]` ) > > - 可以在以上几种运算符前加 `"!"` 表示 取反 > > ​ 如: `"!gt"` 表示 "不大于" 等同于 "小于等于" ```json ## 示例 { "op": "re", ... } ``` #### value - 规则值 > 检测时的具体匹配内容(兼容 CRS 正则规则) > > - 类型:字符串 / 数组 > > 特殊字符 (规则值会使用cjson解码,所以其中一些特殊字符需要转义) > > ```shell > > 控制字符 (ASCII 0 - 31) > > " (ASCII 34) > > / (ASCII 47) > > \ (ASCII 92) > > 退格 (ASCII 127) > > ``` ```json ## 示例 { "value": "\/[\"|'|\\s]*", ... } ``` #### act - 动作 > 针对 `"var"` 通过 `"op"` 匹配 `"value"`, 匹配成功时 WAF 作出的响应动作 > > - 类型:字符串 > > 此处可选动作有: `"deny"` / `"allow"` / `"next"` (为了简便,不追求过于全面的功能) > > - `"deny"` 拦截掉,不再进入下一规则校验,直接返回拦截响应内容 > - `"allow"` 直接放行,不再进行任何规则校验 **慎用**(比如IP白名单命中时,不需要再检测其他规则) > - `"next"` 不处理,进入下一规则校验(可结合 `"log": "on"` 在命中特定规则时只做日志记录) ```json ## 示例 { "act": "deny", ... } ``` #### log - 日志开关 > 是否记录日志 > > - 类型:字符串 > > 开关项: `"on" ` / `"off"` > > - `"on"` 记录日志 > - `"off"` 不记录日志(比如白名单命中时就可以不记录日志) ```json ## 示例 { "log ": "on", ... } ``` #### msg - 信息摘要 > 检测匹配时的信息摘要(主要用于拦截日志记录,方便日志分析) > > - 类型:字符串 ```lua ## 示例 { ... "msg": "sql inject detected." } ``` ### 完整示例 ```json ## xxx.rule 文件 ## 一个规则文件中须用一对中括号将规则作为数组元素包围起来(即使只有一条规则) ## 数组/对象最后一个元素后边 不能有逗号 ( "]" 及 "}" 前边不能出现逗号) [ ## 这是一条规则 { ## 键名 值 都需要用双引号包围 ## "name" 作为该规则的标识,推荐 规则简称+编号 "name": "sql-inject-100022", ## "var" WAF要检测的内容(类似 ModSecurity 变量,此处不区分大小写) ## 可以是多个,每一项 "var" 都会用 "op" 检测 "value" "var": [ "ARGS", ## 一个错误示例(数组结束符前有逗号) "REQUEST_FILENAME", ], ## "op" 检测运算符,检测时用的匹配方法,成功匹配后做相应的动作 ## "re" 正则匹配 "op": "re", ## "value" 规则植 "value": "\.\./[\"|'|\s]*", ## "act" 拦截响应动作,针对 "var" 通过 "op" 匹配 "rule",匹配成功时 WAF 作出响应动作 ## 此处可选动作有3个:"deny" / "allow" / "next" (为了简便,不追求过于全面的功能) ## "deny" 拦截掉,不再进入下一规则,直接返回拦截响应内容 ## "allow" 直接放行,不再进入下一规则 (比如IP白名单命中时,不需要再检测其他规则) ## "next" 进入下一规则检验 "act": "deny", ## "log" 是否记录日志 ## 此处可选动作两个: "on" / "off" ## "on" 记录日志 ## "off" 不记录日志(比如白名单命中时就可以不记录日志) "log": "on", ## "msg" 检测匹配时的信息摘要(主要用于拦截日志记录,便于分析) ## 注意: "msg"的值本身需要用双引号括起来,所以信息中需要用引号的地方最好用单引号 ## 如: "demo演示:['信息1','信息2']" ## 当前元素是规则对象最后一个元素,后边不能加逗号 "msg": "demo演示:['信息1','信息2','本地IP记录一下']" }, { ## 另一条规则 ## 当前规则已经是文件中最后一条,下一行"}"后边不能加逗号 } ] ```