オンラインソフトを使え! 「第3回 hping2」


NetworkWorld 2003年12月号


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




ネットワークシステムのセキュリティ対策を実施する際に、「はたしてこれで十分だろうか?」、「どこかに見落とした穴がないだろうか?」と自問するシステム管理者は多いだろう。ノーマルなネットワークアクセスには十分に耐えられるセキュリティシステムでも、通常考えられないような特殊なパケットがきた時に正常に対処できるだろうか? ある種の状態を持つパケットを素通しさせはしないだろうか?

現実問題として、アブノーマルなネットワークアクセスによりパケットフィルタリングを回避し、不正にアクセスできてしまうケースは数多く存在する。その原因はルール設定のミスの場合もあれば、ネットワーク装置の仕様という場合もある。いずれにせよ不正に侵入される前に、自らのネットワークシステムがアブノーマルなアクセスに対してどのように振舞うかをテストすることが重要だ。今回紹介するhping2は、そのようなネットワークセキュリティのテストに最適のフリーソフトウェアである。




hping2とは


hping2とは、一言で言うと汎用IPパケット送出ツールである。ただ送出するだけでなく、ターゲットからのリプライパケットを表示する機能を持つ。基本的な動きはpingコマンドを想像していただければよい。pingコマンドはターゲットに対してICMPエコーパケットを送出し、ICMPエコーリプライを受信、その結果を表示する。hping2はpingのようにICMPエコーを送出することはもちろん、その他のICMPパケット、さまざまな設定のTCPパケット、UDPパケット、さらに生(raw)のIPパケットを生成して送出することができる。つまり、通常のネットワークアクセスで発生するようなノーマルなパケットではない、いわばアブノーマルなパケットを自在に送出し、ターゲットからの返信を確認することができるのだ。

hping2の実行環境は、以下のプラットフォームがサポートされている。

  • Linux
  • OpenBSD
  • FreeBSD
  • NetBSD
  • Solaris



まずは使ってみよう


hping2の最新版(2.0.0-rc2)は、以下のサイトからダウンロードすることができる。

    http://www.hping.org/
    
tarコマンドでアーカイブされた圧縮ファイル「hping2.0.0-rc2.tar.gz」をダウンロードし、解凍・展開すると、「hping2-rc2」というディレクトリが作成される。インストールは通常のUNIXプログラムと同様、基本的にはconfigure、make、make installを行えばよい(添付のINSTALLファイルを参照)。インストールディレクトリ(通常は/usr/sbin)にはhping2というロードモジュールがコピーされると同時に、それに対するhpingという名前のシンボリックリンクが作成される。

まずはhping2をホスト「192.168.183.130」に対し、特にオプションを指定せずに使ってみよう。

    # hping2 192.168.183.130
    HPING 192.168.183.130 (eth0 192.168.183.130): NO FLAGS are set, 40 headers + 0 data bytes
    len=46 ip=192.168.183.130 ttl=128 id=12318 sport=0 flags=RA seq=0 win=0 rtt=0.0 ms
    len=46 ip=192.168.183.130 ttl=128 id=12319 sport=0 flags=RA seq=1 win=0 rtt=0.0 ms
    len=46 ip=192.168.183.130 ttl=128 id=12320 sport=0 flags=RA seq=2 win=0 rtt=0.0 ms
    len=46 ip=192.168.183.130 ttl=128 id=12321 sport=0 flags=RA seq=3 win=0 rtt=0.0 ms
    len=46 ip=192.168.183.130 ttl=128 id=12322 sport=0 flags=RA seq=4 win=0 rtt=0.0 ms
    len=46 ip=192.168.183.130 ttl=128 id=12323 sport=0 flags=RA seq=5 win=0 rtt=0.0 ms
    ^C
    --- 192.168.183.130 hping statistic ---
    6 packets tramitted, 6 packets received, 0% packet loss
    round-trip min/avg/max = 0.0/0.0/0.0 ms
    
hping2はオプション指定がない場合、デフォルトで相手ホストのTCPポート番号0に対して、すべてのフラグをOFFにしたTCPパケット(データ部は0バイト)を連続して送出し、相手ホストからのリプライパケットの情報を表示する。パケット送出を停止したい場合はCTRL-Cでブレイクすればよい。この例では6つ目のリプライパケットを受信した時点でブレイクしている。

リプライパケットの情報は各々1行ずつに表示されており、それぞれの項目は以下を表している。

    len 	キャプチャしたパケットデータサイズ
    ip  	ソースIPアドレス
    ttl 	TTL(Time to live)値
    id 	IP-ID値
    sport	ソースポート番号
    flags 	TCPフラグ(R:RESET, A:ACK, S:SYN, F:FIN, P:PUSH, U:URG, X:0x40, Y:0x80)
    seq 	リプライパケットの連番。TCP/UDPの場合は送出時のソースポート番号をインクリメントする
    	ことでリプライパケットの順番を判断する。ICMPの場合はICMPのシーケンス番号を用いる。
    win 	TCPのウィンドウサイズ
    rtt 	ラウンドトリップタイム(ミリ秒)
    
ここでは前述のとおり、ターゲットホスト192.168.183.130のTCP/0に対してフラグの立っていないTCPパケットを送出しているわけだが、それぞれについてRESETおよびACKのフラグが立ったリプライパケットが返ってきていることがわかる。

TCPパケットの場合はこの他にも、-Vオプションを付けることでTCP sequence numberやacknowledge number、TCPヘッダチェックサム等を表示することができる。

このようにhping2はデフォルトでTCPパケットを送出するが、以下のオプションによりデフォルトの動作を変更することも可能だ。

    -0	RAW IPモード。各種IPパケットを送出。
    -1	ICMPモード。各種ICMPパケットを送出。
    -2	UDPモード。各種UDPパケットを送出。
    -9	リッスンモード。パケットの送出は行わず、特定のシグネチャを持つパケットを受信。
    
hping2にはこの他にも、パケットのパラメータ設定やhping2自体の動作指定のための、非常に数多くのオプションがある。ここではいくつかの代表的な使い方をピックアップし、その際に指定するオプションについて解説するが、すべてのオプションはhping2のマニュアル(manページ)に記述されているのでそちらも合わせて参照していただきたい。




hping2によるパケットフィルタ機能のテスト


ファイアウォール、それも特にルータやスイッチに実装されているステートレスタイプのパケットフィルタは、ルールの設定を誤ると思わぬ「穴」をあけてしまうことになる。またパケットフィルタの仕様は機器によってさまざまであり、場合によっては特定のTCPフラグしか評価していなかったり、あるいは特定のソースポート番号のパケットを無条件に通過させたりすることもある。

パケットフィルタが適切に機能しているかどうかを調べるには、hping2でさまざまなパケットを生成し、フィルタの向こう側にあるターゲットホストに対して送信してみればよい。

● ソースポートを指定したパケットの送出

以下は、ソースポートを80番に設定し、デスティネーションポート139に対してTCPのSYNパケットを一つだけ送出する例である。

    # hping2 192.168.183.130 -c 1 -S -s 80 -p 139
    HPING 192.168.183.130 (eth0 192.168.183.130): S set, 40 headers + 0 data bytes
    len=46 ip=192.168.183.130 ttl=128 DF id=31946 sport=139 flags=SA seq=0 win=16616 rtt=0.0 ms
    
    --- 192.168.183.130 hping statistic ---
    1 packets tramitted, 1 packets received, 0% packet loss
    round-trip min/avg/max = 0.0/0.0/0.0 ms
    
-sはソースポート番号、-pはデスティネーションポート番号を指定するオプションである。-S(大文字のS)は、TCPフラグにSynを設定している。また-cでは送出するパケットの数を指定している。

ステートレスなパケットフィルタリングのルールを設定する際に、注意しなければならないのがアウトバウンド(外向き)アクセスの「戻り」のパケットを通すためのルール設定だ。例えばTCP/80(Web)に対するアウトバウンドアクセスを許可したい場合、戻りのパケットを通過させるためにソースポートがTCP/80である内向きのパケットを無条件に通すようなルールを設定しがちである。

上記のようにソースポートをTCP/80に設定したパケットを、パケットフィルタで保護されているポートに対して送出し、もしリプライパケットが返ってきた場合、パケットフィルタのフィルタリングルールを見直す必要がある。TCP/80以外にも、TCP/25(SMTP)や、TCP/53(DNS)、TCP/20(FTP DATA)なども試してみるとよい。

ちなみにWindows 2000以降に導入されたIPSecフィルタリングは、ルールの設定に関わらず、デフォルトではソースポートが88番(kerberos)のTCPおよびUDPパケットを無条件に通過させる仕様になっている[1]。このような「穴」も、hping2でソースポート88番に設定したパケットを送出して反応を見ることにより検出することができる。

● 各種のTCPフラグを指定したパケットの送出

今度はhping2で、さまざまなTCPフラグを立てたパケットを送出してみよう。TCPフラグを指定するオプションには、以下のものがある。

    -F ... FinフラグをON
    -S ... SynフラグをON
    -R ... ResetフラグをON
    -P ... PushフラグをON
    -A ... AckフラグをON
    -U ... UrgentフラグをON
    -X ... ECN-Echoフラグ(0x40)をON
    -Y ... CWRフラグ(0x80)をON
    
これらを組み合わせる場合は、例えば-RA(Reset/Ack)のように記号を並べて指定すればよい。-FSRPAUXYとすると、すべてのTCPフラグを立てたパケットが生成される。

    ○ 制御パケットしか評価しないパケットフィルタリング

    通常TCPのコネクションは、クライアントからサーバに対してSynフラグの立ったパケット(Synパケット)を送り、サーバがそれに対してSynおよびAckフラグの立ったパケット(Syn/Ackパケット)を返し、さらにクライアントからAckフラグの立ったAckパケットを返信することにより確立する(TCPの3-Wayハンドシェイク)。つまりTCPコネクションの「きっかけ」は、クライアントから送られるSynパケットだと言えよう。

    そのためある種のパケットフィルタリング(特に高速処理が要求されるスイッチ機器)では、処理の高速化を優先させるため、デフォルト状態でSynパケット等の制御パケットのみを評価する仕様になっている。ところがここに落とし穴が存在する。

    以下はクライアントからサーバ(Windows 2000)に対し、SynフラグおよびFinフラグを立てたTCPパケットをポート139に向けて送出した例である。リプライパケットのTCPフラグ情報(flags=SA)より、サーバからSyn/Ackパケットが返ってきていることがわかる。

      # hping2 192.168.183.130 -c 1 -SF -p 139
      HPING 192.168.183.130 (eth0 192.168.183.130): SF set, 40 headers + 0 data bytes
      len=46 ip=192.168.183.130 ttl=128 DF id=36667 sport=139 flags=SA seq=0 win=16616 rtt=0.0 ms
      
      --- 192.168.183.130 hping statistic ---
      1 packets tramitted, 1 packets received, 0% packet loss
      round-trip min/avg/max = 0.0/0.0/0.0 ms
      
    このように、ターゲットホストのOSによっては、Syn/Finフラグが立ったTCPパケットでTCPコネクションを開設することが可能である。つまり、Synパケットしか評価しないようなパケットフィルタリング装置があった場合、コネクション開設要求として送出されたSyn/Finパケット(これは明らかにアブノーマルである)がフィルタを通過してしまい、TCPセッションが確立してしまう可能性があるのだ。

    Syn/Finパケットを受けてTCPコネクションを開設するようなOSは、上記のWindows 2000以外にも、Linux、FreeBSD等、数多く存在する[2]。

    ○ フィルタリングルール「established」の盲点

    先にステートレス・パケットフィルタリングのルールにおける「戻り」パケットの設定について述べたが、多くのステートレス・パケットフィルタのルール設定にはこのような「戻り」のパケットを安全に通すための「established」という記述が存在する。

    例えばCisco IOSでは、「すべてのIPアドレスから192.168.183.136へのTCPの戻りパケットを許可する」ためのルールを次のように記述する。

      access-list 101 permit tcp any host 192.168.183.136 established
      
    ここで重要なのは、何をもって「戻り」のパケットだと判断しているかだ。これはパケットフィルタリングの実装に依存するが、基本的にAckフラグが立っているか、もしくはResetフラグが立っているかで判断している場合が多い。すなわちestablishedルールは、Resetフラグが立ったTCPパケットを無条件に通してしまう可能性を含んでいる。

    ところで多くのLinux OSは、オープンポートにSyn/Resetパケットを受けた際、前述したSyn/Finの場合と同様にSyn/Ackを返す。つまりSyn/Resetを受けてTCPコネクションが開設されることになる。以下はhping2を用いて、Redhat7.1のTCP/23に対してSyn/Resetを送出した例である。

      # hping2 192.168.183.136 -c 1 -SR -p 23
      HPING 192.168.183.136 (lnc1 192.168.183.136): RS set, 40 headers + 0 data bytes
      len=46 ip=192.168.183.136 ttl=63 DF id=0 sport=23 flags=SA seq=0 win=5840 rtt=53.3 ms
      
      --- 192.168.183.136 hping statistic ---
      1 packets tramitted, 1 packets received, 0% packet loss
      round-trip min/avg/max = 53.3/53.3/53.3 ms
      
    つまりパケットフィルタのestablishedルールが、Resetフラグの立ったTCPパケットを「戻り」だと認識して通過させる仕様であった場合、Syn/Resetパケットを通してしまい、それによって外部からフィルタリングを超えてTCPコネクションを開設することができるわけだ。このように振舞うパケットフィルタリング装置には、Windows 2000やXPが標準でサポートするRRAS(Routing and Remote Access Service)のパケットフィルタも含まれる。

● フラグメント化したIPパケットの送出

パケットフィルタにおけるもう一つの懸念事項は、IPフラグメントの処理である。ネットワークの最大転送単位(MTU: Maximum Transfer Unit)を超えるような大きなパケットがルータに到達した際、ルータはそのパケットをMTUに収まるサイズに分割し(フラグメント化)送出する。最終的なあて先ホストでは、それらの分割されたパケットを一定の規則で再構成することにより、元のパケットに戻す。これが通常のネットワークで発生するIPフラグメントである。ところが意図的に非常に小さなフラグメントに分割してパケットを送り出すことにより、パケットフィルタを回避することができる場合もある。

図1を見ていただきたい。この図はIPフラグメントの最小単位となる8バイトで、TCPのSynパケットをフラグメント化したところを表している。図の「パケット0」が元のパケットで、「パケット1」、「パケット2」、および「パケット3」がフラグメント化されたパケットである。この図からわかるとおり、8バイトでフラグメント化したTCPパケットは、TCPヘッダが細分化されてしまうため、TCPフラグ(Synが立っている)は先頭の「パケット1」には現れず、次に続く「パケット2」に含まれる。


図1 タイニー・フラグメントの例。TCPヘッダが細分化されたため、TCPフラグが先頭フラグメント(パケット1)に入らない。


このように極めて細かくフラグメント化されたパケット(タイニー・フラグメント)は、先頭パケットにTCPヘッダのフラグの情報を含まないため、パケットフィルタの仕様によってはルールで適切に評価できずに通過させてしまう場合がある[3]。

以下は、hping2により8バイトごとにフラグメント化したSynパケットを、サーバ192.168.183.136のTCP/23に対して送出した例である。

    # hping2 192.168.183.136 -c 1 -S -p 23 -f -m 8
    HPING 192.168.183.136 (lnc1 192.168.183.136): S set, 40 headers + 0 data bytes
    len=46 ip=192.168.183.136 ttl=63 DF id=0 sport=23 flags=SA seq=0 win=5840 rtt=9.9 ms
    
    --- 192.168.183.136 hping statistic ---
    1 packets tramitted, 1 packets received, 0% packet loss
    round-trip min/avg/max = 9.9/9.9/9.9 ms
    
-fオプションはフラグメントすることを表し、-mオプションは分割する単位をバイトで指定する。前述したWindowsのRRASパケットフィルタは、デフォルトではこのようなタイニー・フラグメントを通過させてしまうことが知られている。




TCPポートスキャナとしての使い方


さて今まではデスティネーションポートを固定して、単一のパケットを送出する例を示してきたが、デスティネーションポートを一つずつ増加させて連続的にパケットを送出することにより、ポートスキャンを実行することができる。

例えばTCP/21〜30までの範囲のポートスキャンを行うには、次のようにすればよい。

    # hping2 192.168.183.136 -c 10 -S -p +21
    HPING 192.168.183.136 (lnc1 192.168.183.136): S set, 40 headers + 0 data bytes
    len=46 ip=192.168.183.136 ttl=254 DF id=0 sport=21 flags=RA seq=0 win=0 rtt=5.1 ms
    len=46 ip=192.168.183.136 ttl=63 DF id=0 sport=22 flags=SA seq=1 win=5840 rtt=3.3 ms
    len=46 ip=192.168.183.136 ttl=63 DF id=0 sport=23 flags=SA seq=2 win=5840 rtt=1.7 ms
    len=46 ip=192.168.183.136 ttl=254 DF id=0 sport=24 flags=RA seq=3 win=0 rtt=2.0 ms
    len=46 ip=192.168.183.136 ttl=63 DF id=0 sport=25 flags=SA seq=4 win=5840 rtt=2.1 ms
    len=46 ip=192.168.183.136 ttl=254 DF id=0 sport=26 flags=RA seq=5 win=0 rtt=1.5 ms
    len=46 ip=192.168.183.136 ttl=254 DF id=0 sport=27 flags=RA seq=6 win=0 rtt=1.8 ms
    len=46 ip=192.168.183.136 ttl=254 DF id=0 sport=28 flags=RA seq=7 win=0 rtt=1.8 ms
    len=46 ip=192.168.183.136 ttl=254 DF id=0 sport=29 flags=RA seq=8 win=0 rtt=1.4 ms
    len=46 ip=192.168.183.136 ttl=254 DF id=0 sport=30 flags=RA seq=9 win=0 rtt=1.4 ms
    
    --- 192.168.183.136 hping statistic ---
    10 packets tramitted, 10 packets received, 0% packet loss
    round-trip min/avg/max = 1.4/2.2/5.1 ms
    
コマンドラインのオプション-cで送出パケットの数を10とし、デスティネーションポート指定(-pオプション)では+21のように「+」記号を付けている。これによりポート21番から順番に10回、TCPパケットを送り出すことになる。

リプライパケットの表示が「flags=SA」、つまりSyn/Ackが返ってきているポートがオープンポートである。この例ではポート22、23、および25がそれに相当する。

デフォルトではパケットの送出間隔が1秒と長いため、送出間隔を短くしてみよう。そのためには-iオプションの後に例えば「u5」と指定する。これは送出間隔を5マイクロ秒に設定することを意味している。ちなみに、-iの後に単に数字を指定すれば、送出間隔を秒単位で指定することになる。(「-i u5」 → 5マイクロ秒、「-i 5」 → 5秒)

