🐯

GCP-Goat で学ぶ Google Cloud セキュリティ Day2

2022/12/14に公開

はじめに

こんにちは、クラウドエースでSREディビジョンに所属している Shanks と申します。

前回の投稿から間が空いてしまい申し訳ございません。
本日は「GCP-Goat で学ぶ Google Cloud セキュリティ Day2」としまして、以前投稿したDay1(Google Cloud でSSRFに備える記事)の第二弾となります。
もし前回の記事をまだご覧になられていないようでしたら、あわせて是非ご確認いただけますと幸いです。

gcp-goat

ターゲットとなる読者層

  • Google Cloud 上で Cloud SQL を利用している
  • Cloud SQL を使ってはいるもののどのようなセキュリティ対策を行うべきかイメージできていない
  • 自社のセキュリティポリシーで Google Cloud の範囲がカバーできているか不安なので参考情報がほしい

この連載でやること・やらないこと

やること

  • GCP-Goat に掲載された攻撃の詳解
  • Google Cloud 特有機能や技術の詳解
  • 脅威からシステムを保護する方法
  • 事例の紹介(セキュリティインシデント・対策事例)

やらないこと

  • GCP-Goat の手順をそのままなぞること
  • 特定の製品の使い方(セキュリティ対策ソフト等)
  • Cloud Security Command Center のような有料契約(高額)製品の使用

注意事項

この連載はあくまで「脅威からどのようにしてシステムを保護するのか」を学ぶ場であり、攻撃を助長することが目的ではありません。
また、GCP-Goat では意図的に脆弱な環境を構成するため、決してこれを 本番環境へデプロイしないでください。

Cloud SQL への攻撃

attacking-sql
Attacking SQL Instance [原文タイトル]
https://gcpgoat.joshuajebaraj.com/attacking-sql.html

この章では、Cloud SQL に設定すべきアクセス制限等のセキュリティ対策を実施し、悪意ある第三者からの不正なログインから DB を保護する方法について学んでいきます。
まずは、Cloud SQL インスタンスを GCP-Goat の手順に則って作成し、どのような驚異が潜んでいるのかを見ていきましょう。
create-sql

シナリオの初期構成

まずはこの章の初期構成を確認してみましょう。

最初の段階では以下のセキュリティリスクとアーキテクチャの問題を抱えています。

  • Cloud SQL インスタンスに外部IPアドレスが付与されている
    • パブリックインターネットを通して公開されてしまっている
    • 内部通信 / 外部通信問わずアクセスが可能な状態

実際にアクセスできるか、nmap と mysql-client を使って確認していきます。

nmap でスキャン

Cloud SQL に適当な VPC ネットワークと、GCE インスタンスを構築します。
そのうえで、作成された GCE インスタンスに nmap と mysql-client をインストールします。
このときの GCE インスタンスの OS やスペックは任意で構いません。
外部IPアドレスはエフェメラル(動的)で構いませんので付与してください。

Cloud SQL インスタンスのIPアドレスを、以下のコマンドで確認してみましょう。
JSON形式で出力された際に、「ipAddress」がキーになっている値が Cloud SQL インスタンスのIPアドレスです。

$ gcloud sql instances describe ${INSTANCE_NAME} \
  --project=${PROJECT_ID} \
  --format=json \
  | jq '.ipAddresses'
[
  {
    "ipAddress": "xx.xx.xx.xx",
    "type": "PRIMARY"
  }
]

それでは実際に nmap コマンドで確認してみましょう。
Cloud SQL インスタンスがオープンにしているポートが一覧できますね。

$ nmap -Pn xx.xx.xx.xx

