SQL注入簡單入門

SQL注入

寫在前面

談到SQL注入,那麼自然和數據庫有很大的關係。先說數據庫,數據庫大致可以分爲Access數據庫、MySQL數據庫、SQLServer數據庫、Oracle數據庫等。Access數據庫是比較早期的應用於Web應用的數據庫。但是近幾年Access數據庫的使用再逐漸地減少,這是因爲它不能適應大量用戶的訪問,而且安全性沒有其他的數據庫高。而現在使用的比較多的是MySQL數據庫。SQLServer和Oracle在大型公司比較適用。

1、原理

SQL語言時一門解釋型語言,由一個運行時組件解釋代碼並且執行其中的指令。Python也是一種解釋型語言。

基於解釋型語言的執行方式,會產生一系列叫代碼注入的漏洞,SQL就是其中的一種。攻擊者只需要提交專門設計的SQL語句,向Web應用程序攻擊。結果,解釋器就會將這其中一部分的輸入解釋爲程序指令來執行了,就和一開始程序員寫好的代碼一樣。因此,SQL注入漏洞就隨之形成了。

除了語言本身的原因,SQL注入產生的另一個原因就是沒有對輸入或提交數據進行過濾。在編寫Web應用時,由於其自主訪問控制性質,程序員一般會對用戶輸入的信息進行一定程度上的過濾操作,過濾掉一些危險字符,如or、單引號、註釋符等。但是也會存在一些經驗不足的程序員忽視這個問題,從而導致過濾規則不到位,最後就導致SQL注入漏洞的出現,以至於被攻擊者利用。

2、注入分類

主要由3種不同類型的注入點,它們分別是數字型、字符型和搜索型。在編寫實際的web應用時,程序員會根據不同的數據類型編寫不同的查詢代碼。

例如:

(“?”表示需要輸入的數據)

數字型:SELECT * FROM user WHERE id = ?

字符型:SELECT * FROM user WHERE username = ‘?’

搜索型:SELECT * FROM user WHERE username = ‘%?%’

每個類型在輸入數據的時候,對數據進行了一定的規範,因此,才產生了這樣的劃分。重點是要去區分類型。上面的這種區分知識從數據角度進行的劃分,它們的注入步驟和原理都是一樣的。

對於安全人員而言,工具僅是一種實現滲透的手段,不能過多依賴於工具的操作。因爲工具也是安全人員爲了簡化步驟而編寫出來的。對於剛剛接觸的人而說,工具會很方便,但是瞭解原理才真正掌握了這個漏洞。工具確實很方便,感覺工具讓初學者感到舒適,不過還是要學習原理的。畢竟原理纔是最重要的。

那麼就開始SQL注入探索之旅了!!!

這裏我用的是DVWA,之前的博客由介紹過DVWA,不知道的朋友可以去查訪,也可以自行查找資料。

在DVWA裏選擇了low的security level,然後選擇到了SQL注入模塊,在輸入框中輸入1,然後提交,得到如下的結果。

在這裏插入圖片描述

從上圖中可以看出,輸入一個數字後,返回了一個ID=1的查詢結果。以此爲例,在進行注入點判斷的時候,按照一般步驟,輸入數字時會考慮這是一個數字型的注入點,所以會先按照數字型的方式操作注入點。

在其中輸入1 and 1 = 1試試,結果如下:

在這裏插入圖片描述

看結果可以看出ID現在是1 and 1=1,很明顯,沒有達到我要的效果,這裏的ID不是數字型而是個字符型。所以我對注入點類型的判斷就變爲字符型了。

接下來就要去判斷這個注入點是否是有效的。在很多的實際操作中,某些應用程序雖然會允許這樣的輸入操作發生,當它在後端實際是過濾了該部分。所以不一定會由操作效果。那麼就用一個經典的操作來判斷注入點是否有效。

在其中輸入1‘ and ’1’=‘1結果如下:

在這裏插入圖片描述

再輸入1’ and ’1‘=’2,結果如下:

在這裏插入圖片描述
這裏出現了兩種不同的結果,而這兩種結果證明了這個注入點是有效的。and 1=1是一個永真命題,and後面的條件是永遠成立的,而and 1=2正好相反,1=2是一個永假命題,and後面的條件不成立。對於web應用來說,再條件不成立的情況下就也不會將結果返回給用戶,所以後者的查詢結果中看不到數據。

不同的數據庫可能會有不同的操作。

MySQl數據庫允許使用聯合查詢方法,這樣查詢更加便捷。那麼我們判斷完注入點後,應該要判斷數據表的列數,那麼就輸入1' order by 1#。結果如下:

在這裏插入圖片描述

正常顯示了ID=1的數據,說明一下1' order by 1#,其中的order by是根據列值查找的命令,找不到就會報錯。#起到的作用是註釋,這個和Python一樣,註釋後防止後續語句干擾。接下來繼續試1' order by 6#,直到確定列數。結果如下:

在這裏插入圖片描述

這裏就明顯是報錯了,找不到列值爲6的列。這就說明這個數據表裏不存在6列,然後繼續按照這個步驟,可以從1開始往上試(直到出現報錯)或者從6開始往下試(或者正常顯示)。這樣我就可以確定表中究竟有多少列,接下來我一個個試後,發現DVWA的security:low的表只有2列。

知道了列數爲2列之後,我們要看MySQL數據庫的版本,從MySQL5.0版本開始的版本具有information_schema數據庫,裏面有所有數據庫的數據表名和列名。我可以利用這個數據庫來進行數據的檢索,所以在此之前需要查看使用的MySQL數據庫的版本,輸入1' union select version (),2#,提交,結果如下:

在這裏插入圖片描述

可以看到數據庫版本是5.5.53,知道了版本號,就可以使用information_schema來完成後續的操作。

輸入1' union select table_name,2 from information_schema.tables where table_schema=database()#,結果如下:

在這裏插入圖片描述

由此可以看出圖中顯示了兩個表名,一個是guestbook,一個是users。但是可能沒有看懂上面輸入的是說明意思。不慌,這就理解說明一下,information_schema數據庫中含有tables這個數據表,條件是表數據庫名與database()相同,而database()正是當前查詢的數據庫。

然後查詢列名。

輸入1' union select group_concat(column_name),2 from information_schema.columns where table_name = 'user'#,結果如下。

在這裏插入圖片描述

一共可以看到11個列名,輸入語句其實與上面那句類似,就是找到那個數據表中的列名。有了這些數據,我就可以列出想要的數據了,輸入1' union selcet user,password from users#,結果如下:

在這裏插入圖片描述

我們就可以得到用戶名和密碼了,這裏的密碼使用的都是MD5加密,可以利用MD5在線解密工具解密。

這差不多就是手工注入的步驟。

總結一下就是:找注入點—>判斷數據庫的列數—>查看數據庫版本—>獲取數據庫名—>獲取數據表名—>獲取數據列名—>爆出數據。

3、SQL注入工具

SQL注入工具有很多,比較好用的有Pangolin和SQLMap工具。這兩個工具對於初學者來說,上手難度不大。

Pangolin是一款幫助滲透測試人員進行SQL注入測試的安全工具。Pangolin和JSky都是NOSEC公司的產品。Pangolin具備友好的圖形界面並支持測試幾乎所有的數據庫。

SQLMap是一個自動SQL注入工具,可以執行一個廣泛的數據庫,管理系統後端指紋,檢索DBMS數據庫、username、表格、列,並列舉整個DBMS信息。SQLMap提供轉儲數據庫表以及MySQL、PostgreSQL、SQLServer服務器下載或上傳任何文件並執行任意代碼的能力。

注:DBMS:Database Management System,數據庫管理系統

我一般喜歡用SQLMap,這裏實在Windows環境下的演示:

打開cmd,到sqlmap所在的目錄,