さらに今度はTCP/1〜1023と、範囲を広げてスキャンしてみる。なお、分かりやすくするために、fgrepコマンドを用いてhping2の出力結果のうち「flags=SA」を含む行のみを表示することにしよう。

    # hping2 192.168.183.136 -c 1023 -S -p +1 -i u5 | fgrep "flags=SA"
    len=46 ip=192.168.183.136 ttl=63 DF id=0 sport=22 flags=SA seq=21 win=5840 rtt=2.1 ms
    len=46 ip=192.168.183.136 ttl=63 DF id=0 sport=23 flags=SA seq=22 win=5840 rtt=1.8 ms
    len=46 ip=192.168.183.136 ttl=63 DF id=0 sport=25 flags=SA seq=24 win=5840 rtt=1.4 ms
    len=46 ip=192.168.183.136 ttl=63 DF id=0 sport=53 flags=SA seq=52 win=5840 rtt=2.2 ms
    len=46 ip=192.168.183.136 ttl=63 DF id=0 sport=79 flags=SA seq=78 win=5840 rtt=1.4 ms
    len=46 ip=192.168.183.136 ttl=63 DF id=0 sport=80 flags=SA seq=79 win=5840 rtt=1.5 ms
    len=46 ip=192.168.183.136 ttl=63 DF id=0 sport=111 flags=SA seq=110 win=5840 rtt=1.9 ms
    len=46 ip=192.168.183.136 ttl=63 DF id=0 sport=199 flags=SA seq=198 win=5840 rtt=1.3 ms
    len=46 ip=192.168.183.136 ttl=63 DF id=0 sport=443 flags=SA seq=442 win=5840 rtt=2.1 ms
    
    --- 192.168.183.136 hping statistic ---
    1023 packets tramitted, 1023 packets received, 0% packet loss
    round-trip min/avg/max = 1.1/1.7/12.9 ms
    
なお、hping2はもともとポートスキャナとして作られているわけではないので、ポートスキャンについて言えば当然ながら機能および性能的にはnmapのようなポートスキャナにかなわない。このような使い方もできるという程度に考えた方がよいだろう。




TCPシーケンス番号収集モード


hping2の面白い機能として、TCPシーケンス番号収集モードというのがある(-Qオプション)。この機能を用いると、ターゲットマシンの初期シーケンス番号およびその差分値を取得することが可能だ。

以下に、Redhat7.1が稼動するサーバに対してシーケンス番号収集モードで実行した例を示す。(パケット送出はデフォルトの1秒間隔)

    # hping2 192.168.183.136 -c 10 -S -p 80 -Q
    HPING 192.168.183.136 (lnc1 192.168.183.136): S set, 40 headers + 0 data bytes
    2407140356 +2407140356
    2402811086 +4290638025
    2416470793 +13659707
    2418206030 +1735237
    2410673534 +4287434799
    2414132542 +3459008
    2421939362 +7806820
    2418994577 +4292022510
    2409338294 +4285311012
    2412470338 +3132044
    
    --- 192.168.183.136 hping statistic ---
    10 packets tramitted, 10 packets received, 0% packet loss
    round-trip min/avg/max = 1.6/2.1/3.4 ms
    
左側に表示されているのが各リプライパケットの初期シーケンス番号で、右側は直前のシーケンス番号との差分値である。この結果から、Redhat7.1の初期シーケンス番号は非常にランダムであることがうかがえる。

一方、Windows 2000に対して実行すると、次のような結果になる。

    # hping2 192.168.183.130 -c 10 -S -p 80 -Q
    HPING 192.168.183.130 (lnc1 192.168.183.130): S set, 40 headers + 0 data bytes
      40811574 +40811574
      40855514 +43940
      40903396 +47882
      40936477 +33081
      40979333 +42856
      41043144 +63811
      41083446 +40302
      41126158 +42712
      41168815 +42657
      41218864 +50049
    
    --- 192.168.183.130 hping statistic ---
    10 packets tramitted, 10 packets received, 0% packet loss
    round-trip min/avg/max = 1.7/2.8/5.9 ms
    
これを見ると、Windows 2000は初期シーケンス番号の推測が、Redhatと比較して容易であることがわかる。

