MySQL解決SQL注入的另類方法詳解
本文實例講述了MySQL解決SQL注入的另類方法。分享給大家供大家參考,具體如下:
問題解讀
我覺得,這個問題每年帶來的成本可以高達(dá)數(shù)十億美元了。本文就來談?wù)?,假定我們有如?SQL 模板語句:
select * from T where f1 = '{value1}' and f2 = {value2}
現(xiàn)在我們需要根據(jù)用戶輸入值填充該語句:
value1=hello value2=5
我們得到了下面的 SQL 語句,我們再提交給數(shù)據(jù)庫:
select * from T where f1='hello' and f2=5
問題在于,攻擊者可以構(gòu)造如下的用戶輸入值:
value1=anything' or 1=1 or f1='whatever value2=5
拼接好的最終語句就變成了:
select * from T where f1='anything' or 1=1 or f1='whatever' and f2=5
攻擊者成功地改變了模板語句的語義。這種問題不單單發(fā)生在 SQL 上,還出現(xiàn)在通常使用模板的任何語言上,比如 HTML 和 shell 腳本。
常規(guī)解決方案的說明
SQL 是具備任意性和一致性的公理,token 和派生規(guī)則構(gòu)成其公理化基礎(chǔ)。要注意的一個詞語是「任意性」。與 SQL 等價的公理化數(shù)不勝數(shù)。對于這種任意等價的表示,每一條合法的語句都能被準(zhǔn)確地映射到 SQL 里的合法語句,其它語言亦然。在這種任意等價表示中,如果某語句是不合法的,那么它在 SQL 里也是不合法的。攻擊者不可能構(gòu)造出可以滿足任何可能的、任意與 SQL 等價的規(guī)則。
策略1:根據(jù)不同的派生規(guī)則,用另一種語法擴(kuò)展模板語句
例子1:前綴語言
SQL 使用中綴表示法注1。中綴表示法等價于 lisp 風(fēng)格的前綴表示法注2。中綴與前綴:
a OP1 b OP2 c <=> (OP1 a (OP2 b c))
a、b、c 是標(biāo)識符或值,OP1、OP2 是操作符或功能。
前綴表示法的示例語句:
(select * T (and (= f1 '{value1}') (= f2 {value2})))
該語句是等價的。它們在語義上屬于外延。自動把 SQL 的中綴表示法轉(zhuǎn)換成前綴表示法或其它表示法,都不算問題了。然而,攻擊者的注入在前綴語法方面就是不合法的:
語法錯誤。攻擊者想要的是:
這是不同的。攻擊者的注入不能輸出合法的前綴語言。
例子2:歐拉表示法
另一個替代方法將數(shù)得著歐拉表示法了。從中綴表示法到歐拉:
a OP1 b OP2 c <=> OP1(a,OP2(b,c))
例子中的語句:
select( *,T,and(=(f1,'{value1}'),=(f2,{value2})))
而注入的語句將出現(xiàn)語法錯誤:
攻擊者本來是想寫成:
攻擊者正在做錯誤的事情。他的注入根本就沒有注意到所選的任意標(biāo)記法。
例子3:對象標(biāo)記法(object notation)
還有一種替代方法,對象標(biāo)記法。從前綴表示法到對象:
a OP1 b OP2 c <=> a.OP1(b).OP2(c)
例子的代碼:
T.where(f1.=('{value1}').and(f2.=({value2})).select(*)
注入再一次折戟于語法:
T.where(f1.=('anything' or 1=1 or a='whatever').and(f2.=5)).select(*)
我不再提供正確答案了,讀者可以當(dāng)做練習(xí),看看攻擊者應(yīng)該寫成什么樣子。
策略2:為 SQL 選擇其它任意 token
keyword 常常是一門語言里的任意 token。重要的是它們在派生規(guī)則里的位置、而非它們的任意體現(xiàn)。你總是可以用其它 keyword 替換現(xiàn)有 keyword,并且來回轉(zhuǎn)換。舉個例子,我們可以將下面 SQL 語句中的 keyword 轉(zhuǎn)換成我們姑且稱為「任意的 brainfuck」:
為了論證起見,我們將把操作數(shù)映射為 半任意的結(jié)構(gòu)化序列:
T <=> @phai1Oa6@T@ hello <=> @phai1Oa6@hello@
phai1Oa6 是任意選取的字符序列。對于當(dāng)前情形,例子:
select * from T where f1 = '{value1}' and f2 = {value2}
變成了:
iph0ohKi ieZoh4xa aeZi5uja @phai1Oa6@T@ OoJ4aX4n @phai1Oa6@f1@ eeQu2Zad '{value1}' @phai1Oa6@and@ @phai1Oa6@f2@ eeQu2Zad {value2}
這是合法的、任意的 brainfuck 語言。經(jīng)過注入之后,我們得到了:
iph0ohKi ieZoh4xa aeZi5uja @phai1Oa6@T@ OoJ4aX4n @phai1Oa6@f1@ eeQu2Zad 'anything' or 1=1 or a='whatever' @phai1Oa6@and@ @phai1Oa6@f2@ eeQu2Zad 5
你可以看到,它包含的 token 有 'or' 和 '=',它們在任意的 brainfuck 語言中是不合法的。我們的語法說,你必須這樣使用:
or <=> Ocaig5Es = <=> eeQu2Zad
這些 token 也不是操作數(shù),因為它們將只能被視作:
or <=> @phai1Oa6@or@ = <=> @phai1Oa6@=@
換句話說,注入之后的語句就變得不合法、也不可用了。
策略3:驗證不變量
你數(shù)數(shù)下面模板語句例子中的 token 有幾個?
[1] select [2] * [3] from [4] T [5] where [6] f1 [7] = [8] '{value1}' [9] and [10] f2 [11] = [12] {value2}
12 個。模板填充之后,總數(shù)必須仍然為 12,但是我們卻看到了攻擊者所引發(fā)的結(jié)果:
[1] select [2] * [3] from [4] T [5] where [6] f1 [7] = [8] 'anything' [9] or [10] 1 [11] = [12] 1 [13] or [14] a [15] = [16] 'whatever' [17] and [18] f2 [19] = [20] 5
現(xiàn)在有 20 個 token 。違反這種不變量,就暴露了有問題的地方。同樣適用于相同語句的表示,除了任意的、brainfuck 語言。模板的填充根本不可能導(dǎo)致 token 數(shù)量的變化。
事實上,你可以試著使用其它不變量,并在填充之后進(jìn)行驗證。攻擊者必須和它們保持一致。
結(jié)論
有些人提倡,程序員在填充 SQL 模板時,應(yīng)該更加小心。應(yīng)對 SQL 注入問題,只是需要在編程方面多加小心。很明顯,這種方式算不上解決方案。人們?nèi)匀辉谛r炗脩糨斎胫捣矫娉霈F(xiàn)錯誤,最終接受了帶有惡意的用戶輸入值。換句話說,單憑我們所有人更努力地工作,是無法根本解決這種問題的。
真正的解決方案在于,SQL 語句本身的任意性,并要求所有現(xiàn)存不變量都符合任意的等價結(jié)構(gòu)的規(guī)則。無需程序員的干預(yù),就能自動完成。
攻擊者不得不符合一種未知的、任意的 brainfuck 語法的規(guī)則。想要符合一組未知的規(guī)則,將是難以解決的問題。因此,攻擊者通常無法得手。
更多關(guān)于MySQL相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《MySQL日志操作技巧大全》、《MySQL事務(wù)操作技巧匯總》、《MySQL存儲過程技巧大全》、《MySQL數(shù)據(jù)庫鎖相關(guān)技巧匯總》及《MySQL常用函數(shù)大匯總》
希望本文所述對大家MySQL數(shù)據(jù)庫計有所幫助。
相關(guān)文章
前端傳參數(shù)進(jìn)行Mybatis調(diào)用mysql存儲過程執(zhí)行返回值詳解
這篇文章主要介紹了前端傳參數(shù)進(jìn)行Mybatis調(diào)用mysql存儲過程執(zhí)行返回值詳解,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下2022-08-08
MySQL數(shù)據(jù)庫之?dāng)?shù)據(jù)data?基本操作
這篇文章主要介紹了MySQL數(shù)據(jù)庫之?dāng)?shù)據(jù)data?基本操作,文章基于MySQL的相關(guān)資料展開數(shù)據(jù)data?基本操作,具有一定的參考價值,需要的小伙伴可以參考一下2022-05-05
MySQL數(shù)據(jù)庫varchar的限制規(guī)則說明
本文我們主要介紹了MySQL數(shù)據(jù)庫中varchar的限制規(guī)則,并以一個實際的例子對限制規(guī)則進(jìn)行了說明,希望能夠?qū)δ兴鶐椭?/div> 2011-08-08
MySQL?5.7徹底卸載與重新安裝保姆級教程(附常見問題解決)
這篇文章主要介紹了MySQL?5.7徹底卸載與重新安裝保姆級教程的相關(guān)資料,步驟包括停止服務(wù)、卸載程序、刪除文件和注冊表項、清理環(huán)境變量等,還提供了安裝過程中常見問題的解決方案,需要的朋友可以參考下2025-11-11
mysql關(guān)聯(lián)子查詢的一種優(yōu)化方法分析
這篇文章主要介紹了mysql關(guān)聯(lián)子查詢的一種優(yōu)化方法,結(jié)合實例形式分析了針對MySQL的關(guān)聯(lián)子查詢進(jìn)行優(yōu)化的技巧,需要的朋友可以參考下2016-04-04
Mysql字符串截取函數(shù)SUBSTRING的用法說明
今天建視圖時,用到了MySQL中的字符串截取,很是方便。2011-06-06
探索MySQL?8中utf8mb4釋放多語言數(shù)據(jù)的強(qiáng)大潛力
這篇文章主要為大家介紹了探索MySQL?8中utf8mb4釋放多語言數(shù)據(jù)的強(qiáng)大潛力,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12最新評論

