天天看點

java安全編碼指南之:輸入注入injection

文章目錄

簡介

sql注入

java中的sql注入

使用preparedstatement

xml中的sql注入

xml注入的java代碼

注入問題是安全中一個非常常見的問題,今天我們來探讨一下java中的sql注入和xml注入的防範。

什麼是sql注入呢?

sql注入的意思是,使用者輸入了某些參數,最終導緻sql的執行偏離了程式設計者的本意,進而導緻越權或者其他類型的錯誤。

也就是說因為使用者輸入的原因,導緻sql的涵義發送了變化。

拿我們最常用的登入的sql語句來說,我們可能會寫下面的sql語句:

我們需要使用者傳入username和password。

怎麼對這個sql語句進行注入呢?

很簡單,當使用者的username輸入是下面的情況時:

那麼整個sql語句将會變成:

如果somebody是一個有效的使用者,那麼or後面的語言完全不會執行,最終導緻不校驗密碼就傳回了使用者的資訊。

同樣的,惡意攻擊者可以給password輸入下面的内容可以得到同樣的結果:

整個sql解析為:

這條語句将會傳回所有的使用者資訊,這樣即使不知道确定存在的使用者名也可以通過sql語句的判斷。

這就是sql注入。

java中最常用的就是通過jdbc來操作資料庫,我們使用jdbc建立好連接配接之後,就可以執行sql語句了。

下面我們看一個java中使用jdbc sql注入的例子。

先建立一個通用的jdbc連接配接:

然後再自己拼裝sql語句然後調用:

上面的例子中,隻有username會發生注入,password不會,因為我們使用了encodepassword方法對password進行了轉換:

為了防止sql注入,我們一般推薦的是使用preparedstatement,java.sql.preparedstatement可對輸入參數進行轉義,進而防止sql注入。

注意,一定要正确的使用preparedstatement,如果是不正确的使用,同樣會造成sql注入的結果。

下面看一個不正确使用的例子:

上面的代碼中,我們還是自己進行了sql的拼裝,雖然最後我們使用了preparedstatement,但是沒有達到效果。

正确使用的例子如下:

我們需要将使用者輸入作為參數set到preparedstatement中去,這樣才會進行轉義。

可擴充标記語言(xml)旨在幫助存儲,結構化和傳輸資料。 由于其平台獨立性,靈活性和相對簡單性,xml已在許多應用程式中得到使用。 但是,由于xml的多功能性,它容易受到包括xml注入在内的各種攻擊的攻擊。

那麼什麼是xml注入呢?我們舉個例子:

上面的例子中,我們使用了xml定義了一個iphone20的價格和數量。一個iphone20 5000塊。

上面的xml中,如果quantity是使用者輸入的資料的話,那麼使用者可以這樣輸入:

最後得出的xml檔案如下:

一般來說,我們在解析xml的過程中,如果發現有重複的tag,那麼後面的tag會覆寫前面的tag。

結果就是1個iphone20現在的價格是20塊,非常劃算。

我們看下xml的注入在java代碼中是怎麼實作的:

可以看到我們直接使用使用者輸入的quantity作為xml的拼接,這樣做很明顯是有問題的。

怎麼解決呢?有兩種方法。

第一種方法

第一種方法就是對使用者輸入的quantity進行校驗:

上面代碼中,我們對quantity進行了integer的轉換,進而避免了使用者的非法輸入。

第二種方法

第二種方法是使用xml schema,來對生成的xml進行格式校驗。

先看一下我們改怎麼定義這個xml schema:

上面我們定義了一個xml element的序列sequence。如果使用者輸入了非定義格式的其他xml,就會報錯。

我們看下相對應的java代碼該怎麼寫:

上面我們列出了xml驗證的代碼,完整的代碼可以參考文末的代碼連結,這裡就不一一貼出來了。

本文的代碼:

learn-java-base-9-to-20/tree/master/security