輸入:python sqlmap.py -u"http://127.0.0.1/DVWA/vulnerabilities/sqli/?id=1&Submit=Submit#" --cookie="security=low; PHPSESSID=ec88uk1ch1p4872supj3vp2mj3" --current-db

在這裏插入圖片描述

可以看到當前的數據庫名爲dvwa,之後輸入:

python sqlmap.py -u"http://127.0.0.1/DVWA/vulnerabilities/sqli/?id=1&Submit=Submit#" --cookie="security=low; PHPSESSID=ec88uk1ch1p4872supj3vp2mj3" -D dvwa --tables

在這裏插入圖片描述

可以看到有兩個表名,一個是guestbook,一個是users。這個和之前的手工注入效果是一樣的。

接下來繼續,我輸入python sqlmap.py -u"http://127.0.0.1/DVWA/vulnerabilities/sqli/?id=1&Submit=Submit#" --cookie="security=low; PHPSESSID=ec88uk1ch1p4872supj3vp2mj3" -D dvwa -T users --columns

在這裏插入圖片描述

一共有8個列名,之後就dump數據就ok了。之前手工注入的時候多顯示了 3個列,不過問題不大,輸入python sqlmap.py -u"http://127.0.0.1/DVWA/vulnerabilities/sqli/?id=1&Submit=Submit#" --cookie="security=low; PHPSESSID=ec88uk1ch1p4872supj3vp2mj3" -D dvwa -T users -C user,password --dump

在這裏插入圖片描述

這樣就可以得到我們想要的賬號和密碼,這裏的密碼的MD5值也被解出了。
SQLMap自帶字典可以用來破解比較簡單的密碼。從操作上來看的話,SQLMap是一款很不錯的自動注入工具,但是在安全級別較高的應用中,SQLMap的使用還是比較有限的。不過對於新手而言確實是很友好的工具。我一開始接觸SQL注入,就使用了這一款工具,感覺確實很不錯,新手也很容易上手,就是真正來說還是要會手工注入比較好,貼近原理。

4、預防SQL注入

對於服務器層面的防範,應該保證生產環境的Webshelll是關閉錯誤信息的。例如,PHP生產環境的配置php.ini中的display_error是off,這樣就可以關閉服務器的錯誤提示。關閉了錯誤提示是有利於混淆視聽的,可以一定程度上干擾攻擊者,另外可以從編碼方面去預防SQL注入。

最好是使用預編譯語句來防禦SQL注入,就是使用預編譯語句綁定變量。

例如在JSP中使用的預編譯的SQL語句。

String sql="SELECT * FROM users where username = ?";
PreparedStatement pstmt = connection. prepareStatement();
pstmt.setString(1,admin);

?處與後面的輸入的變量相互綁定,之後攻擊者如果使用and 1=1之類的語句,應用程序會將整個部分當作是username來進行檢索數據庫,而不會造成修改語義的問題。

還可以檢查變量類型和格式。如果要求用戶輸入的數據是整型的,那麼就可以在查詢數據庫之前檢查一下獲取到的變量是否爲整型,如果不是整型就要重新校正。還有就是一些比較特殊的格式類型,如日期、時間、郵件等格式。總體而言,如果變量有固定的格式,在SQL語句執行前,就應該嚴格地按照要求去檢查,可以很大程度預防SQL注入攻擊。

還要一種方法就是過濾一些特殊符號。在SQL注入時,往往需要一些特殊的符號幫助我們編寫語句,如'#"等。可以將這些符號都進行轉義處理或使用正則表達式過濾掉。

除了編碼層面的預防,還需要做到數據庫層面的權限管理,儘量減少在數據庫中使用Root權限直接查詢的次數。如果有多個應用程序使用同一個數據庫,那麼數據庫應該分配好每個應用程序的權限。

參考文獻

[1]陳鐵明.網絡空間安全實戰基礎:第一版.北京:人民郵電出版社,2018

發佈了22 篇原創文章 · 獲贊 27 · 訪問量 5595
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章