yassy's note

なんかかきます

nmapのスキャン方法

最近趣味でCTFの勉強したりしているが、よく使用するのがnmap。
nmapはポートスキャンツールとして知られているが、実際にどういう原理で動作しているのかは知らなかったので、今回勉強したことをまとめる。

nmapでよく使用されるスキャン方法は以下のようなものがある。カッコ内はnmapでのオプション。

  • TCP Connectスキャン(-sT)
  • TCP SYNスキャン(-sS) ※ハーフスキャン、ハーフオープンスキャンとも呼ばれる
  • UDP スキャン(-sU)
  • TCP Nullスキャン(-sN)
  • TCP FINスキャン(-sF)
  • TCP クリスマススキャン(-sX)

なお、nmapのデフォルトスキャン方法はユーザの権限によって異なり、
特権ユーザの場合はTCP SYNスキャン、特権でない場合はTCP Connectスキャンとなる。

nmapドキュメントより

-sS (TCP SYN scan) SYN scan is the default and most popular scan option for good reasons.

-sT (TCP connect scan) TCP connect scan is the default TCP scan type when SYN scan is not an option. This is the case when a user does not have raw packet privileges.

TCP Connectスキャン

3ウェイハンドシェイクにより、コネクションを確立させることでポートが開いているかを確認するスキャン方法。

f:id:yassy_225:20210802201252p:plain

対象サーバからSYN/ACKが返ってくれば、そのポートは開いていると判断できる。
もしポートが開いていないならば、対象サーバからはRSTが返ってくる。

この仕様はRFC793で定義されている。

  1. If the connection does not exist (CLOSED) then a reset is sent in response to any incoming segment except another reset. In particular, SYNs addressed to a non-existent connection are rejected by this means.
    1.もし接続が存在しないなら(CLOSED)、リセット以外どんな入ってくる セグメントに対しても、リセットが送られる。特に、非実在の接続へのSYNs がこの手段によって拒絶される。

実際にwiresharkで挙動を確認するのが分かりやすい。
まずはポートが開いていた場合。

