Nginx 的 WAF 规则 LuaJIT 高危险版

SQL报错检测

过滤阶段:返回页面

规则描述:返回页面的sql报错可能会泄露服务器敏感信息

规则内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
local check = waf.plugins.sqlErrorDetection.check
local rb = waf.respBody
local rgx = waf.rgxMatch
local has = waf.contains

if waf.status == 500 then
local m = check(rb)
if m then
if rgx(rb, "JET Database Engine|Access Database Engine|\\[Microsoft\\]\\[ODBC Microsoft Access Driver\\]", "jo") then
return m, "Microsoft Access SQL Information Leakage: " .. rb, true
end
if rgx(rb, "ORA-[0-9][0-9][0-9][0-9]|java\\.sql\\.SQLException|Oracle error|Oracle.*Driver|Warning.*oci_.*|Warning.*ora_.*", "jo") then
return m, "Oracle SQL Information Leakage: " .. rb, true
end
if rgx(rb, "DB2 SQL error:|\\[IBM\\]\\[CLI Driver\\]\\[DB2/6000\\]|CLI Driver.*DB2|DB2 SQL error|db2_\\w+\\(", "jo") then
return m, "DB2 SQL Information Leakage: " .. rb, true
end
if rgx(rb, "\\[DM_QUERY_E_SYNTAX\\]|has occurred in the vicinity of:", "jo") then
return m, "EMC SQL Information Leakage: " .. rb, true
end
if has(rb, "Dynamic SQL Error") then
return m, "firebird SQL Information Leakage: " .. rb, true
end
if rgx(rb, "Exception (?:condition )?\\d+\\. Transaction rollback\\.", "jo") then
return m, "Frontbase SQL Information Leakage: " .. rb, true
end
if has(rb, "org.hsqldb.jdbc") then
return m, "hsqldb SQL Information Leakage: " .. rb, true
end
if rgx(rb, "An illegal character has been found in the statement|com\\.informix\\.jdbc|Exception.*Informix", "jo") then
return m, "informix SQL Information Leakage: " .. rb, true
end
if rgx(rb, "Warning.*ingres_|Ingres SQLSTATE|Ingres\\W.*Driver", "jo") then
return m, "ingres SQL Information Leakage: " .. rb, true
end
if rgx(rb, "<b>Warning</b>: ibase_|Unexpected end of command in statement", "jo") then
return m, "interbase SQL Information Leakage: " .. rb, true
end
if rgx(rb, "SQL error.*POS[0-9]+|Warning.*maxdb", "jo") then
return m, "maxDB SQL Information Leakage: " .. rb, true
end
if rgx(rb, "System\\.Data\\.OleDb\\.OleDbException|\\[Microsoft\\]\\[ODBC SQL Server Driver\\]|\\[Macromedia\\]\\[SQLServer JDBC Driver\\]|\\[SqlException|System\\.Data\\.SqlClient\\.SqlException|Unclosed quotation mark after the character string|'80040e14'|mssql_query\\(\\)|Microsoft OLE DB Provider for ODBC Drivers|Microsoft OLE DB Provider for SQL Server|Incorrect syntax near|Sintaxis incorrecta cerca de|Syntax error in string in query expression|Procedure or function .* expects parameter|Unclosed quotation mark before the character string|Syntax error .* in query expression|Data type mismatch in criteria expression\\.|ADODB\\.Field \\(0x800A0BCD\\)|the used select statements have different number of columns|OLE DB.*SQL Server|Warning.*mssql_.*|Driver.*SQL[ _-]*Server|SQL Server.*Driver|SQL Server.*[0-9a-fA-F]{8}|Exception.*\\WSystem\\.Data\\.SqlClient\\.", "jo") then
return m, "Mssql SQL Information Leakage: " .. rb, true
end
if rgx(rb, "MyS(?:QL server version for the right syntax to use|qlClient\\.)|(?:supplied argument is not a valid |SQL syntax.*)MySQL|Column count doesn't match(?: value count at row)?|(?:Table '[^']+' doesn't exis|valid MySQL resul)t|You have an error in your SQL syntax(?: near|;)|Warning.{1,10}mysql_(?:[a-z_()]{1,26})?|ERROR [0-9]{4} \\([a-z0-9]{5}\\):|mysql_fetch_array\\(\\)|on MySQL result index|\\[MySQL\\]\\[ODBC", "jo") then
return m, "Mysql SQL Information Leakage: " .. rb, true
end
if rgx(rb, "PostgreSQL query failed:|pg_query\\(\\) \\[:|pg_exec\\(\\) \\[:|PostgreSQL.{1,20}ERROR|Warning.*\\bpg_.*|valid PostgreSQL result|Npgsql\\.|PG::[a-zA-Z]*Error|Supplied argument is not a valid PostgreSQL .*? resource|Unable to connect to PostgreSQL server", "jo") then
return m, "Postgres SQL Information Leakage: " .. rb, true
end
if rgx(rb, "Warning.*sqlite_|Warning.*SQLite3::|SQLite/JDBCDriver|SQLite\\.Exception|System\\.Data\\.SQLite\\.SQLiteException", "jo") then
return m, "SQLite SQL Information Leakage: " .. rb, true
end
if rgx(rb, "Sybase message:|Warning.{2,20}sybase|Sybase.*Server message", "jo") then
return m, "Sybase SQL Information Leakage: " .. rb, true
end
end
end

