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 转义清单
Ø &->&
Ø <-><
Ø >->>
l 转移函数
Ø Encode.forXmlContent(userData)。
l 例子与说明
<name>Encode.forXmlContent(userData)</name>
2)编码内容:XML属性
l 转义清单
Ø &->&
Ø <->%lt;
Ø "->"
Ø '->'
l 转移函数
Ø Encode.forXmlContent(userData)。
l 例子与说明
<nameid=Encode.forXmlContent(userData)>XXX</name>
3)编码内容:XML内容和属性
l 转义清单
Ø &->&
Ø <-><
Ø >->>
Ø "->"
Ø '->'
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注入就成为。
…
<adminid=Ś">
<>name > hack</name>
< password > c331… 2059</password>
</admin >
…
这样就不可以用创建的用户登录了。
案例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":"admin@mydomain.com"}
{"username":"root","password":"root","email":"root@mydomain.com"}
{"username":"hack","password":"aabbccd","email":"hack@mydomain.com"}
{"username":"jerry","password":"hzynk","email":"jerrygu@mydomain.com"}
]}
假设仍旧为用户注册,用户名和密码存在JSON文件中,按照案例4-1的思路,就会产生JSON注入,在这里不做更多地介绍。
防止JOSN注入的方法很简单,只需要对以下两个字符进行转义。
l "(双引号)——>\"。
l \(转义号)——> \\。