先日、以下のような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
と表示された。