Rambler's Top100

Система определения версий служб в сетевом сканере Nmap

Nmap, как известно, умеет делать много полезных вещей: это и определение операционной системы при помощи снятия отпечатков стека TCP/IP, многофункциональный ping-опрос, вычисление временных параметров, сканирование протоколов и т.д. Однако историческое его предназначение – это, конечно, сканирование портов. Укажите Nmap’у интересующий Вас хост – и он может сообщить Вам, что порты 25/tcp, 80/tcp и 35/udp хоста открыты. Используя собственную базу данных, размещенную в файле nmap-services и содержащую свыше 2200 названий «общеизвестных» служб, напротив каждого номера обнаруженного порта Nmap укажет возможное назначение этого порта: относится ли он к почтовому серверу (SMTP), веб-серверу (HTTP) или к службе DNS. При этом результат определения службы, закрепленной за «общеизвестным» портом, практически всегда совпадает с действительностью, поскольку все почтовые сервера, например, должны «сидеть» на 25-м порту. Но не стоит забывать о том, что люди могут и ЗАПУСКАЮТ службы, закрепляя их за весьма необычными портами.

Возможна, например, такая ситуация: веб-сервер развернут и работает на 80-м порту, а в дополнении к этому используется другой «нестандартный» порт для тестирования и обслуживания сервера. Вполне возможно, что при выборе «нестандартных» портов людьми движет желание скрыть уязвимые службы от злоумышленников. И наиболее распространенной причиной использования «нестандартных» портов для вполне обычных служб является наличие файрволла, ограничивающего доступ к защищенным портам извне. Так, например, когда один весьма крупный интернет-провайдер заблокировал 80-й порт после «нашумевших» червей CodeRed и Nimida, поражающих службу Microsoft IIS, пользователи попросту переместили свои персональные веб-сервера на другие порты. В другой компании системный администратор заблокировал телнет-доступ к рабочим местам из-за высокой степени риска, а некоторые «продвинутые» пользователи просто перевели службу телнет на порт, используемый SSH, и продолжали работать. И случаи, подобные этим, отнюдь не редкость.

Даже если Nmap прав, и на гипотетическом хосте, описанном выше, действительно запущены службы SMTP, HTTP и DNS, этой информации недостаточно для квалифицированного тестирования безопасности сети. Необходимо знать, какой именно почтовый или DNS-сервер работает на исследуемом хосте (его тип), и, по возможности, определить его версию. Имея точную информацию о типе и версии сервера, можно определить его уязвимости.

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

Те, кто часто занимается сканированием сетей, знают, что большая часть обнаруженных активных служб прослушивают как раз «нестандартные» порты, но определить, какие это службы, не представляется возможным. Без механизма определения версий служб «нестандартные» открытые порты представляют собой подобие «черных дыр»: что туда приходит, что с этим происходит и что выходит – тайна, покрытая мраком.

На самом деле, есть масса причин, по которым иметь информацию о типе и версии работающей службы крайне необходимо. Так, фильтруемые UDP-порты в результатах сканирования выглядят как открытые порты. Однако если открытый UDP-порт положительно отвечает на специальные тесты, проводимые в ходе определения типа и версии службы, использующей этот порт, можно с уверенностью сказать, что порт действительно открыт (и вдобавок к этому получить информацию о службе, прослушивающей его).

Использование нового механизма определения типа и версии активных служб в сетевом сканере Nmap позволяет решить эти проблемы. При обнаружении открытого порта запускается подсистема определения служб, и опрашивает его при помощи специальных тестовых запросов, которые может «понять» та или иная служба. Вот реальный пример:

# nmap -A -T4 -F www.insecure.org