$ sudo nmap -sT -p 80 10.10.149.87 -vv -Pn
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times will be slower.
Starting Nmap 7.91 ( https://nmap.org ) at 2021-08-02 20:02 JST
Initiating Parallel DNS resolution of 1 host. at 20:02
Completed Parallel DNS resolution of 1 host. at 20:02, 0.02s elapsed
Initiating Connect Scan at 20:02
Scanning 10.10.149.87 [1 port]
Discovered open port 80/tcp on 10.10.149.87
Completed Connect Scan at 20:02, 0.25s elapsed (1 total ports)
Nmap scan report for 10.10.149.87
Host is up, received user-set (0.25s latency).
Scanned at 2021-08-02 20:02:58 JST for 0s

PORT   STATE SERVICE REASON
80/tcp open  http    syn-ack

Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 0.33 seconds

f:id:yassy_225:20210802200512p:plain

今回80番ポートは開いているので、サーバからSYN/ACKが返却された。
最後のRST/ACKについては、接続を張ったままとしないようにクライアントから送られたものだと考えられる。

次に、ポートが開いていなかった場合。

$ sudo nmap -sT -p 80 localhost -vv -Pn
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times will be slower.
Starting Nmap 7.91 ( https://nmap.org ) at 2021-08-02 20:21 JST
Warning: Hostname localhost resolves to 2 IPs. Using 127.0.0.1.
Initiating Connect Scan at 20:21
Scanning localhost (127.0.0.1) [1 port]
Completed Connect Scan at 20:21, 0.00s elapsed (1 total ports)
Nmap scan report for localhost (127.0.0.1)
Host is up, received user-set (0.00012s latency).
Other addresses for localhost (not scanned): ::1
Scanned at 2021-08-02 20:21:22 JST for 0s

PORT   STATE  SERVICE REASON
80/tcp closed http    conn-refused

Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 0.07 seconds

f:id:yassy_225:20210802202244p:plain

ローカルホストの80番ポートは開けていないため、RSTが返却されている。

f:id:yassy_225:20210802202553p:plain

ただし、一般的な構成ではファイアウォールを置いていることが多く、
その場合はパケットがドロップされる=対象サーバまで届かない=RSTが返却されない。

結果としてはSYNに対する応答が返ってこないため、nmapはフィルタリングされていると判断する。

$ sudo nmap -sT -p 85 10.10.149.87 -vv -Pn
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times will be slower.
Starting Nmap 7.91 ( https://nmap.org ) at 2021-08-02 20:28 JST
Initiating Parallel DNS resolution of 1 host. at 20:28
Completed Parallel DNS resolution of 1 host. at 20:28, 0.01s elapsed
Initiating Connect Scan at 20:28
Scanning 10.10.149.87 [1 port]
Completed Connect Scan at 20:28, 2.00s elapsed (1 total ports)
Nmap scan report for 10.10.149.87
Host is up, received user-set.
Scanned at 2021-08-02 20:28:18 JST for 2s

PORT   STATE    SERVICE    REASON
85/tcp filtered mit-ml-dev no-response

Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 2.07 seconds

TCP SYNスキャン

TCP SYNスキャンはTCP Connectスキャンと似ているが、コネクションを成立させないという特徴がある。
以下の図のように、サーバからSYN/ACKが返却された後にRSTでコネクションを切断するのだ。

f:id:yassy_225:20210802203422p:plain

確かに、nmapからはSYN/ACKが返却された時点でポートが開いていることは判明しているので、
余計なやり取りをしなくて済む。
(我々が行いたいのはポートスキャンであって、コネクションの成立ではないのだ)

また、この方法では接続が成立していないため、サーバにログが残らないメリット(?)がある。
ただし、間のファイアウォールにはログが記録される可能性がある。

$ sudo nmap -sS -p 80 10.10.149.87 -vv -Pn
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times will be slower.
Starting Nmap 7.91 ( https://nmap.org ) at 2021-08-02 20:35 JST
Initiating Parallel DNS resolution of 1 host. at 20:35
Completed Parallel DNS resolution of 1 host. at 20:35, 0.03s elapsed
Initiating SYN Stealth Scan at 20:35
Scanning 10.10.149.87 [1 port]
Discovered open port 80/tcp on 10.10.149.87
Completed SYN Stealth Scan at 20:35, 0.29s elapsed (1 total ports)
Nmap scan report for 10.10.149.87
Host is up, received user-set (0.25s latency).
Scanned at 2021-08-02 20:35:34 JST for 0s

PORT   STATE SERVICE REASON
80/tcp open  http    syn-ack ttl 127

Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 0.41 seconds
           Raw packets sent: 1 (44B) | Rcvd: 1 (44B)

f:id:yassy_225:20210802203656p:plain

ポートが開いていなかった場合の挙動は、TCP connectスキャンと同様に、サーバからRSTが返却される。

UDP スキャン

UDPTCPと異なり相手の応答を待たないため、ポートスキャンにおいては厄介である。
基本的には接続要求に対して応答を行わないため、nmapからはopen|filteredと判断される。(開いているのかドロップされているのか判断できないため)

$ sudo nmap -sU -p 80 10.10.149.87 -vv -Pn
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times will be slower.
Starting Nmap 7.91 ( https://nmap.org ) at 2021-08-02 20:49 JST
Initiating Parallel DNS resolution of 1 host. at 20:49
Completed Parallel DNS resolution of 1 host. at 20:49, 0.02s elapsed
Initiating UDP Scan at 20:49
Scanning 10.10.149.87 [1 port]
Completed UDP Scan at 20:49, 2.04s elapsed (1 total ports)
Nmap scan report for 10.10.149.87
Host is up, received user-set.
Scanned at 2021-08-02 20:49:08 JST for 2s

PORT   STATE         SERVICE REASON
80/udp open|filtered http    no-response

Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 2.15 seconds
           Raw packets sent: 2 (84B) | Rcvd: 0 (0B)

ただし、ポートが閉じている場合にはICMPパケット(Destination unreachable(Port unreachable))が返却されるため、
閉じているポートについては判断できる。

$ sudo nmap -sU -p 80 localhost -vv -Pn
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times will be slower.
Starting Nmap 7.91 ( https://nmap.org ) at 2021-08-02 20:40 JST
Warning: Hostname localhost resolves to 2 IPs. Using 127.0.0.1.
Initiating UDP Scan at 20:40
Scanning localhost (127.0.0.1) [1 port]
Completed UDP Scan at 20:40, 0.03s elapsed (1 total ports)
Nmap scan report for localhost (127.0.0.1)
Host is up, received user-set (0.000052s latency).
Other addresses for localhost (not scanned): ::1
Scanned at 2021-08-02 20:40:16 JST for 0s

PORT   STATE  SERVICE REASON
80/udp closed http    port-unreach ttl 64

Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 0.14 seconds
           Raw packets sent: 1 (42B) | Rcvd: 2 (112B)

f:id:yassy_225:20210802204837p:plain

TCP Nullスキャン

TCP Nullスキャンは、何のフラグも立てていないパケットを送信する方法。
コネクションの成立はできないため、UDPスキャンと同じく開いているポートの判断ができない。
しかし、閉じているポートからはRSTが返却されるため、閉じているポートが何かを調査する場合に使用する。

$ sudo nmap -sN -p 80 10.10.149.87 -vv -Pn
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times will be slower.
Starting Nmap 7.91 ( https://nmap.org ) at 2021-08-02 20:50 JST
Initiating Parallel DNS resolution of 1 host. at 20:50
Completed Parallel DNS resolution of 1 host. at 20:50, 0.01s elapsed
Initiating NULL Scan at 20:50
Scanning 10.10.149.87 [1 port]
Completed NULL Scan at 20:50, 2.04s elapsed (1 total ports)
Nmap scan report for 10.10.149.87
Host is up, received user-set.
Scanned at 2021-08-02 20:50:51 JST for 2s

PORT   STATE         SERVICE REASON
80/tcp open|filtered http    no-response

Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 2.14 seconds
           Raw packets sent: 2 (80B) | Rcvd: 0 (0B)

wiresharkで確認すると、このように何のフラグも立っていないことが分かる。

f:id:yassy_225:20210802205601p:plain

TCP FINスキャン

TCP FINスキャンは、FINフラグのみを立てたパケットを送信する方法。
こちらもNullスキャンと同じく、コネクションの成立ができないため、閉じているポートが何かを調査する場合に使用する。

f:id:yassy_225:20210802210041p:plain

TCP クリスマススキャン

なんか楽しそうな名前であるが、FIN、URG(緊急に処理すべきデータを含んでいる)、PUSH(データを即座に上位層に渡す)フラグを立てたパケットを送信する方法。
こちらもNullスキャン、FINスキャンと同様に閉じているポートの調査に使用する。
名前の由来は、フラグがクリスマスツリーのごとく点灯しているように見えることから。

f:id:yassy_225:20210802210633p:plain

TCP Nullスキャン、FINスキャン、クリスマススキャンについては、特定のファイアウォールによるフィルタリングを回避するために使用される。