軟體安全性測試(連載12)

  • 2020 年 2 月 10 日
  • 筆記

2.6其他程式碼注入

除了XSS注入外,還存在XML注入、JSON注入和XPath注入三種程式碼注入情形。

1. XML注入

XML注入是指將惡意程式碼注入到XML文件中,比如存在一個user.xml表。

…  <admin id="1">  <username>admin</username>  <password>a384b6463fc216a5f8ecb6670f86456a</password>  </admin>  <admin id="5">  <username>root</username>  <password>eb89f40da6a539dd1b1776e522459763</password>  </admin>  …

其中記錄的資訊是登錄到某個系統的用戶名和密碼帳號資訊。假設有這麼一段資訊被注入進來,這個黑客就很容易進入系統,從而帶來威脅。

<adminid="6">  <username>hack</username>  <password>c331 … 2059 </password>  </admin>   這樣這段HTML文本變為。  …  <admin id="1">  <username>admin</username>  <password>a384b6463fc216a5f8ecb6670f86456a</password>  </admin>  <admin id="5">  <username>root</username>  <password>eb89f40da6a539dd1b1776e522459763</password>  </admin>  <admin id="6">  <username>hack</username>  <password>c331 … 2059</password>  </admin>  …

黑客可以利用嵌入的用戶名和密碼登錄(註:正如1.5-1所示,基於MD5加密的密文可以通過「彩虹表」軟體來破譯)。

對於XML的防禦措施主要通過對特殊字元的轉義。再來看一下OWASP 的ESAPI函數是如何來實現XML轉義的。

1)編碼內容:XML內容

l 轉義清單

Ø &->&amp;

Ø <->&lt;

Ø >->&gt;

l 轉移函數

Ø Encode.forXmlContent(userData)。

l 例子與說明

<name>Encode.forXmlContent(userData)</name>

2)編碼內容:XML屬性

l 轉義清單

Ø &->&amp;

Ø <->%lt;

Ø "->&#34

Ø '->&#39

l 轉移函數

Ø Encode.forXmlContent(userData)。

l 例子與說明

<nameid=Encode.forXmlContent(userData)>XXX</name>

3)編碼內容:XML內容和屬性

l 轉義清單

Ø &->&amp

Ø <->&lt;

Ø >->&gt;

Ø "->&#34

Ø '->&#39

l 轉移函數

Ø Encode.forXml (userData)。

l 例子與說明

<name>Encode.forXml(userData)</name>

4)編碼內容:XML注釋

l 轉義清單

Ø 無效字元->空格

Ø —>-

l 轉移函數

Ø Encode.forXmlComment(comment)。

l 例子與說明

<!–"+Encode.forXmlComment(comment)+"–>

5)編碼內容:XML的DTD

l 轉義清單

Ø 非法字元->空格

