安全漏洞之SQL注入和shell注入
SQL注入
發生部位
SQL注入安全漏洞發生于應用程序和數據庫之間。
原理
當攻擊者在輸入的字符串之中注入SQL指令,由于程序沒有設置相關的字符檢查,那么這些指令就會被數據服務器認為是正常的SQL指令并執行,因此,數據服務器就會遭到破壞或者數據被泄露出去。
示例
某個網站的登錄驗證的SQL查詢代碼為
strSQL = "SELECT * FROM users WHERE (name = '" + userName + "') and (pw = '"+ passWord +"');"惡意填入
userName = "1' OR '1'='1";與
passWord = "1' OR '1'='1";時,將導致原本的SQL字符串被填為
strSQL = "SELECT * FROM users WHERE (name = '1' OR '1'='1') and (pw = '1' OR '1'='1');"也就是實際上運行的SQL命令會變成下面這樣的
strSQL = "SELECT * FROM users;"因此達到無賬號密碼,亦可登錄網站。所以SQL注入被俗稱為黑客的填空游戲。
SQL注入方式
-
數字型輸入
上面的示例就是一種數字型輸入。再比如,在瀏覽器地址欄輸入:learn.me/sql/article.php?id=1,這是一個get型接口,發送這個請求相當于調用一個查詢語句:
$sql = "SELECT * FROM article WHERE id =",$id正常情況下,應該返回一個id=1的文章信息。那么,如果在瀏覽器地址欄輸入:learn.me/sql/article.php?id=-1 OR 1 =1,這就是一個SQL注入攻擊了,可能會返回所有文章的相關信息。因為1=1一定是true,所以整個where語句永遠是true,那么查詢的結果相當于整張表的內容。
-
字符型輸入
用戶登錄時調用接口learn.me/sql/login.html,首先連接數據庫,然后后臺對post請求參數中攜帶的用戶名、密碼進行參數校驗,即sql的查詢過程。假設正確的用戶名和密碼為user和pwd123,輸入正確的用戶名和密碼、提交,相當于調用了以下的SQL語句:
SELECT * FROM user WHERE username = 'user' ADN password = 'pwd123'由于用戶名和密碼都是字符串,SQL注入方法即把參數攜帶的數據變成mysql中注釋的字符串。
(1)’#’:’#'后所有的字符串都會被當成注釋來處理
SELECT * FROM user WHERE username = 'user'#'ADN password = '111' SELECT * FROM user WHERE username = 'user'(2)’-- ’ (–后面有個空格):’-- '后面的字符串都會被當成注釋來處理
SELECT * FROM user WHERE username = 'user'-- 'AND password = '111' SELECT * FROM user WHERE username = 'user' -
搜索型輸入
當在搜索框搜索的時候,稱為搜索型。搜索型與數字型注入最大的區別在于:數字型不需要百分號閉合,而搜索類型一般要使用百分號來閉合。
如何防御SQL注入
- 在設計應用程序時,完全使用參數化查詢(Parameterized Query)來設計資料訪問功能。
- 在組合SQL字符串時,先針對所傳入的參數加入其他字符(將單引號字符前加上轉義字符)。
- 如果使用PHP開發網頁程序的話,需加入轉義字符之功能(自動將所有的網頁傳入參數,將單引號字符前加上轉義字符)。
- 使用php開發,可寫入html特殊函數,可正確阻擋XSS攻擊。
- 其他,使用其他更安全的方式連接SQL數據庫。例如已修正過SQL注入問題的數據庫連接組件,例如ASP.NET的SqlDataSource對象或是 LINQ to SQL。
- 增強WAF的防御力
shell注入(OS命令注入)
發生部位
程序中調用系統命令的地方。
原理
通常情況下,Web應用程序會有需要執行shell命令的時候,有可能只是使用Unix sendmail程序發送電子郵件,或運行指定的Perl和C + +程序。從開發的角度來看,這樣做可以減少程序的開發時間。然而,如果攻擊者以構造特殊命令字符串的方式,把惡意代碼輸入一個編輯域(例如缺乏有效驗證的輸入框),從而傳遞到后臺程序,惡意命令代碼一旦執行,就會導致信息泄露或者正常數據的破壞,甚至可能導致惡意命令掌控該用戶的電腦和他們的網絡。
示例
String imageName = (String) params.get("imageName"); String cmd = "docker pull " + imageName; Process process = Runtime.getRuntime().exec(cmd); // ...在上面的Java代碼中,前端傳遞docker鏡像名至后端服務器,由后端服務器調用docker pull命令拉取對應的鏡像文件。當前端傳入的imageName參數值為正常的鏡像名稱時(如nginx),會執行docker pull nginx命令拉取nginx鏡像。而當前端傳入的imageName參數值為nginx; echo hacked,即帶有惡意指令echo hacked時,后端程序將在執行docker pull nginx成功后執行echo hacked命令。此處為了演示方便以及避免造成誤操作,所以采用了直觀且無害的echo命令。在終端直接運行該命令的結果如下所示:
# 示例中省略了執行結果與本文無關的一些輸出信息 $ docker pull nginx; echo hacked Status: Downloaded newer image for nginx:latest docker.io/library/nginx:latest hacked # <- 此處為執行惡意命令的結果shell注入方式
shell注入主要就是利用了一些符號的的特殊作用,下面介紹幾種常見的符號。
-
; 連續指令
command1; command2表示執行完command1后繼續執行command2,上面的示例就是采取了這種方式。
-
管道 |
command1 | command2表示先執行command1,然后將command1的輸出作為command2的輸入,再執行command2。例如:
$ ping -c 4 127.0.0.1 | grep loss 4 packets transmitted, 4 packets received, 0.0% packet loss # grep loss會輸出ping -c 4 127.0.0.1結果中含loss字段的行 -
& 后臺執行
command1 & command2表示在后臺執行command1,在前臺執行command2。例如:
$ ping -c 4 127.0.0.1 & echo hacked [1] 2333 # <- ping命令的進程號 hacked # <- echo hacked的執行結果 PING 127.0.0.1 (127.0.0.1): 56 data bytes # ... ping的執行結果注: ping命令涉及網絡I/O,所以輸出在echo命令之后,而非ping命令在echo之后執行。
-
&&與||
command1 && command2或command1 || command2
二者的區別為&& command2中的command2僅在command1執行成功后(退出碼為0)執行,而|| command2中的command2僅在command1執行失敗(退出碼為非0值)后執行。
-
command與$(command)
當命令為command1 $(command2)時(command1command2``同理),command2的輸出將作為command1的參數。例如用戶輸入的參數為$(echo hacked)時,程序在執行ping之前將會先執行echo hacked命令。
除了上述幾種shell注入的方式以外,例如重定向(>、>>、<、<<)等也可能被攻擊者所利用。
如何防御shell注入
-
避免直接執行用戶輸入的命令
-
對用戶輸入的參數進行校驗
-
過濾常見的符號
-
使用黑白名單機制
-
使用語言提供的轉碼方法
-
使用最少權限的用戶運行程序
…
參考
維基百科
博客1
博客2
博客3
總結
以上是生活随笔為你收集整理的安全漏洞之SQL注入和shell注入的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 暴风魔镜 光标漂移_如何防止光标在游戏过
- 下一篇: 第十六章 SQL命令 CREATE TA