オンラインソフトを使え! 「第12回 Netcat」


NetworkWorld 2004年9月号


本文書は、NetworkWorld誌に寄稿した記事の原稿を、IDGジャパン編集部殿の許可を得た上で掲載したものです。




システム管理をしていると、システムの動作確認などでSMTPサーバやWebサーバ等に直接アクセスし、生のプロトコルで通信したいといったケースがよくある。今回はそのような時に便利なツール、「Netcat」を紹介しよう。

NetcatはHobbit氏によって開発された、汎用TCP/UDP接続コマンドラインツールである。接続先IPアドレス(もしくはホスト名)とポート番号を指定することにより、その接続先の該当するポートで待ち受けているサーバソフトウェアと通信することができる。またリッスンモードでは、指定したポート番号で通信を待ち受け、接続してきたクライアントソフトウェアと会話することも可能だ。




Netcatのインストール


Netcatは1995年から1996年にかけて開発が行われ、1996年3月にバージョン1.10がリリースされたが、それ以降現在までの8年間、特にバージョンアップされることもなく多くのシステム管理者、ネットワーク技術者に利用され続けている。このことは、基本ツールとしてのNetcatの完成度の高さを物語っている。

もともとNetcatはUNIXプラットフォーム向けに開発されたが、1998年にWeld Pond氏によってWindowsプラットフォームに移植された。その際に若干の機能が追加されたものの、基本的にUNIX版とWindows版はほとんど同じと考えてよい。いずれのバージョンもソースコード込みで配布されており、クレジットを明記する限り、自由に使用・改変することが作者によって認められている。

Netcatは以下のサイトからダウンロードすることができる。

    http://www.atstake.com/research/tools/
    
    「Netcat 1.10 for Unix」→ UNIX版Netcat
    「Netcat 1.1 for Win 95/98/NT/2000」→ Windows版Netcat
    
Windows版Netcatは実行モジュール込みのZIPファイルとして提供されているため、特にインストール作業は必要としない。適当なディレクトリにZIPファイル中の「nc.exe」をコピーすればよい。

UNIX/Linuxについては、Netcatは今や多くのディストリビューションに含まれているが、ソースコードからビルドするには、上記サイトからUNIX版Netcat(nc110.tgz)をダウンロードし、適当なディレクトリに展開後、以下のコマンドラインでmakeする。

    make <systype> DFLAGS="-DGAPING_SECURITY_HOLE -DTELNET"
    
「<systype>」には、プラットフォームにより「linux」や「freebsd」、「solaris」などのキーワードが入る。

    例)make linux DFLAGS="-DGAPING_SECURITY_HOLE -DTELNET"
    
具体的にどのプラットフォームでどのキーワードを指定するかは、Makefileの中を確認してもらいたい。

makeコマンドに与えている「DFLAGS="-DGAPING_SECURITY_HOLE -DTELNET"」は、コンパイルオプションである。「-DGAPING_SECURITY_HOLE」は「-eオプション」を、「-DTELNET」は「-tオプション」を有効にする。

Linux環境下ではmakeコマンド実行時に、「undefined reference to 'res_init'」というエラーによって異常終了する場合があるが、その際はnetcat.cに「#include <resolv.h>」という行を追加してやれば解決する。

makeが正常に終了すると、カレントディレクトリに「nc」というファイルが生成される。これがNetcatの実行モジュールである。

以下のコマンドラインの実行により、Netcatのヘルプ情報を表示することができる。

    nc -h
    
表1に、Netcat(UNIX版)がサポートするオプションの一覧を示す。


表1 Netcat(UNIX版)がサポートするオプションの一覧





Netcatでサービスと通信する


Netcatの基本的な使い方は、極めてシンプルで、次のようなコマンドラインを入力すればよい。

    nc ホスト名 ポート番号
    
「ホスト名」には接続先のホストを指定するが、これはIPアドレスでも構わない。「ポート番号」は、接続先ホスト上で稼動しているサービスのポート番号である。デフォルトでTCPが用いられる。これにより、該当するホストのポート番号に接続が行われ、文字ベースでサービスと通信することができる。

図1は、pc-shio-rh71というホスト上で動いているSMTPサービス(TCP/25)に対し、Netcatで接続した例である。


図1 NetcatでSMTPサービスに接続した例。接続後、HELPコマンドでヘルプ情報を表示させ、QUITコマンドで終了している


ここに表示されている「HELP」および「QUIT」という文字列は、Netcat側からサーバに対して送信したSMTPコマンドで、それぞれヘルプ情報の表示および接続の終了を意味している。つまりここでは、SMTPサービスに接続し、ヘルプ情報を表示させた後、接続を終了していることになる。メール送信に関するSMTPコマンドを知っていれば、このように接続することで、Netcatを使ってメールを送信することもできる。

また図2は、NetcatでWebサービス(TCP/80)に接続した例を示している。


図2 NetcatでHTTPサービスに接続した例。HEADメソッドでWebページのヘッダ情報を取得


ここではpc-shio-rh71というホストのTCP80番ポートに接続後、「HEAD / HTTP/1.0」とキーインし、リターンキーを二回入力している。「HEAD / HTTP/1.0」というのはHTTPリクエストの一種で、サーバに対してHTTPヘッダ情報を要求していると考えてもらえればよい。「HTTP/1.1 200 OK」以降はWebサーバからの返答である。さまざまなHTTPヘッダ情報がサーバから送信されていることがわかる。

このようにNetcatでサーバと接続することにより、サービスプログラムと直接会話することができるため、文字列ベースのプロトコルのテストや、サービスの稼動状況のチェック等、さまざまな局面で利用することが考えられる。




Netcatのリッスンモード


Netcatは前述したような、ネットワークサービスプログラムのクライアントとしての使い方の他に、リッスンモードによりサービスプログラムとして機能することもできる。Netcatをリッスンモードで起動する場合は、次のように「-l」オプションを使用する。

    nc -l -p ポート番号
    
「-p」オプションはリッスンするポート番号(デフォルトではTCP)を指定している。「-p」オプションを指定しない場合は、空いているポート番号が自動的に選択される。

図3はHost-A上でNetcatをリッスンモードで起動し、TCPポート番号1234で待ち受けているところに、Host-Bから同じくNetcatで接続したところを表している。


図3 リッスンモードでNetcatが動作するHost-Aに対し、Host-Bから接続したところ


Host-Bの端末上で「aaaaa」という文字列を入力すると、Netcat同士の通信を経由してHost-Aに送られ、Host-Aの端末上に表示される。逆にHost-A上で入力した文字列「bbbbb」は、Host-B上に表示される。通信を終了する際は、いずれかの端末上で「Ctrl-C」を入力すればよい。

Netcatのリッスンモードを利用することで、Netcat同士の通信を経由したコンピュータ間のファイル転送も可能となる。まずファイルの受け側のコンピュータ上にて、以下のようにリッスンモードでNetcatを起動する。

    nc -l -p ポート番号 > ファイル名
    
次にファイルの送り側で、次のようなコマンドラインを実行する。

    nc ホスト名 ポート番号 < ファイル名
    
送信するファイルは、テキストファイルに限らない。実行モジュール等のバイナリファイルを送ることも可能である。

Netcatを用いたファイル転送は、このように非常に手軽に行うことができるため、ネットワークアクセスが制限されていてFTP等が使用できないような環境下で、ちょっとファイルを送りたいといったような場合に大変重宝する。ただし、Netcatは単純な通信の機能しか持っておらず、相手の認証や通信データの暗号化は行わない。Netcatのリッスンモードを使用する際にはそのことを常に念頭におき、十分注意する必要があるだろう。(注:Netcatに暗号化機能を追加した「CryptCat」というツールも公開されている)




バックドアにも使える「-e」オプション


ローカルコンピュータ上でのNetcatに対する入力およびNetcatからの出力は、通常は標準入出力(つまりキーボードと端末表示)に割り当てられているのだが、「-e」オプションを指定することで入出力先を他のプログラムにリダイレクトすることができる。

NetcatをTCPポート1234番においてリッスンモードで起動し、入出力を「/bin/sh」つまり「シェル」にリダイレクトしているコマンドラインの例を以下に示す。

    nc -l -p 1234 -e /bin/sh
    
これにより、このホストのTCP/1234への通信は、入出力がすべてシェルにリダイレクトされる。つまり、リモートからNetcatでこのホストのTCP/1234に接続しているユーザは、このホスト上で動作するシェルに自由にアクセスすることができるわけだ。

図4は、Host-AにてNetcatを「-e /bin/sh」付きリッスンモードで動作しているところに、Host-Bが接続し、「uname」コマンドでHost-Aの情報を表示させているところを表している。この際のユーザ権限は、リッスンモードのNetcatを起動したHost-Aのユーザの権限に等しくなる。


図4 Netcatで/bin/shのバックドアを開いたHost-Aに対し、Host-Bから接続


このように正規のログイン手続きを踏まずに、ネットワーク経由でシェルにアクセスできるような入り口のことを、一般に「バックドア」と呼ぶ。前述のとおりNetcatにはユーザ認証の機能がないため、第三者がそのホストの当該ポートに接続することを考えると、このようなバックドアは極めて危険性が高い。

バックドアに対する不正接続のリスクを低減させるためには、接続元のIPアドレスおよびソースポート番号を限定することが考えられる。Netcatのリッスンモードでは、接続してくるホストのIPアドレスおよびソースポート番号を指定することができるので、Netcatでバックドアを開く際には、最低限この指定を行うことが望ましい。

接続元IPアドレスとソースポート番号は、以下のようにコマンドラインの最後に指定する。

    nc -l -p 1234 -e /bin/sh 接続元IPアドレス ソースポート番号
    
このように指定することで、このNetcatに対する「接続元IPアドレス」以外からの接続要求は拒否される。「接続元IPアドレス」からの接続要求であっても、「ソースポート番号」が異なれば、やはり接続は拒否される。

とはいえ、ユーザ認証が不要なバックドアが危険であることは変わりがないので、リスクを十分認識した上で使用することが求められる。Netcatをmakeする際に、わざわざ「-DGAPING_SECURITY_HOLE」というコンパイルオプションを指定したが、このオプションを指定せずにmakeすると、「-e」オプションなしのNetcatが生成される。一般ユーザが使用するNetcatをmakeする場合は、安全のために「-DGAPING_SECURITY_HOLE」なしでコンパイルする方がよいかも知れない。




Netcatによるポートスキャン


さてここまでは、Netcatを使って相手と通信する方法をいろいろと述べてきたが、Netcatにはもう一つの使い方がある。それがポートスキャンである。

NetcatでTCPポートスキャンを行う場合、次のようなコマンドラインを指定する。

    nc -z -v ホスト名 ポート番号
    
ここで「-z」というオプションは、「ゼロI/Oモード」を意味している。NetcatはゼロI/Oモードが指定されると、TCPの場合は相手先のポートに接続した後、すぐに接続を切断する。UDPでは相手のポートにパケットを送り、一定時間反応を待った後に処理を終了する。つまりゼロI/Oモードでは、実際のデータ通信は行われない。

「-v」オプションは、一般的なUNIXコマンドのそれと同じく「verbose(多弁)」を意味する。Netcatはこのオプションを付けることにより、接続の可否や、名前解決結果など、詳細な情報を表示するようになる。

ポートスキャン時に指定するポート番号は、単一の番号のみならず、スペースで区切って複数の番号を列挙しても良いし、連続した範囲であれば「1-1023」のようにハイフンで区切って指定することもできる。

図5に、ホストpc-shio-rh71に対して、ポート1から1023の範囲でTCPポートスキャンを実行した結果を示す。


図5 TCPポートスキャンを実行した結果。開いているポートは「open」と表示される


また、UDPのポートスキャンを行う場合は、次のように「-u」オプションを指定する。

    nc -z -v -u ホスト名 ポート番号
    
