W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
所謂 SQL 注入,就是通過(guò)把 SQL 命令插入到 Web 表單提交或輸入域名或頁(yè)面請(qǐng)求的查詢字符串,最終達(dá)到欺騙服務(wù)器執(zhí)行惡意的 SQL 命令。具體來(lái)說(shuō),它是利用現(xiàn)有應(yīng)用程序,將(惡意)的 SQL 命令注入到后臺(tái)數(shù)據(jù)庫(kù)引擎執(zhí)行的能力,它可以通過(guò)在 Web 表單中輸入(惡意)SQL 語(yǔ)句得到一個(gè)存在安全漏洞的網(wǎng)站上的數(shù)據(jù)庫(kù),而不是按照設(shè)計(jì)者意圖去執(zhí)行 SQL 語(yǔ)句。比如先前的很多影視網(wǎng)站泄露 VIP 會(huì)員密碼大多就是通過(guò) Web 表單遞交查詢字符暴出的,這類表單特別容易受到 SQL 注入式攻擊。
下面給了一個(gè)完整的可復(fù)現(xiàn)的 SQL 注入例子,實(shí)際上注入的 SQL 語(yǔ)句寫法有很多,下例是比較簡(jiǎn)單的。
location /test {
content_by_lua_block {
local mysql = require "resty.mysql"
local db, err = mysql:new()
if not db then
ngx.say("failed to instantiate mysql: ", err)
return
end
db:set_timeout(1000) -- 1 sec
local ok, err, errno, sqlstate = db:connect{
host = "127.0.0.1",
port = 3306,
database = "ngx_test",
user = "ngx_test",
password = "ngx_test",
max_packet_size = 1024 * 1024 }
if not ok then
ngx.say("failed to connect: ", err, ": ", errno, " ", sqlstate)
return
end
ngx.say("connected to mysql.")
local res, err, errno, sqlstate =
db:query("drop table if exists cats")
if not res then
ngx.say("bad result: ", err, ": ", errno, ": ", sqlstate, ".")
return
end
res, err, errno, sqlstate =
db:query("create table cats "
.. "(id serial primary key, "
.. "name varchar(5))")
if not res then
ngx.say("bad result: ", err, ": ", errno, ": ", sqlstate, ".")
return
end
ngx.say("table cats created.")
res, err, errno, sqlstate =
db:query("insert into cats (name) "
.. "values (\'Bob\'),(\'\'),(null)")
if not res then
ngx.say("bad result: ", err, ": ", errno, ": ", sqlstate, ".")
return
end
ngx.say(res.affected_rows, " rows inserted into table cats ",
"(last insert id: ", res.insert_id, ")")
-- 這里有 SQL 注入(后面的 drop 操作)
local req_id = [[1'; drop table cats;--]]
res, err, errno, sqlstate =
db:query(string.format([[select * from cats where id = '%s']], req_id))
if not res then
ngx.say("bad result: ", err, ": ", errno, ": ", sqlstate, ".")
return
end
local cjson = require "cjson"
ngx.say("result: ", cjson.encode(res))
-- 再次查詢,table 被刪
res, err, errno, sqlstate =
db:query([[select * from cats where id = 1]])
if not res then
ngx.say("bad result: ", err, ": ", errno, ": ", sqlstate, ".")
return
end
db:set_keepalive(10000, 100)
}
}
其他變種,大家可以自行爬行搜索引擎了解。
其實(shí)大家可以大概網(wǎng)絡(luò)爬行一下看看如何解決 SQL 注入,可以發(fā)現(xiàn)實(shí)現(xiàn)方法很多,比如替換各種關(guān)鍵字等。在 OpenResty 中,其實(shí)就簡(jiǎn)單很多了,只需要對(duì)輸入?yún)?shù)進(jìn)行一層過(guò)濾即可。
對(duì)于 MySQL ,可以調(diào)用 ?ndk.set_var.set_quote_sql_str
? ,進(jìn)行一次過(guò)濾即可。
-- for MySQL
local req_id = [[1'; drop table cats;--]]
res, err, errno, sqlstate =
db:query(string.format([[select * from cats where id = %s]],
ndk.set_var.set_quote_sql_str(req_id)))
if not res then
ngx.say("bad result: ", err, ": ", errno, ": ", sqlstate, ".")
return
end
如果恰巧你使用的是 PostgreSQL ,調(diào)用 ?ndk.set_var.set_quote_pgsql_str
? 過(guò)濾輸入變量。讀者這時(shí)候可以再次把這段代碼放到剛剛的示例代碼中,如果您可以得到下面的錯(cuò)誤,恭喜您,以正確的姿勢(shì)防止 SQL 注入。
bad result: You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use near
'1\'; drop table cats;--''' at line 1: 1064: 42000.
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: