четверг, 29 октября 2009 г.

Solaris 10, NMap и OS fingerprinting

Тема OS fingerprinting (удаленная идентификация операционных систем хостов) актуальна всегда. Простейший поиск в Гугле дает кучу результатов. Далеко не все рекомендации, однако, дают положительные результаты при реальном тестировании сканерами, в частности, всем известным NMap.

Новая версия NMap отличается редкостной устойчивостью ко всякого разного рода админским ухищрениям. Сканирование ОС ведется по целому ряду признаков, и далеко не все защитные меры против подобного сканирования являются самоочевидными.

Давайте попробуем посмотреть, можно ли что-то сделать в связи с необходимостью защиты от OS fingerprinting, реализованном NMap.

Если резюмировать практический опыт, то рекомендации полностью соответствуют методологии сканирования.

Как выполняется определение ОС сканерами?

1. Самоочевидная вещь - сканирование баннеров сервисов. Соответственно, необходимо использовать tcpwrappers итп. или минимизировать баннеры сервисов, максимально скрывая версию служб.
2. Сканеры посылают характерные пакеты для определения версии ОС либо пакеты с определенными опциями (вне установленных сессий - см. ниже). Не менее самоочевидная вещь - блокирование соответствующих пакетов файрволом.
3. Иногда с целью сканирования посылаются обычные пакеты, появление которых, однако, вне установленных сессий TCP нехарактерно (ACK итп.)
4. Сканеры как правило имеют базы данных характерных особенностей (параметров) стеков TCP/IP, которые позволяют в рамках обычных сессий к сервисам достаточно четко идентифицировать целевую ОС.

Соответственно, защита от идентификации ОС (не абсолютная, разумеется, однако достаточно продвинутая - во всяком случае, от автоматического сканирования) выполняется по нескольким направлениям.

1. Максимально минимизируем информацию о сервисах. Там, где это возможно - пересобираем сервисы, меняя версии и названия на что угодно произвольное. Например, модифицируем название и версию для OpenSSH в файле version.h.

2 и 3. Пишем блокирующие правила для IPFilter (фрагмент конфигурации):

# ---------------------
# Common blocking rules
# ---------------------

# Block all IP fragments
block in quick all with frag

# Block all short IP fragments
block in quick proto tcp all with short

# Block any IP packets with options set in them
block in quick all with ipopts

# Block OS fingerprint attempts
block in log first quick proto tcp all flags SF/SF
block in log first quick proto tcp all flags SFUP/SFUP
block in log first quick proto tcp all flags FPU/FPU
block in log first quick proto tcp all flags F/F
block in log first quick proto tcp all flags U/U
block in log first quick proto tcp all flags P/P

Кроме того, модифицируются правила для входящих сервисных соединений следующим образом (пример):

pass in quick on bge0 proto tcp from any to myhost port=80 flags S/SA keep state group 200

(данное правило переводится на русский язык следующим образом - "мы не принимаем вне сессий (до посылки SYN) пакетов ACK")

4. Данный пункт менее очевиден и требует определенных ухищрений, в частности, на Solaris. Во-первых, большая часть параметров стека TCP/IP на Solaris динамическая и через /etc/system не задается. Требуется модификация посредством ndd. Во-вторых - нужно знать, какие параметры требуется модифицировать и каким образом. Чтобы, в частности, не пострадало поведение систем и не упала производительность.

В Solaris выполнение данного пункта слегка осложнено тем, что штатного механизма задания параметров стека TCP/IP при запуске системы в Солярис не существует. Тот единственный и глубоко закопанный пример, который мне удалось найти - содержит ошибки и неработоспособен без существенных корректировок (неспособный пройти валидацию сервисный манифест, не слишком удобный и неполный управляющий метод - отсутствует перенаправление в штатные логи SMF итп.).

В общем, как и во всех прочих случаях, коль скоро встала необходимость решить задачу для себя - пришлось написать сервис NetTune, взяв за основу переделанный вариант Sun. Скачать его в готовом к употреблению виде можно здесь.

Параметры с удобством задаются в /etc/ndd.conf:

# Harden fingerprinting
tcp tcp_mss_def_ipv4 583
ip ip_path_mtu_discovery 0
tcp tcp_xmit_hiwat 64373
tcp tcp_recv_hiwat 64373
tcp tcp_ipv4_ttl 121
# Functional settings
ip ip_strict_dst_multihoming 1
# Security settings
ip ip_respond_to_echo_broadcast 0
ip ip_send_redirects 0
# Performance tunables
tcp tcp_conn_req_max_q 1024
tcp tcp_conn_req_max_q0 4096
tcp tcp_ip_abort_interval 60000
tcp tcp_keepalive_interval 900000
tcp tcp_rexmit_interval_max 10000
tcp tcp_rexmit_interval_min 3000

Установка данных параметров (первой группы) искажает специфические для Solaris поведенческие параметры стека TCP/IP до неузнаваемости сканерами.

Параметр ip_strict_dst_multihoming также позволяет решить одну давнюю задачу - ответ сервисов на multihomed-машине по тем же портам, с которых пришел запрос (по умолчанию в Solaris стоит значение данного параметра равное 0 - Loose, то есть возвратные пакеты посылаются по любым активным интерфейсам по round robin).

Что получилось в результате?

Удалось ли лишить NMap возможности определения типа и версии ОС?

Проверяем. Целевая машина - Solaris 10 x64 10/09, с поднятым согласно приведенным рекомендациям файрволом (IPF) и установленным вышеупомянутым сервисом NetTune:

root @ athena / # nmap -v -sV -O -A -PN 192.168.0.2