ただしNetcatはそもそもポートスキャン専用ソフトウェアではないため、多数のポートを連続して高速スキャンするには向かない。ポートの開閉状況やフィルタリング状況を、一つ一つチェックするといった使い方が適しているだろう。




ソースルーティング機能


Netcatに「-g」オプションを指定することにより、任意のゲートウェイホストを経由したソースルーティングを行うことができる。

ソースルーティングとはIPオプションの一種で、IPパケットのルーティングをルータ任せにするのではなく、パケット送信元が経由ルータ(ゲートウェイ)を明示的に決定するものだ。経由するルータすべてを指定し、それ以外の経由は許さない「ストリクト・ソースルーティング」と、指定したルータは必ず経由するが、その他はルータの経路情報に委ねる「ルーズ・ソースルーティング」の二種類がある。Netcatがサポートしているのは、後者のルーズ・ソースルーティングである。

Netcatでソースルーティングを行うには、次のように「-g」オプションおよび経由するルータを指定する。

    nc -g 経由ルータ ホスト名 ポート番号
    
このようにオプション指定することで、送出されるパケットは必ず経由ルータを経由してからあて先ホストに到達するようになる。

複数のルータを明示的に経由させたい場合は、次のように複数の「-g」オプションを指定すればよい。

    nc -g 経由ルータ1 -g 経由ルータ2 ホスト名 ポート番号
    
「-g」オプションは最大8つまで指定することが可能である。

ソースルーティングは、予期しない経路からパケットが侵入してしまったり、あるいはソースIPアドレスを詐称した不正な接続に用いられたりする危険性がある。そのためセキュリティ上、ルータやファイアウォールでソースルーティングされたパケットを通過させないことが推奨されているが、そのような設定が正しく行われているかどうかをテストする際にも、Netcatのソースルーティング機能は非常に役に立つ。




Windows版Netcat


前述のとおり、NetcatはもともとUNIXベースのOS向けに開発され、その後Windowsに移植されたが、Windows版NetcatにはUNIX版に存在しない次の二つの機能が追加されている。

    1) 「-L」オプションによる再リッスンモード

    通常の「-l」オプションによるリッスンモードの場合、相手側からの接続が切れるとリッスンしているNetcatは終了するが、「-L」オプションで起動した場合、Netcatは接続が切れても繰り返しリッスンモードで待ち受けるようになる。

    2) 「-d」オプションによるステルスモード

    Netcatはコマンドラインプログラムであるため、通常はWindowsのコマンドプロンプト・ウィンドウ上で動作する。だが「-d」オプションを付けてステルスモードで起動すると、コマンドプロンプト・ウィンドウから切り離され、ウィンドウなしの状態で動作するようになる。

これら二つの機能はいずれも、Windows上でNetcatをバックドアとして動かす際に有用なオプションだ。例えばNetcatを次のようなコマンドで実行してみよう。

    start nc -d -L -p 1234 -e cmd.exe
    
これにより、TCP/1234で待ち受け、cmd.exeにリダイレクトするバックドアを設置することができる。その際、コマンドプロンプト・ウィンドウは表示されず、また、一度バックドアへの接続を切ってもNetcatは終了しないので、何度でも同じポート経由でバックドアにアクセスすることが可能になる。

このようにWindows版NetcatはUNIX版から機能拡張が行われているが、一方でWindows版では正常に動作しない機能もある。

筆者が把握している限り、Windows版Netcatでは以下の機能が正常に動作しない(もしくはサポートされていない)。

  • 「-z」および「-u」オプションによるUDPポートスキャン
  • 「-w」オプションによるタイムアウト
  • 「-g」オプションによるソースルーティング
  • 相手先IPアドレスおよびポートを指定した「-L」オプションによるリッスン
普通に使う分にはWindows版でも十分だが、本格的にいろいろと使い込むのであれば、UNIX版Netcatを用いることが推奨される。



2004年6月執筆
塩月 誠人
ネットワークセキュリティコンサルタント