あるいは攻撃を受けた日
この記事は SZPP Advent Calendar 2023 の 12/13 (水) の記事です。
自室にサーバを置いている。自宅サーバの先輩方にとってみれば非常に小さなリソースで限定的な用途にのみ用いているものだが。基本的には録画したアニメの母艦であり、たまに諸々のbotなんかも動かしている。ある日、ふと出先でもアニメ見れたらいいなと思い立ちインターネットに公開してみた。
しっかりブルートフォースアタックされた
せっかく攻撃されたのでインシデントハンドリング(ログ調査のみ)してみた。
環境は
- Raspberry Pi Model A Rev 2
- Raspbian GNU/Linux 11 (bullseye)
以下に、実際の攻撃ログの一部を載せる。
journalctl -x -u ssh --grep=Failed
お手本のような攻撃である。同じユーザ名で複数回ログイン試行しているからブルートフォースと呼ぶのが正確だと思うのだけれど、合ってるかしら?
せっかくなので軽く統計情報をまとめてみよう。
攻撃のログを観察
都度 journalctl
を呼び出してデータベースを読ませるのも負荷が高いだろうなと考え、一旦テキストに書き出した。以降はこれを使うことにする。
journalctl -x -u ssh --grep=Failed --no-pager --output json-pretty --output-fields SYSLOG_TIMESTAMP,MESSAGE > /tmp/journald_ssh_service_20230523_20231205_json.log
中身はこうなる
{ "__CURSOR" : "s=c839e4fc248048c4a7f624a45f792f58;i=16f055;b=e2cad57cbb644386a0d9bc6570859844;m=15202b604f7;t=5fc533a8f78fa;x=17a756bf079ef771", "MESSAGE" : "Failed password for invalid user git from 64.227.144.170 port 44602 ssh2", "__MONOTONIC_TIMESTAMP" : "1451744429303", "__REALTIME_TIMESTAMP" : "1684809278519546", "_BOOT_ID" : "e2cad57cbb644386a0d9bc6570859844", "SYSLOG_TIMESTAMP" : "May 23 11:34:38 " } // ...
(本気でログ管理しようとしたらDataDogやKafkaなどを使うのだろうけれどもふつうのコマンドだけでやってみるという裏テーマもあるので、それに沿っていく)
journalctl
に--output
を渡すとJSON形式で出してくれるの知らなかった。
メッセージ部分
メッセージだけ取り出してgrepしてみる。エラーログはおよそ「Failed password for invalid user」という文字列が含まれているのでJSON形式のログからメッセージだけ取り出したうえでログインを試みているユーザ名以外を削除して集計してみる。
cat /tmp/journald_ssh_service_20230523_20231205_json.log | jq -r '.MESSAGE' > /tmp/sshd_error_log.txt grep 'Failed password for invalid user' /tmp/sshd_error_log.txt | sed -r 's/^Failed password for invalid user ([a-zA-Z0-9]+) from.*$/\1/' | sort | uniq > /tmp/invalid_users.txt
これでおおよそログインユーザ名の辞書が復元できたことになる。
さて保存したファイルを見てみると、下記のような特徴がみられた。
- 同じ文字列でも大文字小文字などで複数回トライされている
- well-knownなユーザ名とそれのミスタイプ名もトライされている
- 人名っぽいユーザ名がある
以下それぞれ見ていく。
まず大文字小文字で複数回トライしている例。まあやるだろうなという名前。
adm admin Admin ADMIN admin123 Admin5
次に well-known なユーザ名とミスタイプ。よく見るec2-user
、wp-admin
、mongodb
などがあった。de-だけでこの量がある。
debian debianuser default dell demo dep deploy deployer design dev develop developer devopsuser
ミスタイプを狙ったものとしては例えばこんなの。
administrador administrator Administrator
(t と d 間違えるかね?)
最後に人名。
robert zhao
などがあった。日本人っぽい名前は見受けられなかった。
攻撃時間帯の頻度
次に時間に着目してみる。
# journald の吐き出す時間がナノ秒なのでミリ秒オーダーに直す $ cat /tmp/journald_ssh_service_20230523_20231205_json.log | jq -r '.__REALTIME_TIMESTAMP|tonumber / 1000000|strftime("%Y-%m-%d-%H")' | uniq -c 51 2023-05-23-02 7 2023-05-23-04 1521 2023-05-23-05 2092 2023-05-23-06 1950 2023-05-23-07 2016 2023-05-23-08 1838 2023-05-23-09 1890 2023-05-23-10 1498 2023-05-23-11 1419 2023-05-23-12 1399 2023-05-23-13 1507 2023-05-23-14 693 2023-05-23-15 347 2023-05-23-16 93 2023-05-23-17 106 2023-05-23-18 2 2023-05-23-19 253 2023-05-23-20 268 2023-05-23-21 406 2023-05-23-22 7 2023-05-23-23 37 2023-05-24-00 15 2023-05-24-01 300 2023-05-24-02 316 2023-05-24-03 1600 2023-05-24-04 2141 2023-05-24-05 2158 2023-05-24-06 2051 2023-05-24-07 2193 2023-05-24-08 2227 2023-05-24-09 1939 2023-05-24-10 1882 2023-05-24-11 2026 2023-05-24-12 1811 2023-05-24-13 1684 2023-05-24-14 451 2023-05-24-15 2 2023-11-15-08 4 2023-12-04-11
5時から10時頃にかけて攻撃の回数が重なっているように見える(UTC)。日本時間だとお昼過ぎから増加して22時前に落ち着く感じだった。なんでだろう?
対策
インターネットに公開しない!!
実際のところ、インターネットのアップロードが激遅いのとサーバに使っているラズパイのUSBの転送速度のせいで出先で動画を観るのは現実的ではないんだけれども、何も対策しないのもいくないと思うので、適当にやってみる。本当はiptables(nftables)なりfirewalldなりのファイアウォールを設定してバインドするポートを制限したり、ブルートフォースアタックっぽいアクセスを検知してそのIPを遮断する監視ツールを入れたりするのがよいのだろうけれど、そこまでやると日付が変わってしまうので、雑に sshd の設定を見直すにとどめる。
- ポートをデフォルトの22番から変更
Port 10222
- 接続元IPを制限
ListenAddress 192.168.1.0/24
*1 - パスワードログインを禁止
PasswordAuthentication no
- ログインできるユーザを制限
AllowUsers someone
- rootログインを禁止
PermitRootLogin no
1と2以外は全部実施済みだったので、ファイアウォールなど別の対策をした方がいいんだろうなとは思う。まあ攻撃体験記なので対策は他の優秀な記事に譲るとして…。
おわりに
今回は実際にSSHのパスワードログインをブルートフォースアタックによって試行してくるある種古典的な攻撃を2023年に受けて興奮したので記事にした。教科書では見たことあるけれど実際に攻撃を受けてみると結構興奮するので読者諸君も壊してもいいサーバをインターネットに公開してみてはいかがだろうか。
そもそもサーバをインターネットに公開したのは録画したアニメを出先でも観たいからだった。nginxをwebサーバにしてHDDの内容を配信しているだけなのだが、そのアクセスログにもそれはそれで面白い攻撃のログが残っていたのでまたいつか紹介できたらしようかな~。
おわり。