ちなみに以下はWindows NT 4.0 SP3に対する実行結果だ。この場合は次の初期シーケンス番号を予測することが極めて容易である。(なおNT4.0におけるこの問題については、マイクロソフトは修正モジュールを提供している)

    # hping2 192.168.183.133 -c 10 -S -p 80 -Q
    HPING 192.168.183.133 (lnc1 192.168.183.133): S set, 40 headers + 0 data bytes
      47799972 +47799972
      47800984 +1012
      47801995 +1011
      47803017 +1022
      47804028 +1011
      47805120 +1092
      47806141 +1021
      47807163 +1022
      47808174 +1011
      47809226 +1052
    
    --- 192.168.183.133 hping statistic ---
    10 packets tramitted, 10 packets received, 0% packet loss
    round-trip min/avg/max = 1.5/2.8/5.0 ms
    
初期シーケンス番号の推測が容易である場合、そのサーバはシーケンス番号推測によるIPソースアドレス詐称攻撃(IP Spoofing)にさらされる危険性がある[4][5]。hping2によるTCPシーケンス番号調査は、そのような脆弱性を持つサーバの存在を調べる際に非常に有効となる。




IP-IDの増分表示


もう一つ、hping2の面白い機能を紹介しよう。それはIP-IDの増分を表示する機能である。前述のとおり、hping2はデフォルトではリプライパケットのIP-IDの値を「id=12318」のように表示するが、-rオプションを指定することにより「id=+1」といった具合に直前のIP-IDとの差分を表示するようになる。

次の例では192.168.183.130(Windows 2000)に対して、-rオプションを付けてSynパケットを送出している。

    # hping2 192.168.183.130 -S -p 80 -r
    HPING 192.168.183.130 (lnc1 192.168.183.130): S set, 40 headers + 0 data bytes
    len=46 ip=192.168.183.130 ttl=127 DF id=6407 sport=80 flags=SA seq=0 win=16616 rtt=9.8 ms
    len=46 ip=192.168.183.130 ttl=127 DF id=+1 sport=80 flags=SA seq=1 win=16616 rtt=2.5 ms
    len=46 ip=192.168.183.130 ttl=127 DF id=+1 sport=80 flags=SA seq=2 win=16616 rtt=2.4 ms
    len=46 ip=192.168.183.130 ttl=127 DF id=+1 sport=80 flags=SA seq=3 win=16616 rtt=2.5 ms
    len=46 ip=192.168.183.130 ttl=127 DF id=+1 sport=80 flags=SA seq=4 win=16616 rtt=2.3 ms
    len=46 ip=192.168.183.130 ttl=127 DF id=+1 sport=80 flags=SA seq=5 win=16616 rtt=2.1 ms
    ^C
    --- 192.168.183.130 hping statistic ---
    6 packets tramitted, 6 packets received, 0% packet loss
    round-trip min/avg/max = 2.1/3.6/9.8 ms
    
このように-rオプションを付けると、最初のリプライパケットの行でIP-IDの値を表示し、2行目以降には差分(この場合すべて+1)が表示される。

IP-IDは通常、そのホストから送出されるIPパケットに対し、送出順に連番が付けられる。この例ではリプライパケットのIP-IDの差分が常に1であることから、ホスト192.168.183.130は上記6つのSynパケットに対するSyn/Ackリプライを返す間、他のIPパケットはまったく送出していないことがわかる。

このようなサイレントホスト(ネットワーク通信を頻繁に行っていないホスト)が存在する場合、hping2のIP-ID増分表示機能を用いて、サイレントホストに対するUDPポートスキャンを行ったり、サイレントホストとの間のフィルタリング状況を調べたりすることができる。

UDPポートスキャンは、たとえターゲットホストにUDPパケットが到達していたとしても、閉じているポートからのICMP port unreachableがファイアウォールによりドロップされてしまう場合、ポート開閉の判断をすることができない。ところがターゲットがサイレントホストだと、ターゲットのIP-IDを調べることによりポート開閉を推測することが可能になる。

