HAYAGUI

FreeBSD 4.7 + netcatの使い方

はじめに

「FreeBSD 4.5 + netcat で 9100 port を使った印刷」でもつかった netcat をもっと詳しく使ってみます。 試したオプションは、これら。
e
クライアントがサーバに接続した時、サーバが実行するプログラムを指定することができる。
o
通信状態を hexダンプする。
u
UDP通信モード。
w
接続タイムアウト指定。
z
IOを行わないモード。ポートスキャンに使用。
v
冗長モード。通信状態などのステータスを表示します。
-e オプションでは、atmarkitでは、セキュリティ上のバックドアの一例としてnetcat を使う例があるので、参照にしました。

ソースをゲット

netcat は、こちら(http://www.atstake.com/research/tools/network_utilities/)からゲットします。

ファイルを nc というディレクトリに保存します。

> pwd
/usr/home/kenz/nc
> ls -la
total 78
drwxr-xr-x  2 kenz  kenz    512 Aug 17 06:07 .
drwxr-xr-x  3 kenz  kenz    512 Aug 17 06:07 ..
-rw-r--r--  1 kenz  kenz  75267 Aug 17 06:07 nc110.tgz
解凍して、make 。 freebsd の場合は、こんな感じ。その他のプラットフォームは、Makefile を見るとわかります。
> tar zxvf nc110.tgz
> make freebsd
make -e nc   XFLAGS='-DFREEBSD' STATIC=-static
cc -O -s  -DFREEBSD -static -o nc netcat.c
コンパイル成功。
> ls -la
total 408
drwxr-xr-x  4 kenz  kenz     512 Aug 17 06:08 .
drwxr-xr-x  3 kenz  kenz     512 Aug 17 06:07 ..
-rw-r--r--  1 kenz  kenz    3840 Mar 21  1996 Changelog
-rw-r--r--  1 kenz  kenz    3805 Mar 20  1996 Makefile
-rw-r--r--  1 kenz  kenz   60834 Mar 21  1996 README
drwxr-xr-x  2 kenz  kenz     512 Aug 17 06:08 data
-rw-r--r--  1 kenz  kenz   11629 Feb 18  1996 generic.h
-rwxr-xr-x  1 kenz  kenz  176652 Aug 17 06:08 nc
-rw-r--r--  1 kenz  kenz   75267 Aug 17 06:07 nc110.tgz
-rw-r--r--  1 kenz  kenz    2645 Mar 20  1996 netcat.blurb
-rw-r--r--  1 kenz  kenz   58553 Mar 21  1996 netcat.c
drwxr-xr-x  2 kenz  kenz     512 Aug 17 06:08 scripts
-rwxr-xr-x  1 kenz  kenz    8549 Nov  8  1995 stupidh

いじる

セキュリティホールになるとして、使用不可になっている -e オプションというのがあります。 このオプションは、接続後に他のプログラムに繋げるちゃうものです。使う時は、理解して十分注意してください。 正しく使えば便利なんですけどね。 先ほど作成した nc が使えるオプションを見ると、こんな感じ。
> ./nc -h
[v1.10]
connect to somewhere:   nc [-options] hostname port[s] [ports] ...
listen for inbound:     nc -l -p port [-options] [hostname] [port]
options:
        -g gateway              source-routing hop point[s], up to 8
        -G num                  source-routing pointer: 4, 8, 12, ...
        -h                      this cruft
        -i secs                 delay interval for lines sent, ports scanned
        -l                      listen mode, for inbound connects
        -n                      numeric-only IP addresses, no DNS
        -o file                 hex dump of traffic
        -p port                 local port number
        -r                      randomize local and remote ports
        -s addr                 local source address
        -u                      UDP mode
        -v                      verbose [use twice to be more verbose]
        -w secs                 timeout for connects and final net reads
        -z                      zero-I/O mode [used for scanning]
port numbers can be individual or ranges: lo-hi [inclusive]

-e は無い。で、netcat.c ファイルを開きます。すると、getopt() の所に、-e が条件コンパイル(GAPING_SECURITY_HOLE)されているのがわかります。
> vi netcat.c

  while ((x = getopt (argc, argv, "ae:g:G:hi:lno:p:rs:tuvw:z")) != EOF) {
/* Debug (("in go: x now %c, optarg %x optind %d", x, optarg, optind)) */
    switch (x) {
      case 'a':
        bail ("all-A-records NIY");
        o_alla++; break;
#ifdef GAPING_SECURITY_HOLE
      case 'e':                         /* prog to exec */
        pr00gie = optarg;
        break;
#endif

これが有効になると、-e が使えるので、generic.h ファイルを開いて有効にします。
#ifndef GENERIC_H               /* only run through this once */
#define GENERIC_H

/* =============================== */
/* System calls, lib routines, etc */
/* =============================== */

#define GAPING_SECURITY_HOLE

clean した後、再度コンパイル。
> make clean
rm -f nc *.o *.obj

> make freebsd
make -e nc   XFLAGS='-DFREEBSD' STATIC=-static
cc -O -s  -DFREEBSD -static -o nc netcat.c

今度は、-e が追加されました。
> ./nc -h
[v1.10]
connect to somewhere:   nc [-options] hostname port[s] [ports] ...
listen for inbound:     nc -l -p port [-options] [hostname] [port]
options:
        -e prog                 program to exec after connect [dangerous!!]
        -g gateway              source-routing hop point[s], up to 8
        -G num                  source-routing pointer: 4, 8, 12, ...
        -h                      this cruft
        -i secs                 delay interval for lines sent, ports scanned
        -l                      listen mode, for inbound connects
        -n                      numeric-only IP addresses, no DNS
        -o file                 hex dump of traffic
        -p port                 local port number
        -r                      randomize local and remote ports
        -s addr                 local source address
        -u                      UDP mode
        -v                      verbose [use twice to be more verbose]
        -w secs                 timeout for connects and final net reads
        -z                      zero-I/O mode [used for scanning]
port numbers can be individual or ranges: lo-hi [inclusive]

eオプションを使ってみる

接続を受ける側(ターゲット)では、以下のように実行します。各オプションはこのような意味。
-l 受信モード
-p 待ちポート
-e 実行するプログラム
> ./nc -l -p 12345 -e /bin/sh
接続する側では、以下の様に実行します。ターゲットのIPアドレスとポート番号を引数とします。
> nc 192.168.0.7 12345
で、この後 hostname とか入力すると、ターゲットの /bin/sh 経由で hostname コマンドが実行されてしまいます。 かなり、危ない。
hostname
mico.hayagui.com
接続を切る時は、Ctrl + c するとセッションが切れます。
^C punt!

通信状態をダンプしてみる

通信している内容をクライアント側で -o オプションを使う事で、hex dump することができます。
> nc -o dump 192.168.0.7 12345
hostname
mico.hayagui.com
^C punt!
先と同じ内容の通信状態はこんな感じ。
> ls -la dump
-rw-r--r--  1 kenz  kenz  212   8/17 20:47 dump
> cat dump
> 00000000 68 6f 73 74 6e 61 6d 65 0a                      # hostname.
< 00000000 6d 69 63 6f 2e 68 61 79 61 67 75 69 2e 63 6f 6d # mico.hayagui.com
< 00000010 0a                                              # .

UDPで通信

netcat は、-u オプションをつけることで、UDP通信となります。付けない時は TCP です。 TCPは接続相手がいないとプログラムは失敗して終了しますが、UDPはコネクションレス型なので、 相手がいなくてもパケットを投げてプログラムが終了します。

まず、送信するファイルを作成します。

> echo "hogehoge" > hoge.txt
> cat hoge.txt
hogehoge
-u オプションを付けない TCP の場合から。
> cat hoge.txt | ./nc  -o dump 192.168.0.8 12345
プログラムは終了しますが、通信状態を見てみると作成されていません。失敗終了していることがわかります。
> cat dump
>
次に、-u オプションをつけて UDP 通信。
> cat hoge.txt | ./nc -u -o dump 192.168.0.8 12345
> cat dump
> 00000000 68 6f 67 65 68 6f 67 65 0a                      # hogehoge.
>
パケットを受けるサーバが無くてもUDPパケットを送信して終了しています。

TCPとUDPの違いがわかった所で、サーバ側を作成します。

> nc -l -u -p 12345 > data.txt
これを実行してから、クライアントで先ほどのように実行します。
> cat hoge.txt | ./nc -u -o dump 192.168.0.8 12345
サーバ側で、Ctrl + c して接続を切ります。受信したデータを見ると、こんな感じに送信された事がわかります。
> cat data.txt
hogehoge
送信した状態でも、クライアント側のプログラムは動いたままです。これを終了させる方法が、次項のタイムアウトです。

タイムアウト

接続のタイムアウトを設定するのが、-w オプションです。

先の「UDP接続」でクライアントがサーバに送信したにもかかわらず切れなかったのは、 -w オプションをつけることで終了することができます。

> cat hoge.txt | ./nc -u -w 3 -o dump 192.168.0.8 12345
>
3秒のタイムアウトで接続が切れます。

ちなみに、サーバ側で -w オプションをつけると、指定時間経過しても接続が無いと終了します。

> nc -l -u -w 3 -p 12345 > data.txt
no connection : Operation timed out
>

ポートスキャン

-z オプションをつけることでポートスキャンができます。 ポートスキャンといえば、nmap ですが、同じような機能が netcat でも実現できます。

ftp として空いている tcp/21 をターゲットとします。

> ./nc -z -w 3 -v  localhost 21
localhost.hayagui.com [127.0.0.1] 21 (ftp) open
「open してるぞ」と。
次に、空けていない tcp/12345 をターゲットとします。
> ./nc -z -w 3 -v localhost 12345
localhost.hayagui.com [127.0.0.1] 12345 (?) : Connection refused
「connectが失敗しているぞ」と。

ポートを範囲指定する場合は、こんな感じにします。

> ./nc -z -w 3 -v localhost 1-50
localhost.hayagui.com [127.0.0.1] 25 (smtp) open
localhost.hayagui.com [127.0.0.1] 23 (telnet) open
localhost.hayagui.com [127.0.0.1] 22 (ssh) open
localhost.hayagui.com [127.0.0.1] 21 (ftp) open
-v オプションを2つにすると、スキャンしたポートすべての状態を表示します。

戻る



(C)1999 - 2003 Kenji Ito All rights reserved.