2007年3月18日 星期日

程式漏洞與隱碼攻擊

摘自 Study Area
http://www.study-area.org/coobila/tutorial_373.html
網路上知名的 隱碼攻擊 (SQL Injection), 今天我們就來掀他的底...
什麼是隱碼攻擊 隱碼攻擊, 英文名字為SQL Injection, 是一種利用輸入SQL語法來對於各種SQL伺服器做資料竊取或是破壞的一種攻擊方式. 一個網站能不能用隱碼攻擊, 與伺服器資料輸入的寫法很大的關係.
一段含有漏洞的語法
Sql = "Select * From 資料表名稱 where name='" &request("name")& "' and password='" &request("password")& "'"
if rs.eof=true then
response.end
end if
這段ASP語法中的SQL利用使用者的輸入來尋找符合帳號以及密碼的資料, 如果找的到的話, 代表資料無誤 (rs.eof為false), 於是讓使用者進入會員區.乍聽之下是沒有什麼不對, 但是仔細看看程式碼...SQL說穿了就是幾段邏輯式而已, 只要SQL邏輯為True該資料就會被納入資料集合 (recordset).上面這段的SQL語法中含有兩個使用者輸入, 如果使用者今天輸入 name' or 'a'='a到name與password 中, 那SQL指令就被竄改成:
Sql = "Select * From 資料表名稱 where name='name' or 'a'='a' and password='name' or 'a'='a"
當然 name='name' 與 password='name' 不一定正確, 但是學過程式語言的人都曉得, OR運算元只要一個條件為True整個條件式就為True. 由於 'a' 是常數, 'a'永遠都是等於'a', 因此'a'='a'這個條件為True, 整個SQL條件式自然也為True.利用這種方法, 不管SQL碰到哪一筆資料, 條件式都是True, 除非資料表中沒有任何資料, 否則 rs.eof 都是 false, 當然, 攻擊者就可以大搖大擺的進入會員區了.如果再加上一些語法, 甚至可以用管理者帳號進入管制區, 進行更大的破壞.
如何修補漏洞 如果您將之前的語法稍微修改...
Sql = "Select * From 資料表名稱 where name='" &request("name")& "'"
if rs.eof=true
thenresponse.end
end if
if request("password")<>rs("password") then
response.end
end if
上面這段語法是先利用帳號名稱的輸入來尋找資料, 找到資料後再進行比對.假設攻擊者同樣使用 name' or 'a'='a 來進行攻擊, 第一段的SQL程式被竄改後 rs.eof 為 false, 過關!但是到了 request("password")<> rs("passworD") 這一段時, 進行比對的並不是使用SQL語法.request("password")的數值仍然是name' or 'a'='a而rs("password")是資料庫裡面的資料的密碼欄位, 兩者不相同, 當然就不讓攻擊者進入, 隱碼攻擊無效!
結語 小弟昨天上網去逛漏洞程式的來源網站, 發現該網站竟然也有相同的漏洞.該網站還是網路上有點知名度的程式庫, 由此可見現在網路上有多少網站仍然存在著這個漏洞. 如果大家有發現的話, 應該立刻通知網站管理者, 以免被有心人士利用.
本教學感謝阿德大大提供資料一起研究討論