今、ターゲット192.168.183.130に対してTCP/80によるアクセスが可能だとしよう。先のようにhping2をターゲットホストのTCP/80に向けて-rオプション付で実行する。すると連続的にターゲットよりSyn/Ackパケットが返ってくる。この時の各リプライパケットのIP-IDは、サイレントホストでは基本的に「+1」である。その一方で、同一ターゲットのUDPポートへ一つずつパケットを送出してみる。ターゲットのUDPポートがクローズであればICMP port unreachableパケットが発信されるが、そのICMPパケットはファイアウォールでブロックされているためhping2を動作させているマシンには到達しない。しかし、ICMPパケットを発信したためにターゲットが生成するパケットのIP-IDは一つインクリメントされる。つまり、連続しているSyn/AckリプライのIP-IDがその時だけ「+2」になるわけだ。(下の例の7つ目のリプライパケット)

    # hping2 192.168.183.130 -S -p 80 -r
    HPING 192.168.183.130 (lnc1 192.168.183.130): S set, 40 headers + 0 data bytes
    len=46 ip=192.168.183.130 ttl=127 DF id=12503 sport=80 flags=SA seq=0 win=16616 rtt=4.3 ms
    len=46 ip=192.168.183.130 ttl=127 DF id=+1 sport=80 flags=SA seq=1 win=16616 rtt=3.4 ms
    len=46 ip=192.168.183.130 ttl=127 DF id=+1 sport=80 flags=SA seq=2 win=16616 rtt=1.7 ms
    len=46 ip=192.168.183.130 ttl=127 DF id=+1 sport=80 flags=SA seq=3 win=16616 rtt=1.8 ms
    len=46 ip=192.168.183.130 ttl=127 DF id=+1 sport=80 flags=SA seq=4 win=16616 rtt=1.7 ms
    len=46 ip=192.168.183.130 ttl=127 DF id=+1 sport=80 flags=SA seq=5 win=16616 rtt=1.7 ms
    len=46 ip=192.168.183.130 ttl=127 DF id=+2 sport=80 flags=SA seq=6 win=16616 rtt=3.1 ms
    len=46 ip=192.168.183.130 ttl=127 DF id=+1 sport=80 flags=SA seq=7 win=16616 rtt=2.6 ms
    len=46 ip=192.168.183.130 ttl=127 DF id=+1 sport=80 flags=SA seq=8 win=16616 rtt=2.5 ms
    ^C
    --- 192.168.183.130 hping statistic ---
    9 packets tramitted, 9 packets received, 0% packet loss
    round-trip min/avg/max = 1.7/2.5/4.3 ms
    
オープンしているUDPポートにパケットを送出しても、ターゲットホストはICMP port unreachableを発信しないため、Syn/AckリプライのIP-IDは「+2」にはならない。すなわち、あるUDPポートにパケットを投げて、そのタイミングでSyn/AckパケットのIP-IDが「+2」になるかならないかでUDPポートの開閉を判断するのである。同様の原理を利用して、パケットフィルタが特定のIPアドレスからのパケットを通すかどうかを調べたりすることもできる。hping2に付属するドキュメントにこのあたりの手法について書かれているので、興味のある方は参照していただきたい。

hping2にはこの他にも、トレースルートモード、レコードルート機能、TTL(Time to Live)のインタラクティブな変更機能、リッスンモードによるファイル転送、などなど多くの機能がある。またhping2の次期バージョンであるhping3が現在開発中で、今年の12月にリリースされる予定となっている。hping3ではスクリプト化の機能等、ますます強化されたバージョンになるようなので、公開が楽しみである。



[1]  [NT]IPSec により保護されるトラフィックと保護されないトラフィック
     http://support.microsoft.com/default.aspx?scid=kb;JPN;253169

[2]  Ambiguities in TCP/IP - firewall bypassing
     http://marc.theaimsgroup.com/?l=bugtraq&m=103496796619647&w=2

[3]  Security Considerations for IP Fragment Filtering
     http://www.ietf.org/rfc/rfc1858.txt

[4]  IP-spoofing Demystified
     http://www.phrack.org/show.php?p=48&a=14

[5]  NTにおけるIPソースアドレス詐称
     http://www.trusnet.com/secinfo/docs/shio4_ipspoof/


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