xinetdでリバースポートスキャナを作る

xinetdを使うと、標準入出力を使うスクリプトなどを簡単にネットワークサーバにすることができる。 ここでは、xinetdを使ってさまざまなネットワークサーバを作ってみる。

環境

Ubuntu 12.04 LTS 32bit版

$ uname -a
Linux vm-ubuntu32 3.11.0-15-generic #25~precise1-Ubuntu SMP Thu Jan 30 17:42:40 UTC 2014 i686 i686 i386 GNU/Linux

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 12.04.4 LTS
Release:        12.04
Codename:       precise

$ gcc --version
gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3

インストール

Ubuntuの場合デフォルトでは入っていないので、aptリポジトリからインストールする必要がある。

$ sudo apt-get install xinetd

uptime

次のようなファイルをxinitd.confとして保存する。

service unlisted
{
       type                = UNLISTED
       socket_type         = stream
       protocol            = tcp
       wait                = no
       only_from           = localhost 192.168.0.0/16
       port                = 20020
       user                = nobody
       server              = /usr/bin/uptime
}

ここでは、only_fromエントリを使いサーバへの接続をlocalhostとプライベートネットワークからに制限している。

引数として上のファイルを指定し、デバッグモードにてサービスを起動してみる。

$ sudo xinetd -f xinetd.conf -d

別のターミナルからncコマンドやtelnetコマンドで記述したポートに接続すると、コマンドの実行結果が表示される。

$ nc localhost 20020
 11:26:50 up 10 min,  2 users,  load average: 0.25, 0.11, 0.06

ここではuptimeコマンドにより、起動時間とロードアベレージが表示される。

python shell

ソケットからの入力も扱う例として、server、server_argsエントリを次のように書き換えてみる。

       server              = /usr/bin/python
       server_args         = -i

この場合、接続するとPythonインタラクティブモードが操作できるようになる。

$ nc localhost 20020
Python 2.7.3 (default, Feb 27 2014, 20:00:17)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.system('/bin/sh')
id
uid=65534(nobody) gid=65534(nogroup) groups=65534(nogroup)
0
>>>

もちろん、このようなサービスをそのまま外部に公開することは危険である。 たとえば、上のようにすればシェルが操作できるようになる。

what's my ip

接続元のIPアドレスはREMOTE_HOST環境変数にセットされる。 これを利用して、server、server_argsエントリを次のように書き換えてみる。

       server              = /usr/bin/printenv
       server_args         = REMOTE_HOST

サーバを起動して別のターミナルから接続すると、接続元のIPアドレスが表示される。

$ nc localhost 20020
127.0.0.1

reverse traceroute

userエントリをrootにし、server、server_argsエントリを次のように書き換えてみる。

       user                = root
       server              = /bin/sh
       server_args         = /tmp/traceroute.sh

上で指定したシェルスクリプトには、次のような内容を書いておく。

# traceroute.sh
traceroute -I -w1 "$REMOTE_HOST"

サーバを起動して別のターミナルから接続すると、サーバから接続元へのtraceroute結果が表示される。

$ nc localhost 20020
traceroute to 127.0.0.1 (127.0.0.1), 30 hops max, 60 byte packets
 1  localhost (127.0.0.1)  0.044 ms  0.008 ms  0.008 ms

reverse port scanner

さらに次のように書き換えてみる。

       port                = 65535
       user                = root
       server              = /bin/sh
       server_args         = /tmp/nmap.sh

上で指定したシェルスクリプトには、次のような内容を書いておく。

# nmap.sh
nmap -v -sSVC -O -p-65534 "$REMOTE_HOST"

ここで、サーバを起動するポートは65535とし、スキャン対象のポート番号からは外しておく。

サーバを起動して別のターミナルから接続すると、サーバから接続元へポートスキャンをかけた結果が表示される。

$ nc localhost 65535

Starting Nmap 5.21 ( http://nmap.org ) at 2014-07-09 15:23 JST
NSE: Loaded 36 scripts for scanning.
Initiating SYN Stealth Scan at 15:23
Scanning localhost (127.0.0.1) [65534 ports]
(snip)
Nmap done: 1 IP address (1 host up) scanned in 41.25 seconds
           Raw packets sent: 65644 (2.892MB) | Rcvd: 131300 (5.521MB)

関連リンク