Starting Nmap 5.00 ( http://nmap.org ) at 2009-10-29 17:12 ALMT
NSE: Loaded 53 scripts for scanning.
Initiating Parallel DNS resolution of 1 host. at 17:12
Completed Parallel DNS resolution of 1 host. at 17:12, 0.15s elapsed
Initiating SYN Stealth Scan at 17:12
Scanning 192.168.201.22 [1000 ports]
SYN Stealth Scan Timing: About 15.00% done; ETC: 17:16 (0:02:56 remaining)
SYN Stealth Scan Timing: About 28.55% done; ETC: 17:16 (0:02:33 remaining)
SYN Stealth Scan Timing: About 42.05% done; ETC: 17:16 (0:02:05 remaining)
SYN Stealth Scan Timing: About 57.00% done; ETC: 17:16 (0:01:31 remaining)
SYN Stealth Scan Timing: About 70.50% done; ETC: 17:16 (0:01:03 remaining)
SYN Stealth Scan Timing: About 83.05% done; ETC: 17:16 (0:00:37 remaining)
Completed SYN Stealth Scan at 17:16, 217.23s elapsed (1000 total ports)
Initiating Service scan at 17:16
Initiating OS detection (try #1) against 192.168.201.22
Retrying OS detection (try #2) against 192.168.201.22
NSE: Script scanning 192.168.201.22.
NSE: Script Scanning completed.
Host 192.168.201.22 is up.
All 1000 scanned ports on 192.168.201.22 are filtered
Too many fingerprints match this host to give specific OS details

Read data files from: /usr/local/share/nmap
OS and Service detection performed. Please report any incorrect results at http://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 227.99 seconds
Raw packets sent: 2048 (94.672KB) | Rcvd: 0 (0B)

На деле, изменение параметров стека даже более важно, нежели настройка или вообще наличие файрвола. Протестируем машину с установленным сервисом NetTune и снятым файрволом (Solaris 10 SPARC 10/09):

Starting Nmap 5.00 ( http://nmap.org ) at 2009-10-29 17:19 Северная Центр. Азия (зима)
NSE: Loaded 30 scripts for scanning.
Initiating SYN Stealth Scan at 17:19
Scanning host1.example.com (192.168.0.5) [1000 ports]
Discovered open port 21/tcp on 192.168.0.5
Discovered open port 443/tcp on 192.168.0.5
Discovered open port 111/tcp on 192.168.0.5
Discovered open port 8080/tcp on 192.168.0.5
Discovered open port 80/tcp on 192.168.0.5
Discovered open port 4045/tcp on 192.168.0.5
Discovered open port 6112/tcp on 192.168.0.5
Increasing send delay for 192.168.0.5 from 0 to 5 due to 21 out of 68 dropped probes since last increase.
Increasing send delay for 192.168.0.5 from 5 to 10 due to max_successful_tryno increase to 4
Discovered open port 2049/tcp on 192.168.0.5
Discovered open port 6003/tcp on 192.168.0.5
Discovered open port 32771/tcp on 192.168.0.5
Discovered open port 32773/tcp on 192.168.0.5
Discovered open port 32772/tcp on 192.168.0.5
Discovered open port 2222/tcp on 192.168.0.5
Discovered open port 32777/tcp on 192.168.0.5
Discovered open port 32779/tcp on 192.168.0.5
Discovered open port 1521/tcp on 192.168.0.5
Discovered open port 5000/tcp on 192.168.0.5
Discovered open port 32778/tcp on 192.168.0.5
Completed SYN Stealth Scan at 17:20, 27.20s elapsed (1000 total ports)
Initiating Service scan at 17:20
Scanning 18 services on host1.example.com (192.168.0.5)
Completed Service scan at 17:22, 122.13s elapsed (18 services on 1 host)
Initiating OS detection (try #1) against host1.example.com (192.168.0.5)
Retrying OS detection (try #2) against host1.example.com (192.168.0.5)
Retrying OS detection (try #3) against host1.example.com (192.168.0.5)
Retrying OS detection (try #4) against host1.example.com (192.168.0.5)
Retrying OS detection (try #5) against host1.example.com (192.168.0.5)

192.168.0.5: guessing hop distance at 1
Initiating Traceroute at 17:22
Completed Traceroute at 17:22, 0.13s elapsed
Initiating Parallel DNS resolution of 2 hosts. at 17:22
Completed Parallel DNS resolution of 2 hosts. at 17:22, 0.38s elapsed
NSE: Script scanning 192.168.0.5.
NSE: Starting runlevel 1 scan
Initiating NSE at 17:22
Completed NSE at 17:22, 7.59s elapsed
NSE: Script Scanning completed.

Host host1.example.com (192.168.0.5) is up (0.027s latency).

Interesting ports on host1.example.com (192.168.0.5):

Not shown: 982 closed ports

PORT STATE SERVICE VERSION
21/tcp open ftp?
80/tcp open http Oracle Application Server 10g httpd 10.1.2.0.0
111/tcp open rpcbind
| rpcinfo:
| 100000 2,3,4 111/udp rpcbind
| 100003 2,3 2049/udp nfs
| 100227 2,3 2049/udp nfs_acl
| 100021 1,2,3,4 4045/udp nlockmgr
| 100026 1 32780/udp bootparam
| 100024 1 32787/udp status
| 100133 1 32787/udp nsm_addrand
| 100001 2,3,4 32797/udp rstatd
| 100011 1 32798/udp rquotad
| 100005 1,2,3 32799/udp mountd
| 100000 2,3,4 111/tcp rpcbind
| 100003 2,3,4 2049/tcp nfs
| 100227 2,3 2049/tcp nfs_acl
| 100021 1,2,3,4 4045/tcp nlockmgr
| 100026 1 32771/tcp bootparam
| 1073741824 1 32772/tcp fmproduct
| 100024 1 32773/tcp status
| 100133 1 32773/tcp nsm_addrand
|_ 100005 1,2,3 32777/tcp mountd
443/tcp open ssl/http Oracle Application Server 10g httpd 10.1.2.0.0
1521/tcp open oracle-tns Oracle TNS Listener 10.2.0.4.0 (for Solaris)
2049/tcp open rpcbind
2222/tcp open ssh (protocol 2.0)
| ssh-hostkey: 1024 1f:ed:ac:a3:26:86:65:e1:df:42:61:61:0a:69:bf:37 (DSA)
|_ 2048 02:53:46:67:91:0d:0b:0c:f5:45:d7:48:00:39:61:b1 (RSA)
4045/tcp open rpcbind
5000/tcp open upnp?
6003/tcp open X11:3?
6112/tcp open dtspc?
8080/tcp open http Apache httpd 2.0.63 ((Unix) DAV/2)
|_ html-title: Test Page for Apache Installation
32771/tcp open rpcbind
32772/tcp open rpcbind
32773/tcp open rpcbind
32777/tcp open rpcbind
32778/tcp open sometimes-rpc19?
32779/tcp open oracle-tns Oracle TNS Listener

==============NEXT SERVICE FINGERPRINT (SUBMIT INDIVIDUALLY)==============
SF-Port2222-TCP:V=5.00%I=7%D=10/29%Time=4AE97A6E%P=i686-pc-windows-windows
SF:%r(NULL,12,"SSH-2\.0-unknown\r\n");
==============NEXT SERVICE FINGERPRINT (SUBMIT INDIVIDUALLY)==============

SF-Port32779-TCP:V=5.00%I=7%D=10/29%Time=4AE97A91%P=i686-pc-windows-windows%r(oracle-tns,24,"\0\$\0\0\x04\0\0\0\"\0\0\x18\(DESCRIPTION=\(ERR=115\)\)\SF:0");

No exact OS matches for host (If you know what OS is running on it, see http://nmap.org/submit/ ).

TCP/IP fingerprint:

OS:SCAN(V=5.00%D=10/29%OT=21%CT=1%CU=42571%PV=Y%DS=1%G=Y%TM=4AE97AF8%P=i686
OS:-pc-windows-windows)SEQ(SP=106%GCD=1%ISR=10B%TI=I%CI=I%II=I%SS=S%TS=7)SE
OS:Q(SP=106%GCD=1%ISR=10B%TI=I%CI=I%TS=7)OPS(O1=NNT11M5B4NW0NNS%O2=NNT11M5B
OS:4NW0NNS%O3=NNT11M5B4NW0%O4=NNT11M5B4NW0NNS%O5=NNT11M5B4NW0NNS%O6=NNT11M5
OS:B4NNS)WIN(W1=C050%W2=C330%W3=C1CC%W4=C0E9%W5=C068%W6=C0B7)ECN(R=Y%DF=N%T
OS:=3C%W=C1E8%O=M5B4NW0NNS%CC=Y%Q=)T1(R=Y%DF=N%T=3C%S=O%A=S+%F=AS%RD=0%Q=)T
OS:2(R=N)T3(R=N)T4(R=Y%DF=Y%T=80%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5(R=Y%DF=N%T=8
OS:0%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)T6(R=Y%DF=Y%T=80%W=0%S=A%A=Z%F=R%O=%RD=0%
OS:Q=)T7(R=N)U1(R=Y%DF=N%T=FF%IPL=70%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G
OS:)IE(R=Y%DFI=S%T=FF%CD=S)

Uptime guess: 1.257 days (since Wed Oct 28 11:12:15 2009)
Network Distance: 1 hop
TCP Sequence Prediction: Difficulty=262 (Good luck!)
IP ID Sequence Generation: Incremental

TRACEROUTE (using port 1025/tcp)

HOP RTT ADDRESS
1 109.00 192.168.2.1
2 0.00 host1.example.com (192.168.0.5)

Read data files from: C:\Program Files\Nmap

OS and Service detection performed. Please report any incorrect results at http://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 173.69 seconds
Raw packets sent: 1641 (77.208KB) | Rcvd: 1075 (46.164KB)

Сюрприз! Здесь, несмотря на снятый файрвол, ОС идентифицировать не удалось! (хотя человек, глядя на баннеры, которые никто и не думал прятать, конечно, идентифицирует ОС с высокой вероятностью).

Проверим еще одну машину Solaris 10 x86 (32 бита) 10/09 с установленным сервисом NetTune и настроенным по рекомендациям файрволом:

Starting Nmap 5.00 ( http://nmap.org ) at 2009-10-29 17:42 Северная Центр. Азия (зима)

NSE: Loaded 30 scripts for scanning.
Initiating ARP Ping Scan at 17:42
Scanning 192.168.0.3 [1 port]
Completed ARP Ping Scan at 17:42, 0.22s elapsed (1 total hosts)
Initiating SYN Stealth Scan at 17:42
Scanning ktulhu.fhtagn.com (192.168.0.3) [5 ports]
Discovered open port 53/tcp on 192.168.0.3
Discovered open port 80/tcp on 192.168.0.3
Discovered open port 8080/tcp on 192.168.0.3
Discovered open port 2222/tcp on 192.168.0.3
Completed SYN Stealth Scan at 17:42, 1.25s elapsed (5 total ports)
Initiating UDP Scan at 17:42
Scanning ktulhu.fhtagn.com (192.168.0.3) [5 ports]
Completed UDP Scan at 17:42, 1.25s elapsed (5 total ports)
Initiating Service scan at 17:42
Scanning 9 services on ktulhu.fhtagn.com (192.168.0.3)
Discovered open port 53/udp on 192.168.0.3
Discovered open|filtered port 53/udp on ktulhu.fhtagn.com (192.168.0.3) is actually open
Discovered open port 123/udp on 192.168.0.3
Discovered open|filtered port 123/udp on ktulhu.fhtagn.com (192.168.0.3) is actually open
Completed Service scan at 17:43, 55.03s elapsed (9 services on 1 host)
Initiating OS detection (try #1) against ktulhu.fhtagn.com (192.168.0.3)
Retrying OS detection (try #2) against ktulhu.fhtagn.com (192.168.0.3)
NSE: Script scanning 192.168.0.3.
NSE: Starting runlevel 1 scan
Initiating NSE at 17:43
Completed NSE at 17:43, 4.27s elapsed
NSE: Script Scanning completed.

Host ktulhu.fhtagn.com (192.168.0.3) is up (0.00s latency).

Interesting ports on ktulhu.fhtagn.com (192.168.0.3):

PORT STATE SERVICE VERSION
53/tcp open domain ISC BIND unknown
80/tcp open http Apache httpd
|_ html-title: 403 Forbidden
123/tcp filtered ntp
2222/tcp open ssh OpenSSH 5.3 (protocol 2.0)
| ssh-hostkey: 1024 e8:01:51:4d:86:55:72:fb:40:1d:46:d4:82:1c:c0:cf (DSA)
|_ 1024 60:8f:2a:57:12:3b:e8:6b:14:28:9a:85:38:b5:b2:21 (RSA)
8080/tcp open http-proxy Squid webproxy 2.7.STABLE4
| http-open-proxy: Potentially OPEN proxy.
|_ Methods successfully tested: GET HEAD CONNECT
53/udp open domain ISC BIND unknown
|_ dns-recursion: Recursion appears to be enabled
80/udp open|filtered http
123/udp open ntp NTP v4
2222/udp open|filtered msantipiracy
8080/udp open|filtered unknown

MAC Address: 00:D0:B7:A0:87:74 (Intel)

Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port

Device type: general purpose

Running (JUST GUESSING) : Sun Solaris 10 (86%)

Aggressive OS guesses: Sun Solaris 10 (86%)

No exact OS matches for host (test conditions non-ideal).

Network Distance: 1 hop

Read data files from: C:\Program Files\Nmap
OS and Service detection performed. Please report any incorrect results at http://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 69.99 seconds
Raw packets sent: 107 (9704B) | Rcvd: 22 (1218B)

Здесь вероятность обнаружения резко выше, практически до попадания.

Почему? Потому что выполнялся UDP-скан, есть двунаправленные порты (53, например); а при наличии пары "открытый порт - закрытый порт" вероятность обнаружения повышается вплоть до точного попадания даже при выполнении всех вышеописанных настроек. То есть, на вероятность детектирования ОС влияют также общие параметры настройки файрвола, открытые и закрытые сервисные порты и режимы сканирования (Та же самая машина в режиме сканирования только TCP не идентифицируется по типу и версии ОС, либо NMap бодро рапортует об OpenBSD 4.0).

Таким образом, хотя обеспечить определенную защиту от идентификации ОС и можно, полностью скрыть версию и тип ОС не представляется возможным.

Также, впрочем, как и обеспечить абсолютную невидимость боевого истребителя от радарного обнаружения. ;)