管理しているMastodonインスタンスのRedisが攻撃を受けてしまった事件の技術的レポート
概要
12/29にクラウドの移行を実施した。 その際にdockerの設定ミスによりRedisへ外部から自由アクセスできるようになっていた。 後日、Redisへの攻撃の試行を検知した。 そのため、設定の修正を行った。
ユーザの皆様および関係各所申し訳ございません。
影響
期間:2018 12/29-2019 01/05
ユーザへの影響: 12/29-01/05にフォローする/されるしたユーザのメールアドレスが、それぞれ短期間(各数秒程度)ではあるものの外部からアクセス可能な状態となっていた。
調査ログ
移行後、頻繁にDOWNアラートを検知。 ログを調査したところ下記出力。
Redis::CommandError: MISCONF Redis is configured to save RDB snapshots,
この時点でRedisまわりかDockerのメモリ関連の設定ミスだろうと疑う。 コンテナを再起動すれば治るのでアラートが起きたら発火する再起動スクリプトで暫定対応を実施。調査は後日することに。
後日調査。 障害時にRedisでsaveが発行できないことを発見。
$ /usr/local/bin/docker-compose exec redis redis-cli 127.0.0.1:6379> save (error) ERR
Redisログ確認実施。
redis_1 | 1:M 05 Jan 12:23:55.004 * Background saving started by pid 1168 redis_1 | 1168:C 05 Jan 12:23:55.004 # Failed opening the RDB file root (in server root dir /etc/crontabs) for saving: Permission denied
なぜか"/etc/crontabs"に書き込もうとしているログ出力を確認。この時点で攻撃を受けた、あるいは使っているRedisイメージに悪意のあるコードが含まれていた可能性を疑う。
Redisのディレクトリ関連の設定を見てみると下記のように"/etc/crontabs"に書き込む設定にされている。真っ黒。
$ docker-compose exec redis redis-cli 127.0.0.1:6379> config get dir 1) "dir" 2) "/etc/crontabs"
もしやと思いホスト外からRedisにアクセス。普通にできてしまう...
ファイアウォール設定確認。
# firewall-cmd --list-all public (active) target: default icmp-block-inversion: no interfaces: eth0 sources: services: ssh dhcpv6-client https http ports: protocols: masquerade: no forward-ports: source-ports: icmp-blocks: rich rules:
redis関連のポートは開けていない。
Docker-Composeの設定を疑いportsを削除。 外部からつながらないことを確認。 Docker-Composeの設定により外部からアクセスできるようになっていたことを把握。
RedisのKeyとして"weaponX"等の不審なキーが存在することを確認。
対応
RedisのRDBファイルを削除。
docker-compose.ymlのportsで"IP:port:port"とすることでホストからのみアクセスできるようになる。この設定に直した。
監視拠点を別のConoHa VPSのインスタンスとしてたて、プライベートネットワークで通信するようにした。 そして、ConoHaの接続許可ポートをしぼった。
DBへのアクセスは外部からできないことを確認。 また、ログ等を精査しRedis以外には侵入された形式がないことを確認。 sidekiqによるメール配送のためにsidekiqのキューに乗って消化されるまでの間、Redisにユーザのメールアドレスが存在することを確認。
なぜ設定漏れが発生したかの経緯
Sidekiqのキュー監視のためにRedisのポートを開放していた。 ただし、この時点ではIDCFクラウドをつかっており、IDCFクラウドでは上位LBでファイアウォールがあったため外部からRedisへはアクセスができなかった。 IDCF個人プラン廃止のため12/29にConoHaへ移行を実施。 ConoHaの接続許可ポートは未設定。 これは任意ポートを指定して開けることができないため監視を通す必要性から。 firewallの設定を実施。 しかし、「Dockerはfirewalldではなくiptablesに書き込むためfirewalldの設定は無視される」ということに気づいていなかった。
再発防止策
- 定期的にセキュリティスキャンを実施する(OSSやサービスを検討中段階)。
- 別の管理人の人に調査してもらいました OSSセキュリティ脆弱性テストツールの紹介(一部) - Qiita
- 構築段階で意図した構成になっているかServerspecでテスト。