SSHハニーポットはKippoではなくCowrieを使え
お久しぶりです。記事を書こうとして下書きが積もっていっております・・・。 今回はサクッと。
今回の内容
ハニーポット入門としてよく導入されるKippo。
しかしKippoは攻撃者に対策されたり、エラーが発生したりして思うようにマルウェアやログを取ることができません。
そういうときはKippoの改良版(?)的なCowrieを使っていきましょう。
Kippo全然うまくいかないよー、どうして?となっている人をたまに見かけます。ぜひともCowrieを使ってほしいです。
今回の記事では、Kippoが何故適さないのかを考えていきたいと思います。
あまり詳細には書きませんが、いわゆるKippoの挙動解説になります。
個人的にKippoは推奨していないので、挙動について書く意味は少ないと思います。
もしKippoの導入とかあれこれについて調べていてこの記事を見つけた方は、この記事を読むよりCowrieについて調べたほうがよいかもしれません。
なぜKippoが適さないのか
普通に使っていて気付いた点です。それ以上のことは特に調べてないです。(Kippoに関してはソースを全く読んでいないので)
コマンドのオプションやリダイレクトへの対応
echoコマンド
Kippoでエミュレートされるechoコマンドにはオプションは対応していません。 echoコマンドには-nや-eといったオプションが存在しますが、オプションを入力するとオプションがそのまま出力されます。
本来の動作
$ echo -n test test $echo -e "\ttest" test
Kippoでの動作
root@svr03:~# echo -n test -n test root@svr03:~# echo -t "\ttest" -t \ttest
これを利用して、攻撃者はログインしたサーバがkippoであるかを判定します。
ほとんどの攻撃者がログイン時にecho -n test
というコマンドを送り込み、-n test
という文字列が帰ってきたら攻撃をやめてしまいます。
sshコマンド
たいていechoコマンドで判定されてしまうのでこちらは必要ありませんが、sshコマンドも完全ではありません。
-V
というオプションが実装されていないようです。
本来の動作
$ ssh -V OpenSSH_7.2p2 Ubuntu-4ubuntu1, OpenSSL 1.0.2g-fips 1 Mar 2016
Kippoでの動作
root@svr03:~# ssh -V usage: ssh [-1246AaCfgKkMNnqsTtVvXxY] [-b bind_address] [-c cipher_spec] [-D [bind_address:]port] [-e escape_char] [-F configfile] [-i identity_file] [-L [bind_address:]port:host:hostport] [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port] [-R [bind_address:]port:host:hostport] [-S ctl_path] [-w local_tun[:remote_tun]] [user@]hostname [command]
上記のように、バージョンを表示しないといけないところをKippoではオプションを表示しています。
しかし攻撃者はこのチェックを特に行わないので、あまり影響はありません。(私はSSHハニーポットのログはあまり見ていないので、チェックする奴もいたかもしれませんが。)
リダイレクト・パイプ
実装されていません。これはマルウェアを収集するにあたって、大問題となります。 まずは挙動をご覧ください。
リダイレクト本来の動作
$ echo test > test.txt $ ls test.txt
リダイレクトKippoでの動作
root@svr03:~# echo test > test.txt test > test.txt
パイプ本来の動作
$ ls | echo test test
パイプKippoでの動作
$ ls | echo test ls: cannot access /root/|: No such file or directory ls: cannot access /root/echo: No such file or directory ls: cannot access /root/test: No such file or directory
(パイプについては、Kippoに実装されているコマンドから選んだため分かりづらいことに・・・)
リダイレクトの>
も、パイプの|
も、文字として判定されるためこうなります。
実は、マルウェアの送り込みはこれが主流となっていて、
root@svr03:~# cat >hogehoge fugafugafugafuga.....(バイナリ)
という形で攻撃対象にマルウェアを設置します。
つまり、リダイレクトが使えないということはほぼマルウェアが取れないことを意味します。
わざわざ別サーバからwgetとか使ってダウンロードさせるものは滅多にお目にかかれません。SSSRぐらいですかね?
エラー
sshコマンドからコマンド入力されることによるエラー
リダイレクトが使えないことと同様、こちらも重大な問題となります。エラーなのでこちらのほうが重い。 正確な条件は分かりませんが、sshコマンドを使って直接コマンドを実行するときに起こります。
$ ssh -l ユーザ名 IPアドレス "cat >/tmp/hoge" Password: exec request failed on channel 0
kippo.logを見てみると
2016-06-30 01:46:44+0900 [-] New connection: 192.168.1.1:52378 (192.168.1.1:2222) [session: 27] 2016-06-30 01:46:44+0900 [-] Remote SSH version: SSH-2.0-OpenSSH_7.2p2 Ubuntu-4ubuntu1 2016-06-30 01:46:44+0900 [HoneyPotTransport,27,192.168.1.1] kex alg, key alg: diffie-hellman-group-exchange-sha1 ssh-rsa 2016-06-30 01:46:44+0900 [HoneyPotTransport,27,192.168.1.1] outgoing: aes128-ctr hmac-sha1 none 2016-06-30 01:46:44+0900 [HoneyPotTransport,27,192.168.1.1] incoming: aes128-ctr hmac-sha1 none 2016-06-30 01:46:48+0900 [HoneyPotTransport,27,192.168.1.1] NEW KEYS 2016-06-30 01:46:48+0900 [HoneyPotTransport,27,192.168.1.1] starting service ssh-userauth 2016-06-30 01:46:48+0900 [SSHService ssh-userauth on HoneyPotTransport,27,192.168.1.1] root trying auth none 2016-06-30 01:46:48+0900 [SSHService ssh-userauth on HoneyPotTransport,27,192.168.1.1] root trying auth keyboard-interactive 2016-06-30 01:46:50+0900 [-] login attempt [root/test] succeeded 2016-06-30 01:46:50+0900 [SSHService ssh-userauth on HoneyPotTransport,27,192.168.1.1] root authenticated with keyboard-interactive 2016-06-30 01:46:50+0900 [SSHService ssh-userauth on HoneyPotTransport,27,192.168.1.1] starting service ssh-connection 2016-06-30 01:46:50+0900 [SSHService ssh-connection on HoneyPotTransport,27,192.168.1.1] got channel session request 2016-06-30 01:46:50+0900 [SSHChannel session (0) on SSHService ssh-connection on HoneyPotTransport,27,192.168.1.1] channel open 2016-06-30 01:46:50+0900 [SSHService ssh-connection on HoneyPotTransport,27,192.168.1.1] got global no-more-sessions@openssh.com request 2016-06-30 01:46:50+0900 [-] request_env: '\x00\x00\x00\x04LANG\x00\x00\x00\x0bja_JP.UTF-8' 2016-06-30 01:46:50+0900 [SSHChannel session (0) on SSHService ssh-connection on HoneyPotTransport,27,192.168.1.1] executing command "cat >/tmp/hoge" 2016-06-30 01:46:50+0900 [-] exec command: "cat >/tmp/hoge" 2016-06-30 01:46:50+0900 [-] Opening TTY log: log/tty/20160630-014650-2137.log 2016-06-30 01:46:50+0900 [-] /etc/motd resolved into /etc/motd 2016-06-30 01:46:50+0900 [-] Running exec command "cat >/tmp/hoge" 2016-06-30 01:46:50+0900 [-] CMD: cat >/tmp/hoge 2016-06-30 01:46:50+0900 [-] Command found: cat >/tmp/hoge 2016-06-30 01:46:50+0900 [SSHChannel session (0) on SSHService ssh-connection on HoneyPotTransport,27,192.168.1.1] Unhandled Error Traceback (most recent call last): File "/usr/local/lib/python2.7/dist-packages/twisted/python/log.py", line 85, in callWithContext return context.call({ILogContext: newCtx}, func, *args, **kw) File "/usr/local/lib/python2.7/dist-packages/twisted/python/context.py", line 118, in callWithContext return self.currentContext().callWithContext(ctx, func, *args, **kw) File "/usr/local/lib/python2.7/dist-packages/twisted/python/context.py", line 81, in callWithContext return func(*args,**kw) File "/usr/local/lib/python2.7/dist-packages/twisted/conch/ssh/channel.py", line 137, in requestReceived return f(data) --- <exception caught here> --- File "/usr/local/lib/python2.7/dist-packages/twisted/conch/ssh/session.py", line 70, in request_exec self.session.execCommand(pp, f) File "/home/kippo/kippo/kippo/core/ssh.py", line 267, in execCommand serverProtocol.makeConnection(protocol) File "/usr/local/lib/python2.7/dist-packages/twisted/internet/protocol.py", line 487, in makeConnection self.connectionMade() File "/home/kippo/kippo/kippo/core/protocol.py", line 237, in connectionMade insults.ServerProtocol.connectionMade(self) File "/usr/local/lib/python2.7/dist-packages/twisted/conch/insults/insults.py", line 427, in connectionMade self.terminalProtocol.makeConnection(self) File "/usr/local/lib/python2.7/dist-packages/twisted/conch/insults/insults.py", line 59, in makeConnection self.connectionMade() File "/home/kippo/kippo/kippo/core/protocol.py", line 146, in connectionMade self.cmdstack[0].lineReceived(self.execcmd) File "/home/kippo/kippo/kippo/core/honeypot.py", line 68, in lineReceived self.runCommand() File "/home/kippo/kippo/kippo/core/honeypot.py", line 125, in runCommand self.honeypot.call_command(cmdclass, *rargs) File "/home/kippo/kippo/kippo/core/protocol.py", line 117, in call_command obj.start() File "/home/kippo/kippo/kippo/core/honeypot.py", line 26, in start self.call() File "/home/kippo/kippo/kippo/commands/fs.py", line 16, in call if self.fs.is_dir(path): File "/home/kippo/kippo/kippo/core/fs.py", line 172, in is_dir dir = self.get_path(os.path.dirname(path)) File "/home/kippo/kippo/kippo/core/fs.py", line 87, in get_path p = [x for x in p[A_CONTENTS] if x[A_NAME] == i][0] exceptions.IndexError: list index out of range 2016-06-30 01:46:50+0900 [HoneyPotTransport,27,192.168.1.1] connection lost
うわああああああああああああああああああああああああああ!!!!!
となります。ちなみにこの状態になると~/kippo/log/tty/
には何も出力されません。(ファイルは作成されます)
ちなみに下記のように>
の前後を空白にするとエラーは出力されません。(正常な結果ではありませんが)
$ ssh -l root IPアドレス "cat > /tmp/hoge" cat: >: No such file or directory cat: /tmp/hoge: No such file or directory
また、catのすぐ横に>
を置くとコマンドは認識されなくなります。
(前者も後者も>
が文字扱いのため)
以上の結果から、おそらくcat
で>/
が入力されたときに発生すると思われます。
このエラーは、sshコマンドからコマンドを入力されることで発生し、ログインしてから入力を行うと発生しません。 しかし、リダイレクトできないため内容を収集することはできません。
攻撃者の挙動とttyログについて
ここで一応説明しておきますが、攻撃者は基本的に
$ ssh -l ユーザ名 IPアドレス コマンド
で攻撃対象での活動を行います。
わざわざログインし続けて行う攻撃者もSSRぐらいですかね、あまり見ません。
ちなみにKippo、Cowrie共に~/kippo/log/tty/
には1度のアクセスにつき1つlogファイルを作成します。
Kippoは日付-時間-ランダムな数値(?).log
という命名規則であるのに対し、Cowrieは`日付-時間-送信元IP等の情報のハッシュ値(?)-アクセス回数eもしくはi.log'です。
eについてはsshコマンドからの実行、iについてはログインしてからの行動を指していると思われます。
Cowrieのほうがニーズに合いますね。
Cowrieについて
Cowrieでは上記の問題ほぼ全てが解決されています。
新たな問題点としては、ログイン後にcatコマンドで文字等を入力しファイルを作成する、ということができなくなっていることでしょうか。(この記事のために検証していたら気づいた)
どうせ攻撃者はほとんどsshコマンドから直接実行しようとしてくるし、もしログインしてもバイナリを注入するまで気づくことはないでしょう。
というわけで、これからハニーポットに手を出そうと思ってる方はKippoではなくCowrieを使ってみるといいですよ。
参考
GitHub - desaster/kippo: Kippo - SSH Honeypot
GitHub - micheloosterhof/cowrie: Cowrie SSH Honeypot (based on kippo)
[技術|SEC] kippoで、echoを用いたハニーポット判定を防ぐ | 話譚でいいと思うよ
余談
ここにいろいろなハニーポットが集めてあります。
SSHハニーポットもいろいろありますが、見た感じKippo系列が一番使いやすそうですね。 Dockerのやつとか面白そうです。(Raspberry Piで使えないのが残念)
っと、結局5時間ぐらいかかったしそこそこがっつりやってしまったかも。でも書いたら書いたで勉強になるんだよなぁ。