先日、以下のようなBashコマンドを目にした。
bash -c "</dev/tcp/1.2.3.4/80"
(IPアドレスは仮のもの)
一瞬、Reverse Shellかと思い、ギクッとしたが、よく見るとコマンドの構文が違う。
結論から言うとReverse Shellではなかった。
クライアント (192.168.74.131) とサーバー (192.168.74.128) を用意して、先述したコマンドを検証してみた。
192.168.74.128
サーバー。80番ポートでwebサーバーを実行している。
$ netstat -an | grep ":80"
tcp6 0 0 :::80 :::* LISTEN
通信内容を確認したいので、以下のtcpdumpコマンドで80番ポートの通信をPCAPに保存した。
tcpdump -i eth0 port 80 -w dev_tcp_test.pcap
192.168.74.131
クライアント。以下のBashコマンドで192.168.74.128の80番ポートと通信してみた。
bash -c "</dev/tcp/192.168.74.128/80"
以下はコマンドの実行結果である。

以下はキャプチャされた通信である。

192.168.74.131:55411と192.168.74.128:80でTCPのハンドシェイクを行っているのが分かる。
bash -c "</dev/tcp/192.168.74.128/80"だけでは、単にリモート・ホストの特定のポートにSYNを投げるだけで、Reverse Shellにはなりえない。
調べたところ、上記のコマンドは主にポートの疎通確認に使用されるコマンドのようである。
bash -c "</dev/tcp/192.168.74.128/80" && printf "port is reachable" || printf "Failed to reach port"
上記のコマンドは192.168.74.128の80番ポートに接続できた場合はport is reachableというメッセージを表示し、接続できなかった場合はFailed to reach portと表示する。(&&や||の意味については、こちらの記事を参照)
$ bash -c "</dev/tcp/192.168.74.128/80" && printf "port is reachable" || printf "Failed to reach port"
port is reachable
192.168.74.128では80番ポートが開放されているので、port is reachableと表示された。
$ bash -c "</dev/tcp/192.168.74.128/1234" && printf "port is reachable" || printf "Failed to reach port"
bash: connect: Connection refused
bash: /dev/tcp/192.168.74.128/1234: Connection refused
Failed to reach port
対して、1234番ポートは開放されていないので、Connection refusedエラーが表示されたのち、Failed to reach portと表示された。