return false

数据泄露检测

过滤阶段:返回页面

规则描述:从返回页面检测列目录漏洞和源代码泄露问题

规则内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
local rgx = waf.rgxMatch
local rb = waf.respBody

local m = rgx(rb, "<(?:TITLE>Index of.*?<H|title>Index of.*?<h)1>Index of|>\\[To Parent Directory\\]</[Aa]><br>", "jo")
if m then
return m, "Directory Listing: " .. rb, true
end

m = rgx(rb, "^\\s*(?:#\\!\\s?/|<%|<\\?\\s*[^x]|<jsp:)", "jo")
if m then
return m, "Source code leak: " .. rb, true
end

return false

固定会话(Session Fixation)攻击

过滤阶段:请求阶段

规则描述:会话固定攻击(session fixation attack)是利用应用系统在服务器的会话ID固定不变机制,借助他人用相同的会话ID获取认证和授权,然后利用该会话ID劫持他人的会话以成功冒充他人,造成会话固定攻击。

规则内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
local kvFilter = waf.kvFilter
local rgx = waf.rgxMatch
local referer = waf.referer
local host = waf.host
local endWith = waf.endWith

local function sMatch(v)
local m = rgx(v, "\\bhttp-equiv\\W+set-cookie\\b", "joi")
if m then
return m, v
end
return false
end

local function nMatch(v)
local m = rgx(v, "^(?:jsessionid|aspsessionid|asp\\.net_sessionid|phpsession|phpsessid|weblogicsession|session_id|session-id|cfid|cftoken|cfsid|jservsession|jwsession)$", "joi")
if m then
return m, v
end
return false
end

local form = waf.form
if form then
local m, d = kvFilter(form["FORM"], sMatch)
if m then
return m, d, true
end
for k, v in pairs(form["FORM"]) do
m, d = nMatch(k)
if m then
if not referer then
if type(v) == "table" then
v = table.concat(v)
end
return m, d .. ":" .. v, true
else
m = ngx.re.match(referer, "^https?://(.*?)/", "jo")
if m and not endWith(m[1], host) then
if type(v) == "table" then
v = table.concat(v)
end
return m, d .. ":" .. v, true
end
end
end
end
end

local queryString = waf.queryString
if queryString then
local m, d = kvFilter(queryString, sMatch)
if m then
return m, d, true
end
for k, v in pairs(queryString) do
m, d = nMatch(k)
if m then
if not referer then
if type(v) == "table" then
v = table.concat(v)
end
return m, d .. ":" .. v, true
else
m = ngx.re.match(referer, "^https?://(.*?)/", "jo")
if m and not endWith(m[1], host) then
if type(v) == "table" then
v = table.concat(v)
end
return m, d .. ":" .. v, true
end
end
end
end
end

local cookies = waf.cookies
if cookies then
local m, d = kvFilter(cookies, sMatch)
if m then
return m, d, true
end
end

return false

通用攻击

过滤阶段:请求阶段

规则描述:本规则拦截ruby、node、js、perl注入和SSRF攻击

规则内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
local kvFilter = waf.kvFilter
local rgx = waf.rgxMatch