Ø 終止符:]]>->]]]]><!CDAT[>

l 轉移函數

Ø Encode.forCDATA(…)。

l 例子與說明

<xml-data><![CDATA[<%=Encode.forCDATA(…)%>]]></xma-data>

經過轉碼,上面的XML注入就成為。

&lt;adminid=&#346&#34&gt;

&lt;>name &gt; hack</name&gt;

&lt; password &gt; c331… 2059&lt;/password&gt;

&lt;/admin &gt;

這樣就不可以用創建的用戶登錄了。

案例4-1 XML注入

註冊介面,用戶名與密碼存儲在user.xml文件中。網站採用jsp+javabean格式。Javabean程式碼如下。

import java.io.File;  import java.io.FileWriter;  public addUser(Stringusername,String password) throws Exception{          File file= newFile("user.xml");          FileWriter filewriter = newFileWriter(file);          String xml_cointent="<?xmlversion="1.0" encode="UTF-8">n"          +"<root>n"+          "<user>n"+          "<username>"+ username+"</username>n"+         "<password>"+password+"</password>n"+          "</user>n"+          "</root>n";          filewriter.write(xml_cointent);          filewriter.flush();          filewriter.close();      }

當用戶輸入用戶名Jerry,密碼123456,user.xml如下。

<?xml version="1.0"encode="UTF-8">  <root>  <user>  <username>Jerry</username>  <password>123456</password>  </user>  </root>   如果用戶輸入用戶名Jerry,密碼123456</password>n<role>admin</role>n<password>,密碼123456,user.xml就變成。  <?xml version="1.0"encode="UTF-8">  <root>  <user>  <username>Jerry</username>  <password>123456</password>  <role>admin</role>  <password></password>  </user>  </root>

從而達到了XML注入的目的。(當然,專業的註冊方法沒有那麼簡單,這裡僅僅作為XML注入進行介紹)。

2. XPath注入

XPath是定位DOM樹的一門技術(關於DOM樹在2.1-1 XSS分類,DOM型 XSS中介紹過)。利用XPath可以查詢XML中的元素。

案例4-2 XPath注入

系統用戶名密碼存在如案例4-1所在的user.xml中。通過頁面的登錄程式實現登錄功能。JAVA程式碼如下。

    importjava.io.File;  import java.util.List;  import org.dom4j.Document;  import org.dom4j.Element;  import org.dom4j.Node;  import org.dom4j.io.SAXReader;  public boolean login(String username,String password) throws Exception{          SAXReadersax=new SAXReader();          Documentdocument=sax.read(new File(".\user.xml"));          Stringxpath ="//user[username/text()='+username+'andpassword/text()='+password+']";          List<Node>nodes= document.selectNodes(xpath);          inti=0          for(Node node:nodes){              if(node instanceof Element){                  Elementelement=(Element) node;                  System.out.println("Id:"+element.attributeValue("id"));                  System.out.println("UserName:"+element.elementText("username"));                  System.out.println("Password:"+element.elementText("password"));                  i++              }          if(i==0){returnfalse;} else{return true;}      }      }   當輸入用戶名Jerry,密碼123456,登錄正確。但是當用戶輸入用戶名Hack,密碼myadmin' or '1'='1,如SQL注入一樣仍舊可以登錄。輸出所有的記錄。  Id:1  UserName:admin  Password:myadmin6548  Id:2  UserName:root  Password:qwert  Id:3  UserName:jerry  Password:123456  運行上面的程式碼需要以下四個jar文件。  l dom4j-1.6.1.jar。  l jaxen-1.1-beta-6.jar。  l log4j-1.2.16.jar。  l slf4j-nop-1.5.8.jar。

對於XPath可以通過以下方式進行。

l 對用戶的輸入進行合理驗證,對特殊字元(如<、>、'、"等)等進行轉義。過濾可以在客戶端和服務端兩邊實現,如果可能的話,建議兩者同時進行過濾OWASP的ESAPI提供了encodeForXPATH()方法。

對上面的。

String xpath="//user[username/text()='jerry'and password/text()=' or'1'='1']";

加入encodeForXPATH()方法,成為。

String encode_xpath = ESAPI.encode().encodeForXPATH("username/text()='jerry'andpassword/text()=' or '1'='1'");

String xpath ="//user/name[text()='"+ encode_xpath+'"]";

l 創建一份安全字元白名單,確保 XPath 查詢中由用戶控制的數值完全來自於預定的字符集合,不包含任何 XPath元字元。

l 使用源程式碼靜態分析工具,進行自動化的檢測,可以有效的發現源程式碼中的XPath 注入問題。

可以看見XML注入存在於寫XML文件,而XPath注入在於查詢XML文件,後面介紹的XXE漏洞是對XML實體變數的讀取。

3. JSON注入

JSON程式碼如下。

{"users":[  {"username":"admin","password":"123456","email":"[email protected]"}  {"username":"root","password":"root","email":"[email protected]"}  {"username":"hack","password":"aabbccd","email":"[email protected]"}  {"username":"jerry","password":"hzynk","email":"[email protected]"}  ]}

假設仍舊為用戶註冊,用戶名和密碼存在JSON文件中,按照案例4-1的思路,就會產生JSON注入,在這裡不做更多地介紹。

防止JOSN注入的方法很簡單,只需要對以下兩個字元進行轉義。

l "(雙引號)——>"。

l (轉義號)——> \。