Starting nmap 3.40PVT16 ( http://www.insecure.org/nmap/ ) at 2003-09-06 19:49 PDT

Interesting ports on www.insecure.org (205.217.153.53):
(The 1206 ports scanned but not shown below are in state: filtered)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 3.1p1 (protocol 1.99)
25/tcp open smtp Qmail smtpd
53/tcp open domain ISC Bind 9.2.1
80/tcp open http Apache httpd 2.0.39 ((Unix) mod_perl/1.99_07-dev Perl/v5.6.1)
113/tcp closed auth

Device type: general purpose
Running: Linux 2.4.X|2.5.X
OS details: Linux Kernel 2.4.0 - 2.5.20
Uptime 108.307 days (since Wed May 21 12:27:44 2003)

Nmap run completed -- 1 IP address (1 host up) scanned in 34.962 seconds

На самом деле, Nmap – не первая программа, которая использует этот механизм. Около 3 лет назад Jay Freeman (AKA Saurik) разработал патч для Nmap, который он назвал Nmap+V. В то время Nmap+V работал гораздо медленнее, чем сейчас, однако технику определения типа и версии службы демонстрировал с успехом. Кроме того, такие замечательные утилиты, как Nessus и THC Amap, также имеют некоторые возможности, характерные для данной техники. Тем не менее, ни одна из этих программ не смогла удовлетворить всем требованиям пользователей. Мы же, напротив, попытались это сделать. Итак, перечислим основные достоинства новой подсистемы определения типа и версии служб, используемой в сканере Nmap:

Примеры использования

Прежде чем перейти к описанию технической реализации нового метода, приведем несколько примеров, демонстрирующих примеры его использования. Для включения механизма определения версий необходимо указать опцию -sV в командной строке при запуске Nmap. Кроме этого, Вы можете использовать новую опцию '-A', которая включает механизм определения версий и определение ОС (-O). Пример результатов сканирования с использованием этой опции приведен ниже:

# nmap -A -T4 -F www.microsoft.com

Starting nmap 3.40PVT16 ( http://www.insecure.org/nmap/ ) at 2003-09-07 01:45 PDT

Interesting ports on 80.67.68.30:
(The 1208 ports scanned but not shown below are in state: closed)
PORT STATE SERVICE VERSION
22/tcp open ssh Akamai-I SSH (protocol 1.5)
80/tcp open http AkamiGHost (Akamai's HTTP Acceleration/Mirror service)
443/tcp open ssl/http AkamiGHost (Akamai's HTTP Acceleration/Mirror service)

Device type: general purpose
Running: Linux 2.1.X|2.2.X
OS details: Linux 2.1.19 - 2.2.25
Uptime 22.924 days (since Fri Aug 15 03:34:27 2003)

Nmap run completed -- 1 IP address (1 host up) scanned in 19.223 seconds

Этот пример демонстрирует несколько весьма любопытных вещей. Прежде всего, мы с удивлением обнаруживаем, что сайт www.microsoft.com размещен на сервере с операционной системой Akami Linux. Что касается определения типов и версий служб – тоже масса интересного. Например, порт 443 определен как «ssl/http». Это означает, что подсистема определения служб вначале обнаружила наличие на этом порту протокола SSL, затем загрузила OpenSSL, повторно провела необходимые тесты через SSL и определила наличие веб-сервера AkamiGHost, спрятанного «за» SSL. Опция -T4 указывает Nmap использовать более агрессивную временную политику сканирования (с меньшими временными затратами), а опция -F включает режим сканирования только тех портов, которые перечислены в файле nmap-services.

А вот более длинный, но и более интересный пример:

./nmap -A -T4 localhost

Starting nmap 3.40PVT16 ( http://www.insecure.org/nmap/ ) at 2003-09-07 02:56 PDT

Interesting ports on felix (127.0.0.1):
(The 1640 ports scanned but not shown below are in state: closed)
PORT STATE SERVICE VERSION
21/tcp open ftp WU-FTPD wu-2.6.1-20
22/tcp open ssh OpenSSH 3.1p1 (protocol 1.99)
53/tcp open domain ISC Bind 9.2.1
79/tcp open finger Linux fingerd
111/tcp open rpcbind 2 (rpc #100000)
443/tcp open ssl/http Apache httpd 2.0.39 ((Unix) mod_perl/1.99_04-dev [cut])
515/tcp open printer
631/tcp open ipp CUPS 1.1
953/tcp open rndc?
5000/tcp open ssl/ftp WU-FTPD wu-2.6.1-20
5001/tcp open ssl/ssh OpenSSH 3.1p1 (protocol 1.99)
5002/tcp open ssl/domain ISC Bind 9.2.1
5003/tcp open ssl/finger Linux fingerd
6000/tcp open X11 (access denied)
8000/tcp open http-proxy Junkbuster webproxy
8080/tcp open http Apache httpd 2.0.39 ((Unix) mod_perl/1.99_04-dev [cut])
8081/tcp open http Apache httpd 2.0.39 ((Unix) mod_perl/1.99_04-dev [cut])

Device type: general purpose
Running: Linux 2.4.X|2.5.X
OS details: Linux Kernel 2.4.0 - 2.5.20
Uptime 8.653 days (since Fri Aug 29 11:16:40 2003)

Nmap run completed -- 1 IP address (1 host up) scanned in 42.494 seconds

В этом примере видно, как Nmap использует методику лобовой атаки на службу RPC, причем использует ее весьма успешно, поскольку в результатах сканирования порта с номером 111 указано, что порт этот закреплен за rpcbind версии 2. На две строки ниже указан порт 515, а служба, использующая его, определена как «printer», однако колонка с описанием версии службы пуста. Это означает, что Nmap определил название службы, однако больше ничего определить не удалось. С другой стороны, тестирование порта 953 дало результат, указанный как «rndc?». Вопросительный знак говорит о том, что Nmap не смог определить названия службы при помощи подсистемы определения версий. Тем не менее, указана служба rndc, поскольку порт с номером 953 зарегистрирован на эту службу в файле nmap-services. К сожалению, ни один тест подсистемы определения версий не дал положительного результата от службы rndc. Если бы результаты были, то Nmap вывел бы «отпечаток» службы и URL, по которому его необходимо отправить на специальное исследование.

Стоит отметить, что некоторые службы предоставляют гораздо больше информации, нежели просто номер версии. В примере выше видно, что X11 не принимает входящих подключений, виден номер протокола SSH и номера версий модулей веб-сервера Apache (нам пришлось вырезать большую часть описаний этих модулей, чтобы статья не занимала много места).

Техническая реализация

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

Прежде всего, Nmap выполняет сканирование портов в соответствии с заданными в командной строке параметрами, после чего передает список обнаруженных открытых TCP и/или UDP портов подсистеме определения версий. Работа с этими портами ведется в параллельном режиме, однако мы не будем вдаваться в эти тонкости и рассмотрим, как подсистема работает с одним портом:

  1. Если открытый порт работает по протоколу TCP, Nmap пробует соединиться с ним.
  2. После установления TCP-соединения, Nmap прослушивает его в течении приблизительно 5 секунд. Большинство служб, таких, как ftp, ssh, smtp, telnet, pop3 и imap идентифицируют сами себя путем передачи приветствия подключившейся машине. Nmap относится к этому как к «нуль-тесту», поскольку Nmap просто прослушивает порт и не отправляет никаких данных. Если в процессе этого теста были получены какие-либо данные, Nmap сравнивает их с сигнатурами, приведенными в файле nmap-service-probes. Если служба полностью идентифицирована, тестирование порта считается завершенным. Сигнатура представляет собой не что иное, как регулярные строковые выражения, с помощью которых можно извлечь необходимую информацию из полученных данных. Иногда Nmap определяет лишь тип службы, но не может определить ее версию. В этом случае Nmap продолжит тестирование при помощи передачи запросов на порт для определения версии данного типа службы.
  3. На этом этапе Nmap начинает тестировать протокол UDP, а TCP-соединение завершается, если «нуль-тест» не дал результата или обнаружил частичное соответствие сигнатуре. Поскольку большинство портов жестко закреплены за соответствующими службами (смотрите файл nmap-services), подсистеме тестирования, как правило, передается список портов для выполнения теста. Например, для выполнения теста, называемого GetRequest (определение наличия веб-сервисов) передаются номера портов 80-85, 8000-8010 и 8080-8085. Тестирование списка портов происходит последовательно. В процессе каждого теста на исследуемый порт передается строка (простой текст или двоичная escape-последовательность). Полученный ответ сравнивается со списком регулярных выражений (аналогично «нуль-тесту» описанному выше). В процессе тестирования могут быть получены следующие результаты: полное совпадение с сигнатурой (завершение теста), частичное совпадение (целенаправленный выбор дальнейших тестов для определенной службы), или отсутствие сигнатуры (неизвестная служба).
  4. В большинстве случаев предполагается, что «нуль-тест» или дополнительное тестирование порта все-таки даст результат, и служба будет определена. Поскольку дополнительное тестирование порта происходит после «нуль-теста», подсистема определения версий может успешно завершить работу за один «сеанс связи». Для протокола UDP обычно необходимо отправить лишь один пакет, поэтому сеанс будет весьма коротким. Если же «нуль-тест» и дополнительный опрос порта не дали результатов, Nmap начнет последовательно проводить все тесты. Для протокола TCP, Nmap должен создавать новое соединение для предотвращения искажений результатов предыдущего теста. Этот процесс занимает достаточно много времени, кроме того, результат, получаемый при выполнении «общего» теста, как правило, применим к нескольким службам одновременно. Например, при выполнении теста GenericLines на порт передается две пустые строки (\r\n\r\n). Положительный результат этого теста соответствует 10 типам служб, таким, как ftp, ident, pop3, uucp, postgres и whois. Положительный результат теста GetRequest (строка «help\r\n» и опрос RPC и MS SMB) дает значительно больше различных служб. Любое частичное совпадение с сигнатурой на этом этапе значительно уменьшает число последующих тестов.
  5. Одним из важных тестов является проверка протокола SSL. Если определено наличие SSL (и доступен OpenSSL), Nmap повторно соединится с этим портом по протоколу SSL и повторит тестирование, чтобы определить, какая служба использует порт «за» шифрованием. Специальный набор инструкций позволяет работать с различными портами с использованием обычного и шифрованного (SSL) соединения. Например, Nmap самостоятельно должен начать проверку порта 443 (https) с теста SSL. После того, как будет установлено наличие SSL, Nmap должен запустить тест GetRequest на порт 443.
  6. Если хотя бы один тест прошел результативно (был получен ответ), а Nmap не смог определить службу, содержание ответа на тест будет выведено на экран (по аналогии с отпечатком неизвестной ОС). Одновременно с этим на экран будет выведен адрес, куда необходимо отправить этот «отпечаток». В дальнейшем будет проведена работа по детальному изучению полученной информации, и, возможно, в следующей версии Nmap мы сможем сопоставить этому отпечатку определенную службу.
  7. Для некоторых служб возможно проведение пост-процессинга после основной группы тестов для определения дополнительной информации. Например, любая обнаруженная служба RPC будет передана подсистеме «лобовой атаки» на RPC (-sR) для определения номера программы и ее версии.

Если это описание показалось Вам недостаточным, Вы можете включить опции --version_trace и -d (режим отладки) при запуске Nmap и посмотреть на весь процесс, что называется, «вживую».

Описание формата файла nmap-service-probes

По аналогии с подсистемой определения ОС, Nmap использует простой текстовый файл для хранения тестов и сигнатур подсистемы определения версий. Файл этот называется nmap-service-probes.

Как принято в файлах ОС UNIX, nmap-service-probes состоит из строк. Строки, начинающиеся с символа «hash» (#) воспринимаются как комментарии и игнорируются обработчиком. Пустые строки также не обрабатываются. Строки, подлежащие обработке, должны содержать следующие директивы:

Probe <protocol> <probename> <probesendstring>

Примеры:

Probe TCP GetRequest q|GET / HTTP/1.0\r\n\r\n|
Probe UDP DNSStatusRequest q|\0\0\x10\0\0\0\0\0\0\0\0\0|
Probe TCP NULL q||

Директива «probe» (тест) указывает Nmap, какие данные отправлять в процессе определения служб. Аргументы этой директивы следующие:

Protocol – тип протокола. Может быть указан один из протоколов TCP или UDP. Nmap будет использовать только те тесты, тип протокола которых совпадает с рабочтм протоколом проверяемой службы.

Probenameназвание теста. Используется в отпечатке службы для указания, на какой тест был получен ответ. Название может быть произвольным (удобным для пользователя).

Probestringстрока, используемая для тестового запроса. Должна начинаться и заканчиваться символом-ограничителем «q». Между ограничителями находится непосредственно сама строка, передаваемая в качестве теста. Эта строка имеет формат, аналогичный строкам языков C или Perl, и может содержать стандартные escape-последовательности: \\ \0 \a \b \f \n \r \t \v \xHH . В последнем примере показано, что тестовая строка может быть пустой. Это и есть тот самый «нуль-тест», при котором данные на порт не отправляются.

match <service> <pattern> [versioninfo]

Примеры:

match ftp m/^220.*Welcome to PureFTPd (\d\S+)/ v/PureFTPd/$1//
match ssh m/^SSH-([.\d]+)-OpenSSH_(\S+)/ v/OpenSSH/$2/protocol $1/
match mysql m/^.\0\0\0\n(4\.[-.\w]+)\0...\0/s v/MySQL/$1//
match ssc-agent m|^\0\x1e\0\x06\0\t\0\0$| v/Novell Netware ssc-agent///
match chargen m|@ABCDEFGHIJKLMNOPQRSTUVWXYZ|

Директива «match» указывает Nmap на то, как точно определить службу, используя полученный ответ на запрос, отправленный предыдущей директивой. Эта директива используется в случае, когда полученный ответ полностью совпадает с шаблоном. При этом тестирование порта считается законченным, а при помощи дополнительных спецификаторов Nmap строит отчет о названии приложения, номере версии и дополнительной информации, полученной в ходе проверки. Директива имеет следующие аргументы:

Service – название службы, для которой приведен шаблон. Например, ssh, smtp, http, или SNMP.

Pattern – шаблон, с которым должен совпадать полученный ответ. Формат шаблона аналогичен принятому в языке Perl, и имеет следующий синтаксис: «m/[regex]/[opts]». Литерал «m» указывает на начало строки. Прямой слэш ('/') является разделителем, вместо которого может быть подставлен любой печатаемый символ (при этом вместо второго слэша должен быть подставлен такой же символ). Regex – это регулярное выражение, принятое в языке Perl. В настоящее время поддерживаются только две опции – это 'i' (снимает чувствительность выражения к регистру) и 's', включающая символ перевода строки в спецификаторе типа '.' .

Versioninfo – это поле имеет следующий формат: v/vendorproductname/version/info/, где слэш может быть заменен любым разделителем. Любое из трех полей может быть пустым. Кроме этого, поле само может быть пустым, и это означает, что дополнительная информация о службе отсутствует. Поле vendorproductname содержит название производителя и имя службы, например, «Sun Solaris rexecd», «ISC Bind named», или «Apache httpd». Поле version содержит «номер» версии (в кавычках потому, что может обозначаться не числовым значением, а напротив, состоять из нескольких слов). Поле info содержит дополнительную полезную информацию, которая может пригодиться на этапе сканирования (например, номер протокола сервера ssh).

softmatch <service> <pattern>

Примеры:

softmatch ftp m/^220 [-.\w ]+ftp.*\r\n$/i
softmatch smtp m|^220 [-.\w ]+SMTP.*\r\n|
softmatch pop3 m|^\+OK [-\[\]\(\)!,/+:<>@.\w ]+\r\n$|

Директива softmatch имеет формат, аналогичный директиве match. Основное отличие заключается в том, что после совпадения принятого ответа с одним из шаблонов softmatch, тестирование будет продолжено с использованием только тех тестов, которые относятся к определенной шаблоном службе. Тестирование порта будет идти до тех пор, пока не будет найдено строгое соответствие («match») или не закончатся все тесты для данной службы. Аргументы те же самые, только, конечно, отсутствует versioninfo.

ports <portlist>

Примеры:

ports 21,43,110,113,199,505,540,1248,5432,30444
ports 111,4045,32750-32810,38978

Эта директива группирует порты, которые обычно закрепляются за идентифицируемой данным тестом службой. Синтаксис представляет собой упрощенный формат опции ‘-p’.

sslports <portlist>

Пример:

sslports 443

Аналогично описанной выше, эта директива указывает порты, обычно используемые совместно с SSL. Например, в тесте HTTP объявлено 'sslports 443', а в тесте SMTP есть строка 'sslports 465'.

totalwaitms <milliseconds>

Пример:

totalwaitms 5000

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

База данных отпечатков служб

Не зависимо от того, насколько технически грамотно реализована система определения версий, от нее не будет никакого толка, пока не наберется внушительная база отпечатков различных сервисов. Вот почему нам (Insecure.Org) нужна Ваша помощь. Сами мы не в состоянии проделать такую громадную работу, даже если будем сидеть 24 часа в сутки и сканировать, сканировать, сканировать… Весьма удачный опыт с отпечатками ОС показал, что мы избрали правильный путь. В настоящее время эта база содержит десятки тысяч отпечатков различных операционных систем и устройств, и непрерывно пополняется! Много, очень много работы ушло на создание базы данных отпечатков сервисов, состоящей всего из нескольких сотен спецификаций, а их не меньше, чем операционных систем! Поэтому есть несколько путей, как мы всем миром сможем составить базу служб, не уступающую базе ОС:

1) Передача отпечатков служб – Если служба отвечает на один или более тестов, а Nmap не может определить ее, он выведет отпечаток службы наподобие этого:

SF-Port21-TCP:V=3.40PVT16%D=9/6%Time=3F5A961C%r(NULL,3F,"220\x20stage\x20F
SF:TP\x20server\x20\(Version\x202\.1WU\(1\)\+SCO-2\.6\.1\+-sec\)\x20ready\
SF:.\r\n")%r(GenericLines,81,"220\x20stage\x20FTP\x20server\x20\(Version\x
SF:202\.1WU\(1\)\+SCO-2\.6\.1\+-sec\)\x20ready\.\r\n500\x20'':\x20command\
SF:x20not\x20understood\.\r\n500\x20'':\x20command\x20not\x20understood\.\
SF:r\n");

Если Вы получите такую информацию, но точно знаете, какая именно служба работает на этом хосте, пожалуйста, отправьте этот отпечаток по адресу, который укажет Nmap. Процесс передачи анонимен (если Вы сами не укажете идентификационную информацию) и займет не более пары минут.

2) Передача исправлений – Еще один способ улучшить базу данных. Если Вы протестировали известную Вам службу и получили неверную информацию, пожалуйста, отправьте полный лог Nmap и правильное название службы по адресу fyodor@insecure.org. В ближайшем релизе мы внесем соответствующие корректировки.

3) Передача новых тестов – Предположим, Nmap не определил службу ввиду того, что ни на один тест не был получен ответ. Что тогда делать? Ответ прост – создайте свой собственный результативный тест и отправьте его нам! Как это сделать правильно, чтобы никому не было обидно:

  1. Загрузите последнюю версию Nmap и попробуйте снова протестировать службу. Для того, чтобы не почувствовать себя глупо после недельной разработки нового теста, мы рекомендуем сначала проверить – а не сделал ли кто-нибудь это за вас?
  2. Определитесь с тестовым воздействием. Почитайте RFCs и прочую документацию. Поставьте все, что есть на Вашем вооружении – снифферы, пакетные генераторы и т.д. Словом, заставьте эту службу отправить хоть что-нибудь, что бы ее характеризовало.
  3. Если у Вас все получилось, составьте правильное описание тестового воздействия согласно описанным выше правилам, проверьте его работу при помощи Nmap и если все в порядке, смело отправляйте тест по адресу fyodor@insecure.org для включения в Nmap. Не забудьте подробно описать, как все это у Вас получилось.

(с) 2003 Fyodor

(c) 2003 Алексей Волков

Insecure.Org - Россия

Rambler's Top100 ???????@Mail.ru