local function sMatch(v)
local m = rgx(v, "Process\\s*\\.\\s*spawn\\s*\\(", "jos")
if m then
return m, "Ruby Injection Attack: "..v
end
m = rgx(v, "t(?:his\\.constructor|runcateSync\\s*\\()|\\b(?:spawn|eval)\\s*\\(|_(?:\\$\\$ND_FUNC\\$\\$_|_js_function)|String\\s*\\.\\s*fromCharCode", "jos")
if m then
return m, "Node.js Injection Attack: "..v
end
m = rgx(v, "__proto__|constructor\\s*(?:\\.|\\[)\\s*prototype", "jos")
if m then
return m, "JavaScript Prototype Pollution: "..v
end
m = rgx(v, "(?:s(?:sh(?:2(?:.(?:s(?:(?:ft|c)p|hell)|tunnel|exec))?)?|m(?:[bs]|tps?)|vn(?:\\+ssh)?|n(?:ews|mp)|ips?|ftp|3)|p(?:op(?:3s?|2)|r(?:oxy|es)|h(?:ar|p)|aparazzi|syc)|c(?:ompress.(?:bzip2|zlib)|a(?:llto|p)|id|vs)|t(?:e(?:amspeak|lnet)|urns?|ftp)|f(?:i(?:nger|sh)|(?:ee)?d|tps?)|i(?:rc[6s]?|maps?|pps?|cap|ax)|d(?:a(?:ta|v)|n(?:tp|s)|ict)|m(?:a(?:ilto|ven)|umble|ms)|n(?:e(?:tdoc|ws)|ntps?|fs)|r(?:tm(?:f?p)?|sync|ar|mi)|v(?:iew-source|entrilo|nc)|a(?:ttachment|f[ps]|cap)|b(?:eshare|itcoin|lob)|g(?:o(?:pher)?|lob|it)|u(?:nreal|t2004|dp)|e(?:xpect|d2k)|h(?:ttps?|323)|w(?:ebcal|s?s)|ja(?:bbe)?r|x(?:mpp|ri)|ldap[is]?|ogg|zip):\\/\\/(?:(?:[\\d.]{0,11}(?:(?:\\xe2(?:\\x92(?:[\\x9c\\x9d\\x9e\\x9f\\xa0\\xa1\\xa2\\xa3\\xa4\\xa5\\xa6\\xa7\\xa8\\xa9\\xaa\\xab\\xac\\xad\\xae\\xaf\\xb0\\xb1\\xb2\\xb3\\xb4\\xb5]|[\\x88\\x89\\x8a\\x8b\\x8c\\x8d\\x8e\\x8f\\x90\\x91\\x92\\x93\\x94\\x95\\x96\\x97\\x98\\x99\\x9a\\x9b]|[\\xb6\\xb7\\xb8\\xb9\\xba\\xbb\\xbc\\xbd\\xbe\\xbf]|[\\x80\\x81\\x82\\x83\\x84\\x85\\x86\\x87])|\\x93(?:[\\x80\\x81\\x82\\x83\\x84\\x85\\x86\\x87\\x88\\x89\\x8a\\x8b\\x8c\\x8d\\x8e\\x8f]|[\\x9c\\x9d\\x9e\\x9f\\xa0\\xa1\\xa2\\xa3\\xa4\\xa5\\xa6\\xa7\\xa8\\xa9]|[\\x90\\x91\\x92\\x93\\x94\\x95\\x96\\x97\\x98\\x99\\x9a\\x9b]|[\\xbf\\xb5\\xb6\\xb7\\xb8\\xb9\\xba\\xbb\\xbc\\xbd\\xbe]|[\\xab\\xac\\xad\\xae\\xaf\\xb0\\xb1\\xb2\\xb3\\xb4])|\\x91(?:[\\xaa\\xa0\\xa1\\xa2\\xa3\\xa4\\xa5\\xa6\\xa7\\xa8\\xa9\\xaa\\xab\\xac\\xad\\xae\\xaf\\xb0\\xb1\\xb2\\xb3]|[\\xb4\\xb5\\xb6\\xb7\\xb8\\xb9\\xba\\xbb\\xbc\\xbd\\xbe\\xbf]))|\\xe3\\x80\\x82))+)|[a-z][\\w\\-\\.]{1,255}:\\d{1,5}(?:#?\\s*&?@(?:(?:\\d{1,3}\\.){3,3}\\d{1,3}|[a-z][\\w\\-\\.]{1,255}):\\d{1,5}\\/?)+|(?:0x[a-f0-9]{2}\\.){3}0x[a-f0-9]{2}|(?:0{1,4}\\d{1,3}\\.){3}0{1,4}\\d{1,3}|\\d{1,3}\\.(?:\\d{1,3}\\.\\d{5}|\\d{8})|0x(?:[a-f0-9]{16}|[a-f0-9]{8})|\\[[a-f\\d:]+(?:[\\d.]+|%\\w+)?\\]|(?:\\x5c\\x5c[a-z\\d-]\\.?_?)+|\\d{10})", "josi")
if m then
return m, "Possible Server Side Request Forgery (SSRF) Attack: "..v
end
m = rgx(v, "\\@\\{.*?\\}", "jos")
if m then
return m, "Perl Injection Attack: "..v
end
return false
end

local form = waf.form
if form then
local m, d = kvFilter(form["FORM"], sMatch)
if m then
return m, d, true
end
end

local queryString = waf.queryString
if queryString then
local m, d = kvFilter(queryString, sMatch)
if m then
return m, d, true
end
end

local cookies = waf.cookies
if cookies then
local m, d = kvFilter(cookies, sMatch)
if m then
return m, d, true
end
end

local m, d = kvFilter(waf.reqHeaders, sMatch)
if m then
return m, d, true
end
return false

php安全规则集

过滤阶段:请求阶段

规则描述:检测php相关的对象序列化等漏洞

规则内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
local kvFilter = waf.kvFilter
local rgx = waf.rgxMatch

local function sMatch(v)
local m = rgx(v, "php://(?:std(?:in|out|err)|(?:in|out)put|fd|memory|temp|filter)|(?:ssh2(?:.(?:s(?:(?:ft|c)p|hell)|tunnel|exec))?|z(?:lib|ip)|(?:ph|r)ar|expect|bzip2|glob|ogg)://", "joi")
if m then
return m, v
end
m = rgx(v, "[oOcC]:\\d+:\"\\w+\":\\d+:{.*?}", "jos")
if m then
return m, v
end
return false
end

local function fileContentMatch(v)
local m = rgx(v, "<\\?.+?\\$_(?:GET|POST|COOKIE|REQUEST|SERVER|FILES|SESSION)|<\\?php", "jos")
if m then
return m, v
end
return false
end

local form = waf.form
if form then
local m, d = kvFilter(form["FORM"], sMatch)
if m then
return m, d, true
end
m, d = waf.knFilter(form["FILES"], fileContentMatch, 0)
if m then
return m, d, true
end
end

local queryString = waf.queryString
if queryString then
local m, d = kvFilter(queryString, sMatch)
if m then
return m, d, true
end
end

local cookies = waf.cookies
if cookies then
local m, d = kvFilter(cookies, sMatch)
if m then
return m, d, true
end
end

local m, d = kvFilter(waf.reqHeaders, sMatch)
if m then
return m, d, true
end
return false

路径遍历攻击

过滤阶段:请求阶段

规则描述:检测url、上传文件或参数中的路径遍历攻击。采用LFI语义检测引擎,可以检查如://///…\…\etc///passwd等变形攻击。

规则内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
local checkPT = waf.checkPT
local kvFilter = waf.kvFilter

local function ptMatch(v)
local m = checkPT(v)
if m then
return m, v
end
return false
end

local url = waf.urlDecode(waf.reqUri)
if checkPT(url) then
return true, url, true
end

local form = waf.form
if form then
local m, d = kvFilter(form["FORM"], ptMatch)
if m then
return m, d, true
end
m, d = waf.knFilter(waf.form["FILES"], ptMatch, 1)
if m then
return m, d, true
end
end

local queryString = waf.queryString
if queryString then
local m, d = kvFilter(queryString, ptMatch)
if m then
return m, d, true
end
end

return false

异常请求字符编码拦截

过滤阶段:请求阶段

规则描述:黑客通常会在Content-Type头中使用异常的charset定义字符集编码来绕过waf保护,如IBM037, IBM500, cp875等

规则内容:

1
2
3
4
5
6
7
8
9
10
11
local rct = waf.reqContentType
local has = waf.contains
local counter = waf.strCounter
local rgx = waf.rgxMatch
if rct then
rct = waf.toLower(rct)
if has(rct, "charset") and (not rgx(rct, "charset\\s*=\\s*(utf\\-8|gbk|gb2312|iso\\-8859\\-1|iso\\-8859\\-15|windows\\-1252)","jo") or counter(rct, "charset") > 1) then
return true, rct, true
end
end
return false

代理头sql注入

过滤阶段:请求阶段

规则描述:过滤http请求中X-Forwarded-For、Client-IP请求头中单引号sql注入

规则内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
local rip=waf.reqHeaders.x_forwarded_for
if rip then
if type(rip) ~= "string" then
return true,"Malform X-Forwarded-For",true
elseif waf.contains(rip,"'") then
return true,rip,true
end
end
rip=waf.reqHeaders.client_ip
if rip then
if type(rip) ~= "string" then
return true,"Malform Client-IP",true
elseif waf.contains(rip,"'") then
return true,rip,true
end
end
return false

Invalid protocol

过滤阶段:请求阶段

规则描述:cookie参数过多

规则内容:

1
2
3
4
if waf.cookies==nil then
return true,waf.cErr,true
end
return false

Invalid protocol

过滤阶段:请求阶段

规则描述:querystring参数过多

规则内容:

1
2
3
4
if waf.queryString==nil then
return true,waf.qErr,true
end
return false

本文链接:https://my.lmcjl.com/post/15853.html

展开阅读全文

4 评论

留下您的评论.