Starting Nmap 7.93 ( https://nmap.org ) at 2022-11-28 09:35 JST
Stats: 0:00:41 elapsed; 0 hosts completed (1 up), 1 undergoing Connect Scan
Connect Scan Timing: About 97.35% done; ETC: 09:35 (0:00:01 remaining)
Nmap scan report for 100.61.80.34.bc.googleusercontent.com (xx.xx.xx.xx)
Host is up (0.011s latency).
Not shown: 994 filtered tcp ports (no-response)
PORT     STATE SERVICE
80/tcp   open  http
110/tcp  open  pop3
143/tcp  open  imap
3128/tcp open  squid-http
3306/tcp open  mysql
8080/tcp open  http-proxy

Nmap done: 1 IP address (1 host up) scanned in 42.28 seconds

これにより、悪意ある攻撃者は「どの宛先に」「どのポートがあり」「どのようなサービスを展開しているか」を確認できます。
また、外部IPアドレスによるスキャンが実行できたということは、ファイアウォール等で守られていないサーバなのだと判断できます。
このように、サーバのIPアドレス(宛先エンドポイント)やポートなどを公開状態にしてしまうと、次の攻撃の糸口になり得るため、安全とは言えません。

root のユーザーパスワードポリシー

続いて、mysql-client を使って上記で判明した宛先にアクセスしてみましょう。

$ mysql -u root -h xx.xx.xx.xx

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 222
Server version: 5.7.39-google (Google)

Copyright (c) 2000, 2022, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

なんと、root にも関わらずパスワードを求められることなくアクセスできてしまいました。

SQL リソースの追加/閲覧/編集

root でアクセスできてしまえば、SQL リソースへも自由にアクセスできます。

例えば、データベースを作ってみたり

mysql> CREATE DATABASE GCP
    -> ;
Query OK, 1 row affected (0.04 sec)

mysql> SHOW DATABASES
    -> ;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| GCP                |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.04 sec)

例えば、テーブルを作ってみたり

mysql> CREATE TABLE GCP.SAMPLE(id int, name varchar(10))
    -> ;
Query OK, 0 rows affected (0.06 sec)

mysql> SHOW TABLES FROM GCP
    -> ;
+---------------+
| Tables_in_GCP |
+---------------+
| SAMPLE        |
+---------------+
1 row in set (0.04 sec)

といったことも自由にできてしまいます。
sql-databases-list

root のパスワード

Cloud SQL には root 以外にも mysql.sys、cloudsqlimport、cloudsqlreplica といったデフォルトで用意/予約されているアカウントがあります。
後者3点については Cloud SQL 内部で利用される管理用アカウントであり、変更や削除、ログインといったことはできません。
しかし、 root にはパスワード無しでアクセス可能 なため、セキュリティ上の脅威になる上、データの改ざんや損失リスクの可能性もあります。

どうすればリスクを緩和できるのか

外部IPアドレスを付与しない

種別 MySQL PostgreSQL SQL Server
対応状況

Cloud SQL のプライベート サービス アクセスを設定することで、Cloud SQL インスタンスに外部IPアドレスを付与せず、内部IPアドレスのみを付与することができます。

Cloud SQL インスタンスに内部IPアドレスのみを付与するには、プライベート サービス アクセスを設定します。
このとき、Cloud SQLインスタンスがデプロイされ管理されている Google 管理のプロジェクトに存在するVPCネットワークと、ユーザが指定する任意のVPCネットワークとを内部的にVPCピアリングで接続します。
これにより、接続されたVPCネットワークからのみアクセスできるようになります。
(この操作は1回限りの操作ですので、複数回行うものではありません)

プライベート IP の使用方法の詳細

注意点

よくあるご質問として「Cloud SQL インスタンスのIPアドレスが設定したIPアドレス範囲から払い出されていない!」というものをいただきます。
これは少しややこしいかもしれませんが、「設定したIPアドレス範囲からインスタンスIPアドレスが設定される」のではなく、「Cloud SQL インスタンスにアクセスを許可するIPアドレス範囲を指定する」という解釈が正しいものになります。

例)

  • 192.168.1.0/24 を設定 ➜ 192.168.1.0/24 からのアクセスが許可される(インスタンスのIPアドレスは異なるIPアドレスが付与される)
  • 10.1.0.0/16 を設定 ➜ 10.1.0.0/16 からのアクセスが許可される(インスタンスのIPアドレスは異なるIPアドレスが付与される)

