一个合格程序猿应该知道的基础知识—XML注入介绍
Posted 安全犀牛
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一个合格程序猿应该知道的基础知识—XML注入介绍相关的知识,希望对你有一定的参考价值。
(图片源于网络,侵删)
ps:竟然有人说我是教小学生的!我就不信小学生能看懂我今天给的东西!
XML,Extensible Markup Language,扩展性标识语言。文件的后缀名为:.xml。就像html的作用是显示数据,XML的作用是传输和存储数据。今天阿姨给你们详细介绍一下关于XML的知识(敲黑板!文章略长,请仔细阅读)
1
XML定义
XML由3个部分构成,它们分别是:文档类型定义(Document Type Definition,DTD),即XML的布局语言;可扩展的样式语言(Extensible Style Language,XSL),即XML的样式表语言;以及可扩展链接语言(Extensible Link Language,XLL)。
XML:可扩展标记语言,标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言。
它被设计用来传输和存储数据(而不是储存数据),可扩展标记语言是一种很像超文本标记语言的标记语言。设计宗旨是传输数据,而不是显示数据。它的标签没有被预定义。你需要自行定义标签。
它被设计为具有自我描述性,是W3C的推荐标准。是用来传输和存储数据,其焦点是数据的内容。
2
XML作用
XML应用于wed开发的许多方面,最常用的作用就是配置文件和数据读写操作。
配置文件
许多应用都将配置数据存储在各种文件里,比如.INI文件。虽然这样的文件格式已经使 用多年并一直很好用,但是XML还是以更为优秀的方式为应用程序标记配置数据。使用. NET里的类,如XmlDocument和XmlTextReader,将配置数据标记为XML格式,能使其更具可读性,并能方便地集成到应用系统中去。使用XML配置文件的应用程序能够方便地处理 所需数据,不用象其他应用那样要经过重新编译才能修改和维护应用系统。
数据读写操作
在真实的世界中,计算机系统和数据使用不兼容的格式来存储数据。XML 数据以纯文本格式进行存储,因此提供了一种独立于软件和硬件的数据存储方法。这让创建不同应用程序可以共享的数据变得更加容易通过 XML,可以在不兼容的系统之间轻松地交换数据。对开发人员来说,其中一项最费时的挑战一直是在因特网上的不兼容系统之间交换数据。由于可以通过各种不兼容的应用程序来读取数据,以 XML 交换数据降低了这种复杂性。
3
XML格式说明
也可以是这样
两种方式都是xml,都很直观,附带了对数据的说明,并且具备通用的格式规范可以让程序做解析。如果用json格式来表示的话,就是下面这样
其实数据都是一样的,不同的只是数据的格式而已,同样的数据,我用xml格式传给你,你用xml格式解析出三个数据。
4
XML的实体
XML实体分为:参数实体和通用实体两种。参数实体用在DTD定义中。一般的xml文档中都使用通用实体。这里只介绍通用实体。
使用实体之前,必需先声时,声明语句位于xml文档的序言的内部子集中,实体声明必需使用大写方式,如:<!ENTITY myentity "这是一个实体"> ,ENTITY必需是大写的。
使用实本时,在实体名称前面加上 & ,并表在后面加上分号: ;。与HTML中的转义符类似。在以下xml中:&client;引用了一个实体,&241;引用了一个实体。当xml处理器碰到实体引用时,会使用定义实体时设定的值去代替实体声时。
如下面的示例,当处理器解析到&client;时, 会使用"Mr.Rufus Xavier Sasperilla"来代替这个&client;在解析后的文本中,是看不到&client;的。
字符实体
字符实体用来代表单个字符。字符实体分为以下三种:
a、预定义字符实体
由XML规范预先定义好了,如 amp 代表&, apos 代表单引号,gt 代表>, 在使用时加上&号,如: & 表示单个字符&, ' 表示单引号。
b、数字字符实体
在前面我们总结实体的作用时,有一条;可以代表无法输入的字符。这些字符就是使用数字字符实体表示的。我们可以使用某个字符在字符集中的位 置数来表示该字符。 该数字可以使用10进制或16进制的方式表示,在数字前面加上:&# , 比如: ç 16进制的表示:ç , 这两种方式都表示同一个字符。
c、命名字符实体
与数字字符实体类似,只是将数字改为一个更容易记忆的英文标识.
混合内容实体
混合内容实体是xml中使用得最多的实体,它的值不仅限于单个字符,还可以代表不限长度的各种字符块。混合内容实体分为:内部实体和外部实体
a、内部混合实体
内部混合实体表示该实体在xml文档内部定义,内部实体常用来代替经常重复的短语,名称和模板文本。上面的xml示例中,agent实体就是典型。除了agent,clietn, phone 实体都是内部混合实体。
a、外部混合实体
一些实体需要代表大块的字符,为了便于文件的管理,可以将这些大块的字符放在其他文件中,这是外部混合实体便发挥作用了。可以在外部文件中定义实体,然后在xml文档中声明并使用它。下面是一个例子:
<!ENTITY part1 SYSTEM "P1.xml"> 声明了一个名称为;“part1"的外部实体,该实体代表的内容处于P1.xml文件中。 part2, part3 也分别代表了 p2.xml, p3.xml 中的内容。
外部混合实体最大的用处是可以将内容太长的xml文档分成几个小的xml文档,便于网络传输。
未析实体
未析实体代表不同于xml文档内容的其他数据,如:二进制数据等等。当xml处理器无法识别该数据时,不会像对待其他实体一样,去解析它,而是让它保持原样。未析实体的定义与外部混合实体的声明方式类似,只是后面多了个“NDATA”字符和一些数据标识。比如:
5
XML外部实体注入
XXE注入,即XML External Entity,XML外部实体注入。通过 XML 实体,”SYSTEM”关键词导致 XML 解析器可以从本地文件或者远程 URI 中读取数据。
所以攻击者可以通过 XML 实体传递自己构造的恶意值,是处理程序解析它。当引用外部实体时,通过构造恶意内容,可导致读取任意文件、执行系统命令、探测内网端口、攻击内网网站等危害。下面介绍两个注入实例:
文件内容和信息泄露
在早前的一个信息泄露的例子中,我们注意到自定义实体可能引用一个外部文件。
这会把文件内容扩展到自定义的&harmless;实体中。由于所有类似的请求都是在本地完成的,这使得该应用有权限读取的所有文件内容都可能被泄露。
只要应用的输出中包含了这个扩展了的实体,攻击者就可以查看那些文件,包括没有公开的文件。因这种方式而造成内容泄露的文件是相当有限的,只能是XML文件,和不会造成XML解析错误的文件。但是,php可以完全忽略这种限制。
PHP允许通过URI访问PHP wrapper,这是一般文件系统函数,如file_get_contents()、require()、require_once()、file()、和copy()等,接受的协议之一。
PHP wrapper支持一些过滤器,这些过滤器运行在给定的资源上,结果可以通过函数调用返回。在上述例子中,我们对想要读取的目标文件使用了convert.base-64-encode过滤器。
这意味着,攻击者通过利用XXE的脆弱性,可以用PHP读取任何可读的文件,不论文本格式如何。攻击者只需用base64将应用输出解码,就可以毫无顾忌的分析一大堆非公开文件的内容。
尽管这本身不会直接伤害终端用户或是应用后台,但是它能让攻击者了解目标应用,从而以最小的代价、最低的风险发现应用的其他弱点。
绕过访问控制
访问控制可以通过各种方法来实现。由于XXE攻击是挂在web应用后台的,它无法使用当前用户会话产生任何影响,但是攻击者仍然可以借助从本地服务器发送请求,来绕过后台访问控制。我们来看一下下面这个简单的访问控制:
这段PHP和无数的类似代码都用于限制特定PHP文件对本地服务器的访问,如 localhost。但是,应用前端的XXE脆弱性,正好为攻击者提供了绕过访问控制所需的凭证,因为XML解析器发出的所有HTTP请求都来自localhost。
如果只有本地请求可以查看日志,攻击者就可以成功获取日志。同样的思路也适用于只接受本地请求的维护和管理接口。
6
如何抵御XML外部实体注入
这类攻击十分“诱人“,但对它的防御也简单的出奇。既然DOM、SimpleXML和XMLReader依赖于libxml2,我们可以简单地利用libxml_disable_entity_loader()函数来禁止外部实体引用。
与此同时,DOCTYPE中预定义的自定义实体却不会受到影响,因为它们并没有使用任何需要文件系统操作或发送HTTP请求的外部资源。
在所有涉及通过字符串、文件或者远程URI来加载XML时,都需要使用这些操作。
当应用程序及其大部分请求都不需要外部实体时,你可以简单地从全局禁掉外部资源加载。大多数时候,这比找出所有的XML加载实例来逐个操作要更好。记住,许多库天生自带XEE脆弱性:
每次需要临时允许加载外部资源时,加载完后切记再把这里设为TRUE。例如,在将Docbook XML转换为HTML时,所使用的XSL样式就是依赖于外部实体的,这里需要外部实体,但是是无害的。
但是,libxml2函数绝不是”万能钥匙”。我们需要确认,其他用于解析或处理XML的扩展和PHP库的引用外部实体的功能,都处于关掉状态。
如果不能通过上述方法来开关外部实体引用,你还可以检查一下XML文档是否声明了DOCTYPE。如果声明了,同时禁掉了外部实体,则可以简单地丢弃XML文档,拒绝可能造成解析器脆弱性的不受信任的XML访问,同时将这种行为记录为一次可能的攻击。
我们需要将这种行为记录下来,因为除此之外不会有任何系统报错记录。可以在日常输入验证中进行这项检查。但是,这种方法并不理想,我们还是强烈建议从源头上解决外部实体的问题。
同时,值得注意的是,当我们怀疑一段数据有可能是某个攻击的结果时,最好的方法是丢弃它,而不是继续使用它。既然它已经表现出了危险,为什么还要继续使用它呢?因此,将上述两个步骤合并起来,我们可以在无法丢弃数据时(例如第三方的库),通过主动跳过坏数据起到保护作用。
之所以我们更愿意完全丢弃这些数据,还因为上文提到过的一个理由:libxml_disable_entity_loader()不会将自定义实体完全禁掉,只有引用外部资源的才会被禁掉。因此这仍有可能导致一个被称为XML实体扩展的注入攻击。(未完待续)
以上:就是今天的知识点,大家都看明白了吗,没看明白的扣个1,让阿姨看看谁家孩子这么bèn~
ps:竟然有人不喜欢玩扫雷,白给你的扫雷外挂不要我就自己私藏喽~今天还能领,有兴趣的去学一学吧!
资料获取方式还是老规矩
点击阅读原文,给我知乎点个赞
知乎ID:一棵树
私信留03,看见就发给你
小编微信
以上是关于一个合格程序猿应该知道的基础知识—XML注入介绍的主要内容,如果未能解决你的问题,请参考以下文章
做一个合格的程序猿之浅析Spring AOP源码(十五) 分析JdkDynamicAopProxy的invoke方法