電気ひつじ牧場

技術メモ

nmapでポートスキャンを試す

nmapを初めて触って見たので備忘録
CentOS7で試してます。

nmapとは?

network mapperの略です。サーバで開いているポートをスキャンするなど、セキュリティモニタリングに使われます。名前が似ているものにmmapがありますが、これはmallocなどの内部で使われるメモリ確保のためのシステムコールなので全く別物です。

注意

言うまでも無いですが自分の管理下に無いホストにポートスキャンするのは法に触れる可能性があるのでやめましょう。

基本の使い方

1~2000のポートをスキャン
$ nmap -p 1-2000 localhost
サブネット全てのホストのポートをスキャン

IP/ホストしか指定しない場合は1~1000までのポートしかスキャンされない模様

$ nmap 192.168.XX.1/24
全てのポートをスキャン
$ nmap -p- localhost
ホストで稼働しているサービスとその情報について調べる
$ nmap -A localhost

以下のように利用している公開鍵やサービスのバージョン情報などが得られます。

PORT     STATE SERVICE        VERSION
22/tcp   open  ssh            OpenSSH 7.4 (protocol 2.0)
ssh-hostkey: 2048 b5:f9:81:71:eb:c6:7f:55:43:25:b0:8b:c0:43:4c:b2 (RSA)
_256 75:06:22:b7:e2:3b:46:88:51:97:c4:4f:27:20:21:26 (ECDSA)
25/tcp open tcpwrapped
_smtp-commands: Couldn't establish connection on port 25
80/tcp open http Apache httpd 2.4.6 ((CentOS))
http-methods: Potentially risky methods: TRACE
_See http://nmap.org/nsedoc/scripts/http-methods.html
_http-title: Apache HTTP Server Test Page powered by CentOS

スキャンタイプ

多くのスキャンタイプが用意されていますが、主に使うのはSYN Stealth ScanとTCP Connect Scanです。

SYN Stealth Scan

TCPのSYNパケット(コネクション確立要求)をポートに送り、SYN/ACKが返って来た時点でポートが開いていると判断します。
実行にはroot権限が必要で、rootで実行した時はデフォルトでこのモードになります。明示したいなら-sSオプションをつけます。

# nmap -p 80 localhost 

tcpdumpでスキャンされたポートの挙動を確認してみます。

# tcpdump -vi lo 'tcp port 80'
tcpdump: listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
15:20:46.703843 IP (tos 0x0, ttl 42, id 43762, offset 0, flags [none], proto TCP (6), length 44)
    localhost.55992 > localhost.http: Flags [S], cksum 0xa4a0 (correct), seq 2374338805, win 1024, options [mss 1460], length 0
15:20:46.703863 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 44)
    localhost.http > localhost.55992: Flags [S.], cksum 0xfe20 (incorrect -> 0xbeb1), seq 3554636079, ack 2374338806, win 43690, options [mss 65495], length 0
15:20:46.703871 IP (tos 0x0, ttl 64, id 51482, offset 0, flags [DF], proto TCP (6), length 40)
    localhost.55992 > localhost.http: Flags [R], cksum 0xc059 (correct), seq 2374338806, win 0, length 0

パケットの送信方向は、
赤字がnmap -> http server
青字がhttp server -> nmap
です。Flags[S]はSYNパケット、Flags[S.]はSYN, ACKパケット、Flags[R]はRSTパケットを表しています。確かに標的ポートからSYN, ACKが返って来た時点で強制的にコネクションを切断しているのがわかります。

TCP Connect Scan

TCPの3-way-handshakeを行いコネクションを確立することで、ポートが開いていることを判断します。こちらはroot権限は必要ありませんが、以下のようなデメリットがあります。
1)SYNスキャンよりも低速。
2)IDS(Intrusion Detection System; 侵入検知システム)やfirewallに検出されやすい。
root権限がないときはデフォルトでこのスキャンタイプが使用されます。逆にrootの時は明示的に-sTオプションをつける必要があります。

