dockerはufwに穴を空ける。

本投稿は TECOTEC Advent Calendar 2021 の17日目の記事です。

決済認証システム事業部の下江です。 今年の夏ごろ、ふとサービスを作りたいなと思い、仮想レース配当サービスを個人で作っていた時に起きたDB情報を全部抜かれた話をしていこうと思います。

<2021.12.17 追記>
※本記事はあくまで個人開発上で起きた問題であり、弊社開発ではセキュリティ専門の部隊がこの要な事態が発生しないよう対応しています。

構成

OS: Ubuntu 20.04.2 LTS
フレームワーク:Laravel
フロント : blade
デザイン : TailwindCSS

DB情報が抜かれるまでの流れ

サーバの初期設定を行い、動作確認のためBasic認証を掛けて知り合い内共有して、 いくつか細かい問題の修正を行いとりあえず動作するところまで終わらせた後就寝しました。

翌日、知り合いから「500出てるよ」と連絡があり調査を行ったところ、サーバのエラーログにUnknow Database の文字列がずらり。
dbを確認しに行くと、メインのデータベースが消されており正体不明のReadmeデータベースが作成されていました。 中身には要約すると、データ取ったから返して欲しかったらここに振り込んでねと書いてありました。
f:id:teco_shimoe:20211215132952p:plain
ひえ…

原因

ポート

幸い知り合い内で動作確認を行っている段階だったので軽傷で済んだのですが、もちろんこのままリリースする訳はいかないので原因調査開始。
laravelの脆弱性で良く話題に上がる、debug modeをオンにしていたことが原因だと考えて調査していたのですが、特にこれといった問題なく、成果なし。
そうしているとき再度友人から、ポートが空いてるけど大丈夫?と連絡があり確認を行うと f:id:teco_shimoe:20211214172500p:plain 3306のポートが開いたままになっていることが確認されました。
なぜ....

ファイアウォール設定

さすがにリリース前にファイアウォール設定をしていない訳は無いので設定を再確認。 今回はufwを利用して設定を行っていました。 f:id:teco_shimoe:20211214173153p:plain 画像の通り設定は、7614/80/443のホワイトリストになっています。

iptables

ufwでは、iptablesにufwの設定を書き込んでいるのでその部分を調査

Chain INPUT (policy DROP)
target     prot opt source               destination         
ufw-before-logging-input  all  --  anywhere             anywhere            
ufw-before-input  all  --  anywhere             anywhere            
ufw-after-input  all  --  anywhere             anywhere            
ufw-after-logging-input  all  --  anywhere             anywhere            
ufw-reject-input  all  --  anywhere             anywhere            
ufw-track-input  all  --  anywhere             anywhere            

Chain FORWARD (policy DROP)
target     prot opt source               destination         
DOCKER-USER  all  --  anywhere             anywhere            
DOCKER-ISOLATION-STAGE-1  all  --  anywhere             anywhere            

(省略)

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
ufw-before-logging-output  all  --  anywhere             anywhere            
ufw-before-output  all  --  anywhere             anywhere            
ufw-after-output  all  --  anywhere             anywhere            
ufw-after-logging-output  all  --  anywhere             anywhere            
ufw-reject-output  all  --  anywhere             anywhere            
ufw-track-output  all  --  anywhere             anywhere            

Chain DOCKER (2 references)
target     prot opt source               destination         

Chain DOCKER-ISOLATION-STAGE-1 (1 references)
target     prot opt source               destination         
DOCKER-ISOLATION-STAGE-2  all  --  anywhere             anywhere            
DOCKER-ISOLATION-STAGE-2  all  --  anywhere             anywhere            
RETURN     all  --  anywhere             anywhere            

Chain DOCKER-ISOLATION-STAGE-2 (2 references)
target     prot opt source               destination         
DROP       all  --  anywhere             anywhere            
DROP       all  --  anywhere             anywhere            
RETURN     all  --  anywhere             anywhere            

Chain DOCKER-USER (1 references)
target     prot opt source               destination         
RETURN     all  --  anywhere             anywhere            

(省略)

Chain ufw-user-input (1 references)
target     prot opt source               destination         
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:7613
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:http
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:https

(省略)  

以上のようになっていました。
docker...?

docker

ということで、上のiptablesの設定を見て察しの良い方は気づかれるかもしれませんが、ufwのユーザ設定とdockerのユーザ設定が並列で並んでいます。
つまり、ufwでいくらホワイトリスト設定していても、dockerで開けたポートは空きっぱなしになってしまいます。
結論、
「docker-compose.ymlのport指定がグローバルアドレスになっていた」
ということでした。(DBのキーパス周りの設定もしていなかったのも悪かった)

対応

とりあえず、dbを作り直した後、 dockerファイルでポートの指定を

3306:3306
↓
127.0.0.1:3306:3306

とすることで、想定通りの動作をするようになりました。

まとめ

dockerはufwに穴を空けるので気を付けよう。
リリース終わったらちゃんと外部からのポート確認を行おう。
そもそもdbにちゃんとキーパスつけておこう。
皆さん良い個人開発ライフを

www.tecotec.co.jp