AWSが不正利用された件に対する対応(その3・技術対応編)

AWS logo
シリーズ最終回は技術対応編です






やったことをまとめます

AWSにめちゃくちゃ詳しいかといわれるとそうでもないし、サービスを設計した人間でもなく設計書が残されているわけでもないので、実際にはAWSの各種設定とプログラムとを両方見ながら試行錯誤しました。超大変でした。最終解決するまでに1ヶ月掛かっちゃった。ただ結果的に非常にセキュアな環境に出来たので良かったんじゃないかなと思います。


ではやったことを適当に並べて書きましょう。



アクセスキーの廃止とロールの導入

技術対応の中で最も重要だと思うのはこれです。

プログラムの設計ポリシーとして、全てのサービスはただ1つのアクセスキーを使い回して利用されていました。例えば:


  • EC2からファイルをS3にアップロードする
  • EC2からSESでメールを送る
  • EC2からDynamoDBにデータを保存する


サービスを動かすという点だけ考えるとシンプルで便利なのですけど、もしこのアクセスキー(とシークレット)が流出してしまったらどうなるか?IAMユーザーの権限にもよりますが、許可された範囲であれば外部から好きなことが出来てしまいます。AWSのベストプラクティスにもこう書かれています。


Amazon EC2 インスタンスで実行されているアプリケーションまたは AWS CLI スクリプトがある場合。アプリケーション内で直接アクセスキーを使用しないでください。アクセスキーをアプリケーションに渡したり、アプリケーションに埋め込んだり、ソースからアクセスキーを読み取ったりしないでください。代わりに、アプリケーションに適したアクセス許可を持つ IAM ロールを定義し、EC2 のロールを使用して Amazon Elastic Compute Cloud (Amazon EC2) インスタンスを起動します。これにより、IAM ロールが Amazon EC2 インスタンスに関連付けられます。この方法により、アプリケーションは AWS へのプログラムされた呼び出しに使用することもできる、一時的なセキュリティ認証情報を取得します。AWS SDK および AWS Command Line Interface (AWS CLI)は、そのロールから一時的なセキュリティ認証情報を自動的に取得できます。

AWS アクセスキーを管理するためのベストプラクティス – AWS アカウント管理


IAMロールをEC2インスタンスに紐付けるのは簡単です。少し古いですが、この辺の記事が参考になります。


こんにちは。イムチェジョンです。 今回のブログではIAMロールをEC2インスタンスに設定をし、インスタンスの中でawsコマンドを実行してみたいと思います。

IAMロールをEC2インスタンスに設定をしてみた | DevelopersIO


EC2インスタンスにロールを紐付けたら、あとはそのロールにポリシーを設定すればOKです。そのEC2インスタンスからは認証情報を意識することなく操作が可能になります。SDKでクライアントを生成するときにも認証情報は不要になります。


$client = new \Aws\Ses\SesClient([
   'region' => 'ap-northeast-1',
   'version' => 'latest'
]);


設定が完了し動作確認が済んだら、プログラム内もしくは設定ファイルに記載されたアクセスキーを順次削除していきます。クライアント呼び出し部分も忘れずに。クライアント呼び出し部分がサービス化されていて1ヵ所変えればOKとかだったら楽だったんですけど、プログラムごとに設定している箇所もあってものすごい骨の折れる作業でした。必要なので仕方ありませんが、設計者の手抜きを尻拭いしてるって感じですかね。




権限を絞る

フルアクセス権限(AdministratorAccess)をもったIAMユーザーはシステムの脆弱性になります。そんなのrootユーザーだけでいいじゃん。


権限の設定には色んな方法があり、もっと管理しやすくセキュアな方法もあるのだと思いますけど、今回はわかりやすさ優先でサービスごとにポリシーを作り、それを必要に応じてロールにアタッチする設計にしてみました。例えばSES経由でメールを送信するプログラムを操作するときは、そのEC2インスタンスにそのインスタンス用のロールを紐付けた上で、次のようなポリシーをアタッチします。


{
   "Version": "2012-10-17",
   "Statement": [
       {
           "Effect": "Allow",
           "Action": [
               "ses:SendRawEmail",
               "ses:SendEmail"
           ],
           "Resource": *
       }
   ]
}


以前は安易に「AmazonSESFullAccess」(SESに関するフルアクセス)ポリシーなんかをアタッチしていたようですが、それだと権限が広すぎてなんでも出来てしまうので、真に必要としているアクションだけを許可するようにしました。そんなに頻繁に機能追加されるシステムではないのでそれで十分です。