$ nmap -p 80 localhost
or
# nmap -sT -p 80 localhost

こちらもtcpdumpで確認して見ます。

[root@server ~]# tcpdump -vi lo 'tcp port 80'
tcpdump: listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
15:25:46.134000 IP (tos 0x0, ttl 64, id 19227, offset 0, flags [DF], proto TCP (6), length 60)
    localhost.38237 > localhost.http: Flags [S], cksum 0xfe30 (incorrect -> 0xe184), seq 2702549441, win 43690, options [mss 65495,sackOK,TS val 4975322 ecr 0,nop,wscale 7], length 0
15:25:46.134020 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60)
    localhost.http > localhost.38237: Flags [S.], cksum 0xfe30 (incorrect -> 0x06d8), seq 1016705756, ack 2702549442, win 43690, options [mss 65495,sackOK,TS val 4975322 ecr 4975322,nop,wscale 7], length 0
15:25:46.134142 IP (tos 0x0, ttl 64, id 19228, offset 0, flags [DF], proto TCP (6), length 52)
    localhost.38237 > localhost.http: Flags [.], cksum 0xfe28 (incorrect -> 0xd91c), ack 1, win 342, options [nop,nop,TS val 4975322 ecr 4975322], length 0
15:25:46.134218 IP (tos 0x0, ttl 64, id 19229, offset 0, flags [DF], proto TCP (6), length 52)
    localhost.38237 > localhost.http: Flags [R.], cksum 0xfe28 (incorrect -> 0xd918), seq 1, ack 1, win 342, options [nop,nop,TS val 4975322 ecr 4975322], length 0
15:25:46.134327 IP (tos 0x0, ttl 64, id 22311, offset 0, flags [DF], proto TCP (6), length 60)

文字色は先ほどと同じ対応です。確かにSYN, SYN/ACK, ACKという3-way-handshakeによりコネクションの確立がされています。

FIN Scan

ポートにFINパケットが送られた際、空いているポートはそれを破棄する一方、閉じているポートはRSTパケットを送り返します。その特徴を利用したものがFIN Scanです。TCP Connect Scan, SYN Stealth Scanの検知にのみ対応しているIDSには有効です。

開いているポートに対してFINスキャンをかけて見ます。

# map -sF -p 80 localhost
[vagrant@server ~]$ sudo tcpdump -vi lo port 80
tcpdump: listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
04:09:47.183373 IP (tos 0x0, ttl 40, id 43279, offset 0, flags [none], proto TCP (6), length 40)
    localhost.61623 > localhost.http: Flags [F], cksum 0x7425 (correct), seq 1745477802, win 1024, length 0
04:09:48.186070 IP (tos 0x0, ttl 46, id 22071, offset 0, flags [none], proto TCP (6), length 40)
    localhost.61624 > localhost.http: Flags [F], cksum 0x7424 (correct), seq 1745412267, win 1024, length 0

80番ポートにFINパケットを送信しているのがわかります。開いているポートはFINパケットを破棄するので、何も返って来ていません。


次に閉じているポートにFINスキャンをかけて見ます。

# map -sF -p 50000 localhost
[vagrant@server ~]$ sudo tcpdump -vi lo port 50000
tcpdump: listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
04:13:40.401923 IP (tos 0x0, ttl 49, id 64336, offset 0, flags [none], proto TCP (6), length 40)
    localhost.55868 > localhost.50000: Flags [F], cksum 0x2c3c (correct), seq 2412794951, win 1024, length 0
04:13:40.401945 IP (tos 0x0, ttl 64, id 51783, offset 0, flags [DF], proto TCP (6), length 40)
    localhost.50000 > localhost.55868: Flags [R.], cksum 0x3028 (correct), seq 0, ack 2412794952, win 0, length 0

閉じているポートからはRSTパケットが返って来ています。これによりポートの開閉が判別できます。

他にも色々

今後追記します。多分。
Idleスキャンとか言うのが何やら面白そうなので実験したい