Netcat (nc) によるshサーバの仕組み

ncのマニュアルにあるshサーバの実行例が気になったので図にまとめてみた。

マニュアルはBSD General Commands Manualである。
(LinuxでもncのマニュアルはBSDなんだな)

On ‘server’ side:
      $ rm -f /tmp/f; mkfifo /tmp/f
      $ cat /tmp/f | /bin/sh -i 2>&1 | nc -l 127.0.0.1 1234 > /tmp/f

On ‘client’ side:
      $ nc host.example.com 1234
      $ (shell prompt from host.example.com)

このサーバサイドコマンドであるcat /tmp/f | /bin/sh -i 2>&1 | nc -l 127.0.0.1 1234 > /tmp/fをまとめる。

mkfifo

まずは最初の行で実行されているコマンドmkfifoについて。

これは名前付きパイプを生成するコマンドである。
パイプといえばシェルの縦棒(|)に相当するもので、見た目としてはファイルのように現れる。
あるプロセスがそのファイルに書き込みをし、同時に別のプロセスがそのファイルから読み込みを行うと、コマンド同士が「|」で繋がっていなくても、入出力が接続される。

nc -lの入出力

続いてnc -lの入出力について。

nc -lはポートを開けて通信を受け付けるコマンドである。
出力は簡単で、接続してきたプロセスが送信してきたものをそのまま吐き出す。

$ nc -l 1234 > output.txt
$ nc localhost 1234
THIS IS OUTPUT
<C-d>

こうするとoutput.txtには”THIS IS OUTPUT”と入っている。

入力は反対に、接続してきたプロセスに送るデータになる。

$ echo HELLO | nc -l 1234
$ nc localhost 1234
HELLO #勝手に出力される

問題のコード

$ cat /tmp/f | /bin/sh -i 2>&1 | nc -l 127.0.0.1 1234 > /tmp/f

生成された/tmp/fは名前付きパイプである。
コマンドの最後にnc -lの結果を/tmp/fに流しているので、クライアントが送ってきた文字列が名前付きパイプが流れる。
つづいてコマンドの最初には/tmp/fからの出力をbashに流し、その出力をnc -lに流れている。

したがってこの図のようになる。

このコマンドを実行すれば、ncするとshのプロンプトが現れ、コマンドを打つとその実行結果が送られてくる。

まぁもちろん普段は絶対使用しないように。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です