posts - 3, comments - 0, trackbacks - 0, articles - 0
            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

          日歷

          <2010年11月>
          31123456
          78910111213
          14151617181920
          21222324252627
          2829301234
          567891011

          搜索

          •  

          最新評(píng)論

          SQL注射原理

          SQL 注射能使攻擊者繞過(guò)認(rèn)證機(jī)制,完全控制遠(yuǎn)程服務(wù)器上的數(shù)據(jù)庫(kù)。SQL是結(jié)構(gòu)化查詢(xún)語(yǔ)言的簡(jiǎn)稱(chēng),它是訪(fǎng)問(wèn)數(shù)據(jù)庫(kù)的事實(shí)標(biāo)準(zhǔn)。目前,大多數(shù)Web應(yīng)用都使用 SQL數(shù)據(jù)庫(kù)來(lái)存放應(yīng)用程序的數(shù)據(jù)。幾乎所有的Web應(yīng)用在后臺(tái)都使用某種SQL數(shù)據(jù)庫(kù)。跟大多數(shù)語(yǔ)言一樣,SQL語(yǔ)法允許數(shù)據(jù)庫(kù)命令和用戶(hù)數(shù)據(jù)混雜在一 起的。如果開(kāi)發(fā)人員不細(xì)心的話(huà),用戶(hù)數(shù)據(jù)就有可能被解釋成命令,這樣的話(huà),遠(yuǎn)程用戶(hù)就不僅能向Web應(yīng)用輸入數(shù)據(jù),而且還可以在數(shù)據(jù)庫(kù)上執(zhí)行任意命令了。
          登陸驗(yàn)證
          現(xiàn) 在以一個(gè)需要用戶(hù)身份認(rèn)證的簡(jiǎn)單的Web應(yīng)用程序?yàn)槔M(jìn)行講解。假定這個(gè)應(yīng)用程序提供一個(gè)登錄頁(yè)面,要求用戶(hù)輸入用戶(hù)名和口令。用戶(hù)通過(guò)HTTP請(qǐng)求發(fā)送 他們的用戶(hù)名和口令,之后,Web應(yīng)用程序檢查用戶(hù)傳遞來(lái)用戶(hù)名和口令跟數(shù)據(jù)庫(kù)中的用戶(hù)名和口令是否匹配。這種情況下,會(huì)要求在SQL數(shù)據(jù)庫(kù)中使用一個(gè)數(shù) 據(jù)庫(kù)表。
          對(duì)一個(gè)用戶(hù)進(jìn)行認(rèn)證,實(shí)際上就是將用戶(hù)的輸入即用戶(hù)名和口令跟表中的各行進(jìn)行比較,如果跟某行中的用戶(hù)名和口令跟用戶(hù)的輸入完全匹配,那么該用戶(hù)就會(huì)通過(guò)認(rèn)證。
          假如后臺(tái)的sql語(yǔ)句時(shí)這樣拼接的
          select id from test where username='"+myname+"' and password='"+mypasswd+"' ";
          表面上看,如果用戶(hù)名和口令對(duì)匹配,那么該用戶(hù)通過(guò)認(rèn)證;否則,該用戶(hù)不會(huì)通過(guò)認(rèn)證——但是,事實(shí)果真如此嗎?非也!讀者也許已經(jīng)注意到了,這里并沒(méi)有對(duì)SQL命令進(jìn)行設(shè)防,所以攻擊者完全能夠在用戶(hù)名或者口令字段中注入SQL語(yǔ)句,從而改變SQL查詢(xún) 。為此,我們仔細(xì)研究一下上面的SQL查詢(xún)字符串:
          上述代碼認(rèn)為字符串username和password都是數(shù)據(jù),不過(guò),攻擊者卻可以隨心所欲地輸入任何字符 。如果一位攻擊者輸入的用戶(hù)名為
          ’OR1=1—
          而口令為
          x
          雙劃符號(hào)--告訴SQL解析器,右邊的東西全部是注釋?zhuān)圆槐乩頃?huì)。這樣,查詢(xún)字符串相當(dāng)于:
          select id from test where username='' or 1=1;
          如 今的SELECT語(yǔ)句跟以前的已經(jīng)大相徑庭了,因?yàn)楝F(xiàn)在只要用戶(hù)名為長(zhǎng)度為零的字符串''或1=1這兩個(gè)條件中一個(gè)為真,就返回用戶(hù)標(biāo)識(shí)符ID——我們知 道,1=1是恒為真的。所以這個(gè)語(yǔ)句將返回user_table中的所有ID。在此種情況下,攻擊者在username字段放入的是SQL指令 'OR1=1--而非數(shù)據(jù)。
          更為嚴(yán)重的情況是當(dāng)username對(duì)應(yīng)的是'OR1=1;DROPTABLEuser_table;--
          數(shù)據(jù)庫(kù)中執(zhí)行的sql語(yǔ)句就變成了:
          select id from test where username='' or 1=1;drop table test
          這個(gè)語(yǔ)句將執(zhí)行句法上完全正確的SELECT語(yǔ)句,并利用drop命令清空test表。
          應(yīng)對(duì)策略
          問(wèn)題的關(guān)鍵就是不要用string構(gòu)造sql語(yǔ)句,這樣就不會(huì)利用輸入的參數(shù)構(gòu)造sql語(yǔ)句了。所以要用PreparedStatement替換Statement,即用占位符作為實(shí)參定義sql語(yǔ)句,從而避免sql注入攻擊。
          不管什么框架,還是純JDBC,只用Preparedstatement,一定要用占位符作為實(shí)參來(lái)構(gòu)造sql(或hql)語(yǔ)句。

          String sql= "select * from test where usernmae=? and password=? " ;
          PreparedStatement psm=conn.preparedStatement(sql);
          psm.setString(1,myname);
          psm.setString(2,mypasswd);
          Result rs=psm.executeQuery();

          if (rs.next){
          rs.close();
          con.close();
          return false ;
          }
          else {
          rs.close();
          con.close();
          return true ;
          }


          只有注冊(cè)用戶(hù)登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 盱眙县| 济南市| 监利县| 河东区| 沂南县| 当阳市| 铁岭县| 黄平县| 和顺县| 西乌| 赣州市| 苍溪县| 云林县| 文登市| 区。| 剑川县| 丰原市| 黄骅市| 仁化县| 吉隆县| 牙克石市| 淳化县| 达孜县| 富顺县| 收藏| 榆社县| 赤城县| 浮梁县| 克什克腾旗| 新干县| 化德县| 呼和浩特市| 阿拉善盟| 奇台县| 岑巩县| 博野县| 罗定市| 长阳| 临颍县| 图片| 林甸县|