ポートスキャンツール「Nmap」を使ったセキュリティチェック
サーバーの基本的なセキュリティ対策の1つとして重要なのが、ネットワーク内のどのマシンがどのポートでサービスを提供しているのかを把握することだ。このために有用なのが、ポートスキャナと呼ばれるツールだ。本記事ではポートスキャナとして有名な「Nmap」というソフトウェアを使用し、ポートスキャンを行う方法について解説する。
定番のポートスキャナ「Nmap」とは
対象として指定したホストに対してポート番号を変えながらIPパケットを送信し、その反応を調べることでどのポートが外部からアクセス可能なのかを調査する行為をポートスキャンと呼ぶ。Nmap(Network Mapperの略)は、オープンソース(GPLv2ライセンス)で開発・提供されているポートスキャンツール(ポートスキャナ)だ。NmapではOSが提供するソケット機能を利用するだけでなく、ポートスキャンに使用するパケットを独自に生成することで、高速なポートスキャンやファイアウォール/IPS(侵入検知システム)で保護されたサーバーに対するポートスキャンを可能にしているのが特徴だ。また、対象とするホストの挙動からそのOSやバージョンと行った情報を推測したり、稼働しているサーバーソフトウェアの種類やバージョンを取得するといった機能も備えている。
なお、Nmapには多くのスキャンオプションが用意されており、この中には特殊なパケットを送信して対象ホストの情報を取得するオプションや、発信元を隠してポートスキャンを実行することを可能にするオプション、侵入検知システムを回避することを可能にするオプションなどが用意されている。そのため、悪意のあるハッカーが攻撃対象のホストを調査する、といった用途にも利用できてしまう。他者が管理しているサーバーに対しポートスキャンを行うことは不正アクセスに該当する可能性もあるため、Nmapを利用する際は十分に注意してほしい。
Nmapのダウンロードとインストール
Nmapはマルチプラットフォーム対応が行われており、LinuxだけでなくWindowsやMac OS X、FreeBSDなど各種BSD、Solaris、HP-UXなどの各種UNIXでも動作する。ソースコードだけでなく、WindowsやMac OS X向けバイナリも提供されている。
Linux環境の場合、多くのLinuxディストリビューションで公式パッケージが提供されているので、それを利用するのが簡単だ。たとえばRed Hat Enterprise Linux(RHEL)やその互換OSであるCentOSなどでは「nmap」というパッケージでNmapのバイナリが提供されており、yumコマンドでインストールできる。
# yum install nmap
また、Gtk+で実装されたGUIフロントエンド(Zenmap)もnmap-frontendというパッケージで提供されている。GUIフロントエンドを利用したい場合はこちらもインストールしておこう。
# yum install nmap-frontend
なお、ディストリビューションの公式パッケージとして提供されているNmapは、そのバージョンがやや古いことがある。最新版のNmapを利用したいという場合やLinux以外のプラットフォームでNmapを利用したいという場合、NmapのWebサイト内のダウンロードページで公開されているバイナリやソースコード、ソースRPMを利用してインストールすれば良い。
たとえばWindows環境の場合、ダウンロードページの中頃に「Microsoft Windows binaries」という項目があり、そこにインストーラおよびZIPアーカイブのダウンロードリンクが用意されている。インストーラにはNmapが使用するWinPcap(オープンソースのパケットキャプチャライブラリ)も含まれているので、通常はインストーラを使ったインストールをおすすめする(図1)。また、このインストーラにはNmap本体に加え、GUIフロントエンドの「Zenmap」や各種ツールも同梱されている。
そのほか、ダウンロードページではMac OS X(x86版)向けのバイナリも提供されている。Mac OS Xユーザーはこちらを利用すると良いだろう。
Nmapを使ったポートスキャンを行う
Nmapのコアとなるのが、コマンドラインツールであるnmapコマンドだ。nmapコマンドの使い方はどのプラットフォームでも同じで、付属ドキュメントや「man nmap」コマンドで表示できるmanページでそのコマンドライン引数やオプションを確認できる。そのほか、NmapのWebサイトには日本語のドキュメントも用意されている(Nmap リファレンスガイド)。ただし、nmapコマンドには非常に多くのオプションが用意されており、manページの分量も多い。そこで、以下ではその基本的な機能に絞ってその使い方を解説していく。
シンプルなポートスキャン
nmapコマンドのもっともシンプルな使い方は、以下のように対象とするホスト名を指定してnmapコマンドを実行するものだ。
# nmap example.com/ Starting Nmap 5.51 ( http://nmap.org ) at 2012-12-26 17:01 JST Nmap scan report for example.com (***.***.***.***) Host is up (0.39s latency). rDNS record for ***.***.***.***: **********.***.**.** Not shown: 994 filtered ports PORT STATE SERVICE 22/tcp open ssh 25/tcp open smtp 80/tcp open http 995/tcp closed pop3s 3000/tcp closed ppp 8080/tcp closed http-proxy Nmap done: 1 IP address (1 host up) scanned in 38.84 seconds
nmapコマンドの実行結果では、ポートおよびその状態(STATE)、そのポートに対するサービス名が表示される。STATEの意味は表1のとおりだ。
STATE | 説明 |
---|---|
open | そのポートで何らかの待ち受けが行われている(ポートが開いている) |
closed | ポートにアクセス可能だが待ち受けを行っているアプリケーションはない(ポートが閉じられている) |
filtered | そのポートに対しパケットフィルタが適用されており、ポートが利用できるかを判断できない |
unfiltered | ポートへのアクセスは可能だが、ポートが開いているかどうかは判断できない |
open|filtered | ポートは開いている、もしくはパケットフィルタが適用されているが、そのどちらかは判断できない |
closed|filtered | ポートは閉じられている、もしくはパケットフィルタが適用されているが、そのどちらかは判断できない |
たとえばこの例では、TCPの22番および25番、80番、995番、3000番、8080というポートが検出されており、そのうち22番および25番、80番ポートは外部から接続可能で、サービスがこのポートに対しなんらかの待ち受けを行っているということが分かる。いっぽう、「STATE」が「closed」になっている995番および3000番、8080番については、そのポートへのアクセスは可能だが、そのポートで待ち受けを行っているサービスは存在しない、ということを示している。実はこのサーバーでは、ファイアウォール(iptables)を使用し、22番および25番、80番、995番、3000番、8080番以外のポートへの接続を拒否するように設定しており、995番および3000番、8080番への接続自体は可能になっている。ただし、ポートスキャンの実行時にはこれらポートを利用するサーバーアプリケーションは稼働させていなかった。そのため、これらのポートは「closed」と表示されている。
なお、nmapによるポートスキャンではサーバーのバージョンをチェックする-Aオプション(後述)などを利用しない限り、各サーバーアプリケーションのアクセスログにその痕跡が残ることはほとんどない。今回の例でも、唯一残されたのはmaillog内の以下のようなログだけだった。
Dec 26 17:01:42 taro postfix/smtpd[4346]: connect from unknown[unknown] Dec 26 17:01:42 taro postfix/smtpd[4346]: lost connection after CONNECT from unknown[unknown] Dec 26 17:01:42 taro postfix/smtpd[4346]: disconnect from unknown[unknown]
ただし、ファイアウォール(パケットフィルタ)でログを残すように設定を行っていた場合、そこにはポートスキャンの痕跡が残される場合がある。今回の場合では、パケットフィルタであるiptablesのログに同一のホストからの多数のアクセスが記録されていた。
IN=eth0 OUT= MAC=**:**:**:**:**:**:**:**:**:**:**:** SRC=***.***.**.*** DST=**.***.***.*** LEN=44 TOS=0x00 PREC=0x00 TTL=48 ID=54167 PROTO=TCP SPT=46701 DPT=443 WINDOW=1024 RES=0x00 SYN URGP=0 IN=eth0 OUT= MAC=**:**:**:**:**:**:**:**:**:**:**:**:**:** SRC=***.***.**.*** DST=**.***.***.*** LEN=44 TOS=0x00 PREC=0x00 TTL=33 ID=18420 PROTO=TCP SPT=46701 DPT=1723 WINDOW=4096 RES=0x00 SYN URGP=0 IN=eth0 OUT= MAC=**:**:**:**:**:**:**:**:**:**:**:**:**:** SRC=***.***.**.*** DST=**.***.***.*** LEN=44 TOS=0x00 PREC=0x00 TTL=36 ID=258 PROTO=TCP SPT=46701 DPT=587 WINDOW=3072 RES=0x00 SYN URGP=0 IN=eth0 OUT= MAC=**:**:**:**:**:**:**:**:**:**:**:**:**:** SRC=***.***.**.*** DST=**.***.***.*** LEN=44 TOS=0x00 PREC=0x00 TTL=34 ID=29587 PROTO=TCP SPT=46701 DPT=135 WINDOW=1024 RES=0x00 SYN URGP=0 : :
RHELやその互換OSの場合、デフォルトではiptablesのログを記録する設定にはなっていないが、この例のようにログから攻撃の予兆を検出することもできるため、必要に応じて設定を変更しておくと良いだろう。
ちなみにNmapの実行自体は一般ユーザー権限でも可能だが、その場合一部利用できない機能がある。たとえば一般ユーザー権限では後述するTCP SYNスキャンは実行できず、低速なTCP connectスキャンしか利用できない。そのため、Nmapは可能な限りroot権限で利用することをおすすめする。
さて、nmapコマンドは多数のオプションが用意されている。たとえば-vオプションを付けてnmapコマンドを実行すると、より詳細なログが出力される。
# nmap -v example.com Starting Nmap 5.51 ( http://nmap.org ) at 2012-12-20 20:03 JST Initiating Ping Scan at 20:03 Scanning example.com (***.***.***.***) [4 ports] Completed Ping Scan at 20:03, 0.04s elapsed (1 total hosts) Initiating Parallel DNS resolution of 1 host. at 20:03 Completed Parallel DNS resolution of 1 host. at 20:03, 0.15s elapsed Initiating SYN Stealth Scan at 20:03 Scanning example.com (***.***.***.***) [1000 ports] Discovered open port 25/tcp on ***.***.***.*** Discovered open port 80/tcp on ***.***.***.*** Discovered open port 22/tcp on ***.***.***.*** Completed SYN Stealth Scan at 20:03, 22.10s elapsed (1000 total ports) Nmap scan report for example.com (***.***.***.***) Host is up (0.024s latency). rDNS record for ***.***.***.***: www13376ue.sakura.ne.jp Not shown: 994 filtered ports PORT STATE SERVICE 22/tcp open ssh 25/tcp open smtp 80/tcp open http 995/tcp closed pop3s 3000/tcp closed ppp 8080/tcp closed http-proxy Read data files from: /usr/share/nmap Nmap done: 1 IP address (1 host up) scanned in 22.39 seconds Raw packets sent: 2963 (130.348KB) | Rcvd: 35 (2.268KB)
また、-Aオプションを付けるとポートスキャンに加えて対象ホストのOSやサービスのバージョンに関する情報も確認できる。
# nmap -A example.com Starting Nmap 5.51 ( http://nmap.org ) at 2012-12-20 20:10 JST Nmap scan report for example.com (***.***.***.***) Host is up (0.016s latency). rDNS record for ***.***.***.***: *****.***.**.** Not shown: 994 filtered ports PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 5.3 (protocol 2.0) | ssh-hostkey: 1024 b7:b5:03:3a:9c:4a:88:aa:07:8a:64:61:a5:cf:45:b9 (DSA) |_2048 ad:87:b3:6b:19:dc:03:20:c2:c9:5a:08:b2:05:be:a5 (RSA) 25/tcp open smtp Cisco PIX sanitized smtpd 80/tcp open http Apache httpd 2.2.15 ((CentOS)) | http-robots.txt: 2 disallowed entries |_/wp-admin/ /wp-includes/ |_http-methods: No Allow or Public header in OPTIONS response (status code 200) |_http-title: Sample Web Site |_http-favicon: 995/tcp closed pop3s 3000/tcp closed ppp 8080/tcp closed http-proxy Device type: WAP Running (JUST GUESSING): Linksys embedded (89%) Aggressive OS guesses: Linksys BEFW11S4 WAP (89%) No exact OS matches for host (test conditions non-ideal). Network Distance: 11 hops Service Info: Device: firewall TRACEROUTE (using port 995/tcp) HOP RTT ADDRESS 1 0.76 ms ***.***.***.** 2 0.34 ms ********.**.**.** (***.***.***.***) 3 0.38 ms ********.**.**.** (***.***.***.***) 4 15.51 ms ********.**.**.** (***.***.***.***) 5 15.99 ms ********.**.**.** (***.***.***.***) 6 16.02 ms ********.**.**.** (***.***.***.***) 7 23.36 ms ********.**.**.** (***.***.***.***) 8 23.39 ms ********.**.**.** (***.***.***.***) 9 23.61 ms ********.**.**.** (***.***.***.***) 10 23.69 ms ********.**.**.** (***.***.***.***) 11 24.25 ms ********.**.**.** (***.***.***.***) 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 27.33 seconds
たとえばこの例では、22番ポートではOpenSSH 5.3でOpenSSH 2.0プロトコルを使ったサービスが、80番ポートではApache httpd 2.2.15を使ったサービスが稼働していることが分かる。そのほか、ネットワーク経路に関する情報なども確認できる。
また、「Device type」や「Running」、「Aggressive OS guesses」では、対象ホストのOS推測結果が表示されている。ただし、この推測はあくまで外部からの推測であるため、必ずしも正しいものが表示されるとは限らない。たとえば今回の例では以下のように「Linksys BEFW11S4 WAP」(Linksysの無線LANルータ)の可能性が89%と検出されているが、実際はこのホストはVPS上で稼働しているLinuxサーバーだ。
Device type: WAP Running (JUST GUESSING): Linksys embedded (89%) Aggressive OS guesses: Linksys BEFW11S4 WAP (89%)
Nmapでは配布パッケージに含まれている「fingerprint」と呼ばれる情報を使用してOSの推測を行っている。そしてNmapのバージョンアップとともにfingerprint情報も増えており、推測精度も向上している。たとえば、先の例ではNmap 5.51を使っていたが、最新版であるNmap 6.25(Windows版)で同様のポートスキャンを実行すると、以下のように94%の確率でLinux 3.1~3.4、92%の確率でLinux 2.6.39、91%の確率でLinux 2.6.32~3.6と、それなりに正しい検出結果が得られている(実際の稼働OSはLinux 2.6.32)。
C:\>nmap -A example.com Starting Nmap 6.25 ( http://nmap.org ) at 2012-12-21 19:25 東京 (標準時) Nmap scan report for example.com (***.***.***.***) Host is up (0.015s latency). rDNS record for ***.***.***.***: ***.***.***.*** Not shown: 995 filtered ports PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 5.3 (protocol 2.0) | ssh-hostkey: 1024 b7:b5:03:3a:9c:4a:88:aa:07:8a:64:61:a5:cf:45:b9 (DSA) |_2048 ad:87:b3:6b:19:dc:03:20:c2:c9:5a:08:b2:05:be:a5 (RSA) 80/tcp open http Apache httpd 2.2.15 ((CentOS)) |_http-generator: WordPress 3.4.1 |_http-methods: No Allow or Public header in OPTIONS response (status code 200) | http-robots.txt: 2 disallowed entries |_/wp-admin/ /wp-includes/ |_http-title: Sample Web Site 995/tcp closed pop3s 3000/tcp closed ppp 8080/tcp closed http-proxy Aggressive OS guesses: Linux 3.1 - 3.4 (94%), Linux 2.6.39 (92%), HP P2000 G3 NAS device (91%), Linux 2.6.32 - 3.6 (91%), Linux 3.0 (90%), Ubiquiti AirMax NanoStation WAP (Linux 2.6.32) (90%), Linux 3.0 - 3.2 (89%), Linux 3.3 (89%), Netgear DG834G WAP or Western Digital WD TV media player (89%), Linux 2.6.32 (89%) No exact OS matches for host (test conditions non-ideal). Network Distance: 16 hops TRACEROUTE (using port 995/tcp) HOP RTT ADDRESS 1 1.00 ms ***.***.***.*** 2 6.00 ms ***.***.***.*** 3 7.00 ms ***.***.***.*** 4 7.00 ms ***.***.***.*** 5 8.00 ms ***.***.***.*** 6 8.00 ms ***.***.***.*** 7 8.00 ms ***.***.***.*** 8 57.00 ms ***.***.***.*** 9 8.00 ms ********.**.**.** (***.***.***.***) 10 8.00 ms ********.**.**.** (***.***.***.***) 11 8.00 ms ********.**.**.** (***.***.***.***) 12 15.00 ms ********.**.**.** (***.***.***.***) 13 15.00 ms ********.**.**.** (***.***.***.***) 14 16.00 ms ********.**.**.** (***.***.***.***) 15 18.00 ms ********.**.**.** (***.***.***.***) 16 16.00 ms ********.**.**.** (***.***.***.***) 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 26.14 seconds
なお、-sVオプションを指定するとバージョン検出のみを、-OオプションでOS検出のみを行うことが可能だ。
スキャンのタイミングを指定する
-Tオプションでは、ポートスキャンを行うタイミングを指定するオプションだ。-T0から-T5までの6段階を指定でき、数字が大きくなるほどスキャン速度が速くなる。ただし、スキャン速度を速くするとより高頻度で対象とするホストにパケットを送信することになるため注意が必要だ。通常は「-T4」がおすすめされている。いっぽう、IPSなどの防御システムが導入されているホストに対しては-T0や-T1といったオプションを指定することでそれらを回避できる可能性がある。
複数ターゲットの同時指定
Nmapでは複数のターゲットに対し同時にポートスキャンを実行することもできる。たとえば「192.168.1.1-10」と指定すると、192.168.1.1から192.168.1.10までを対象にポートスキャンを実行できる。また、ターゲットとするホストを1つ以上のスペース、タブ、改行文字で区切ってファイルに記述し、-iLオプションでそのファイルを指定することも可能だ。
スキャン対象とするポート範囲の指定
-pオプションを指定することで、ポートスキャンをする範囲を指定できる。Nmapはデフォルトでは1024番までのポートをスキャンするが、-pオプションでスキャン対象のポートを変更できる。対象ポートはカンマ区切りで指定できるほか、ハイフン(-)を使って範囲を指定することも可能だ。たとえば203.0.113.1から203.0.113.100までの範囲を対象に、かつポート番号1〜1024に対してポートスキャンを実行するには次のようにする。
# nmap -p 1-1024 203.0.113.1-100