送信元が限られている場合には、以下のようにリソースを制限するとなお可です。下の例では「example.com」以外のドメインを送信元にしてメールを送ることは出来ません。


{
   "Version": "2012-10-17",
   "Statement": [
       {
           "Effect": "Allow",
           "Action": [
               "ses:SendRawEmail",
               "ses:SendEmail"
           ],
           "Resource": [
               "arn:aws:ses:ap-northeast-1:{AWSアカウントID}:identity/example.com"
           ]
       }
   ]
}


ちなみに既に動いているサービスに対してこれらの設定を全体に反映させるためには、またもやサービス全体の見直しが必要です。ソースコードを全部チェックして使っている機能を洗い出し、それに応じたポリシーを作成・アタッチした上で動作確認。マジ大変。

ただ実際に機能を洗い出して並べて見ると、必要としていた権限(アクション)は思った以上に少なくてびっくりしました。フルアクセス何か要らなかったんや。


なおS3はバケットとオブジェクトで権限やアクションの名称がわかりにくいので注意が必要です。このへんとか参考になるかも。


S3 を色々触っていて気になる事・ちょっとハマった事などがいくつかあったので、それについて書く。

S3 の ListObjects, ListBucket などについてのあれこれ – K blog



IAMユーザーの整理と制限

作ったけど使っていないユーザーや、ログインする必要ないのにログイン可能になっているユーザがたくさんあったので整理しました。


まずアクティビティがないユーザーは、ソースコード等確認の上削除。

コンソールにログインする必要があるユーザーは業務フロー的に2つしかなかったので、それ以外のユーザーはコンソールログインを禁止。許可されたユーザーは確実にMFA設定。

さらにログイン可能なユーザーが極端に大きな権限を持たないように、それぞれの役務に合わせた最低限の権限を設定。例えば経理担当だったら「Billing」だけとか。コンソールを少しは触れる人には「自分のアクセス情報をコントロール出来るポリシー」と「自分のMFAを設定・変更出来るポリシー」をアタッチするとか。


諸事情で大きな権限を持たせる必要があるIAMユーザーが出てくることもあるかもしれませんが、その場合でもMFAを確実に設定して、アクセスキーは発行しない、この2つがとても重要です。理想はそういうユーザーを作らずに済むようにすることですけども、例外というのは必ず出てくるので、最悪な状態にはならないようにしつつ柔軟に対応する必要があるのかなと。



完走した感想

最終的にAWSのサポートチーム、SESチームから「もう大丈夫そうだよ」というお墨付きを得て全ての制限が解除されるまでに1ヶ月ほど要しました。もちろん緊急対応は初日で済ませて、その間もサービスは継続して動いていたのですが、全部の対応が終わるまではいつ何されるかわからず怖かったです。今はもう安心。例えログインされても大したことは出来ないので。


しかしまあなんというか、何がどこからどうやって漏れたかがいまだにわからないのがものすごく気持ち悪いんですよね。。漏れた内容からして、Googleドライブを覗かれてる可能性やスタッフのPC内になんらかのウィルスが仕込まれてる可能性もあります。確か基幹システム的なソフトウェアを更新できなくて、しつこく古いPCを使ってる部署があったはずなんですよね。

ソースコードはGitHubでロックしてるので大丈夫だとは思うんですけど、、どうだろうか。念のためGitHubもパスワードを変えてMFA設定しておきましたけど、Googleアカウントもそうしておいた方が良いのかも。その辺りは僕の仕事と言うより社内SEさんの仕事なのでお任せですけども。


ともあれ結果的にとてもセキュアな状態に持って行けたのでその点は良かったかなと思います。



なお気になる請求額(さすがに額は明らかには出来ません)についてですが、様々な報告と交渉の結果、かなりの額については「今回だけよ」ということで免除してもらえました。しかしやはり不正利用全額免除とまでは行かず、まだ結構な額を請求されていて担当者が引き続き交渉中のようです。契約上、全ての責任はAWSではなくユーザーの方にあるので「だからちゃんとしろよって言ってるじゃん」と言われたら終わりで支払うしかないんですけど、心情的にはもうちょっと免除してくれませんかという感じ。わかりみ。

でもきっと難しいんだろうなあ。世知辛いぜ。自分が悪いから仕方ないんですけどね。



みなさんAWSのアカウント管理は抜かりなく。油断してるとやられますよという話でした。いやー大変でした。