外部IPアドレスを付与しなければならないケース

種別 MySQL PostgreSQL SQL Server
対応状況

要件として外部IPアドレスを付与しなければならない(外部IPアドレスを使用してアクセスしなければならない)ケースの場合、承認済みネットワークを構成してアクセスを許可するIPアドレス範囲を制限することができます。

承認済みネットワークを使用して承認する

Firewallルールによる制御

種別 MySQL PostgreSQL SQL Server
対応状況

プライベートサービスアクセスによる内部IPアドレスに限定した通信であっても、共有VPCなどで複数の Google Cloud プロジェクトにサブネットを払い出している場合もあるかと思います。
サブネットAからはアクセスを許可したいが、サブネットBからはアクセスを拒否したい場合などを例にあげます。

この場合、共有VPC と Cloud SQL とを接続しているため、共有VPC から払い出されたサブネット全てがアクセス可能になってしまいます。
特定のサブネットからのみアクセスを許可するようにするためには、Firewall ルールを設ける必要があります。
sql-access-xpn-fw

VPC Service Controls による制御

種別 MySQL PostgreSQL SQL Server
対応状況

VPC SC は Cloud SQL に対応しているものの、Cloud SQL Admin APIのみをサポートしている点に注意してください。

サービス境界は、Cloud SQL Admin API のみを保護します。
Cloud SQL インスタンスへの IP ベースのデータアクセスは保護されません。

サポートされているプロダクトと制限事項(sqladmin.googleapis.com)

管理アカウントとユーザアカウントを適切に設ける

種別 MySQL PostgreSQL SQL Server
対応状況

公式ドキュメントとして案内されているベストプラクティスに従い、以下の点を実施するだけでも十分効果はあります。

  • root ユーザのパスワードを強力なものに変更する
  • 特定の IP アドレス範囲やホストからの接続のみ承認するよう変更する

本番環境用の Cloud SQL for MySQL の設定

また、デフォルトでは root ユーザーパスワードは設定されていませんので、強力なパスワードを設定することを推奨します。
sql-users-list
user-passwd-policy

ユーザーのパスワードを変更する

IAM データベース認証を設定する

Cloud SQL IAM 認証を使用してデータベースに対するアクセス制限を設けることが可能です。

従来のユーザー名とパスワードを使用してアカウントアクセスを管理する組み込み認証に対し、
アクセストークンと IAM を使用してアカウントアクセスを管理する仕組みが Cloud SQL IAM 認証です。
これにより、Cloud SQL に接続する サービスアカウント ないしは Googleアカウント に対して、IAM による一元管理されたアクセス制限を設けることができます。

Cloud SQL IAM 認証についても IAM のベストプラクティスと同様に、必要最低限の IAM 権限を最小権限の原則に基づき付与することを推奨します。

Cloud SQL IAM データベース認証

IAM データベース認証のインスタンス構成

注意点

上記で説明した点については、Cloud Console のトップページにある推奨事項に表示されません。
そのため、Security Command Center やその他アーキテクチャレベルでの脆弱性などを検知できる外部ツールなどで確認するか、管理者による確認を行ってください。
recommendations

まとめ

この章では以下のことについて、学んでいきました。

  1. Cloud SQL を使う時に気をつけるべきポイント
  2. どのようにして脅威からシステムを保護するか

特に、意外と怠りがちなユーザーパスワードポリシーや内部IPアドレスに限定したアクセスなどはハードルも高くないと思われます。
既に構築されたシステムや、これから展開予定のシステムを今一度見直し、より安全なものにする一助になればと思います。

参考情報

一般的に推奨される利用方法

Cloud SQL for SQL Server: データベース管理のベスト プラクティス

Cloud SQL IAM データベース認証

IAM データベース認証のインスタンス構成

関連記事

Day1(前回) Compute Engine への攻撃

次回
Coming Soon...

Discussion