AWS × 形式手法で人知を超えたセキュリティを手に入れろ #jd2018_c #jawsdays / JAWS DAYS 2018

AWS × 形式手法で人知を超えたセキュリティを手に入れろ #jd2018_c #jawsdays / JAWS DAYS 2018

JAWS DAYS 2018 で使用したスライドです。形式手法の一種、モデル検査器 Alloy を用いて AWS の IAM 設定を検証する手法について解説しました。公式が提供する IAM Policy Simulator でできるのはすでに存在するポリシの検証までですが、本手法では一歩進んで設計の段階からツールがサポートします。

講演概要:https://jawsdays2018.jaws-ug.jp/session/1476/
ブログ:http://ccvanishing.hateblo.jp/entry/2018/05/18/205101

332f89cc697355902a817506b6995f2b?s=128

y_taka_23

March 10, 2018
Tweet

Transcript

  1. AWS × 形式手法で 人知を超えたセキュリティを 手に入れろ JAWS DAYS 2018 (2018/03/10) [Security

    Slot] C トラック チェシャ猫 (@y_taka_23)
  2. #jd2018_c Tweet Me!

  3. 目次 ★ IAM 設定の理想と現実 ★ モデル検査器 Alloy 入門 ★ Alloy

    による IAM 検証 #jd2018_c
  4. IAM Identity and Access Management #jd2018_c

  5. IAM 設定の難しさ ★ 機能そのものの複雑性 ◦ そもそも設定できる項目が多い ◦ 多数の AWS リソースの連携が必要

    ◦ 最小権限の原則から細分化されがち ★ 運用の中でより複雑化 ◦ 設定ミスすると被害が大きい ◦ 既存の Policy に手を出せなくなる #jd2018_c
  6. IAM 設定を補助するツール ★ Policy Validator ◦ 構文的なチェックのみ ★ Visual Editor

    ★ IAM Policy Simulator ◦ 操作主体となる Group や User を選ぶ ◦ 操作対象となる Resource や Action を選ぶ ◦ Allow または Deny を判定してくれる #jd2018_c
  7. #jd2018_c

  8. IAM Policy Simulator の限界 ★ 論理的な不整合が検出できない ◦ 重複や互いに矛盾する Policy の存在

    ★ 具体的な設定は教えてくれない ◦ 結局は経験とカンによる設計に ★ IAM 以外の要素を考慮できない ◦ 例えばセキュリティグループや VPC 設計と合わせて考えたいとき困る #jd2018_c
  9. “ 人間の直感だけでは まともに戦えない世界

  10. 形式手法 Formal Methods #jd2018_c

  11. 形式手法とは ★ システムを数学的対象として記述 ◦ その対象に関する理論を用いて検証 ◦ 選んだ対象によって特性が変わる ★ いわゆるテストと比較すると ◦

    テストケースの漏れが生じない ◦ 実装以前の設計レベルで検査できる ◦ さほど普及しておらず習熟者が少ない #jd2018_c
  12. モデル検査器 Alloy Alloy Model Checker #jd2018_c

  13. Alloy の特徴 ★ 関係論理でシステムを定義 ◦ データモデル的な表現に向く ★ SAT ソルバにより具体例を発見 ◦

    条件を満たす例を自動で全列挙 ◦ コーナーケースも含め機械的に網羅 ★ 発見した具体例を可視化 ◦ 直感的で導入のハードルが下がる #jd2018_c
  14. sig User { policy : Policy } sig Policy {}

    run {} #jd2018_c
  15. #jd2018_c

  16. #jd2018_c

  17. #jd2018_c

  18. システムを関係論理で記述 ★ シグニチャ ◦ 有限集合を表す ◦ さっきの例では User や Policy

    ★ フィールド ◦ シグニチャ上の関係を表す ◦ さっきの例では policy ◦ 実体は部分集合 policy ⊆ User × Policy #jd2018_c
  19. (u0, p0) (u0, p1) (u0, p2) (u1, p0) (u1, p1)

    (u1, p2) (u2, p0) (u2, p1) (u2, p2) User0 User1 User2 Policy0 Policy1 Policy2 #jd2018_c
  20. (u0, p2) (u1, p1) (u2, p0) User0 User1 User2 Policy0

    Policy1 Policy2 #jd2018_c
  21. (u0, p2) (u1, p2) (u2, p1) User0 User1 User2 Policy0

    Policy1 Policy2 #jd2018_c
  22. (u0, p2) (u1, p2) (u2, p2) User0 User1 User2 Policy0

    Policy1 Policy2 #jd2018_c
  23. 関係の多重度 ★ 対応する要素の個数を指定 ◦ one : ちょうど 1 個(デフォルト) ◦

    lone : 0 個または 1 個 ◦ set : 0 個以上 ◦ some : 1 個以上 ◦ no : 0 個 ★ ER 図における 1..* などに相当 #jd2018_c
  24. 二種類の検査モード ★ assert + check ◦ 必ず満たされてほしい条件を与える ◦ 全探索して違反が存在すれば表示 ★

    pred + run ◦ 満たされるかどうか不明な条件を与える ◦ 全探索して条件を満たす例を発見 #jd2018_c
  25. “ 先入観も疲労もない 信頼できるナビゲータ

  26. Alloy による IAM の検証 Beating the IAM Policy Simulator #jd2018_c

  27. Alloy vs IAM Simulator ★ 論理的な不整合が検出できない ◦ ★ 具体的な設定は教えてくれない ◦

    ★ IAM 以外の要素を考慮できない ◦ #jd2018_c
  28. Alloy vs IAM Simulator ★ 論理的な不整合が検出できない ◦ assert + check

    で違反を検出 ★ 具体的な設定は教えてくれない ◦ ★ IAM 以外の要素を考慮できない ◦ #jd2018_c
  29. { “Version”: “2012-10-17” “Statement”: [ { “Effect”: “Allow”, “Action”: [“ec2:*”],

    “Resource”: [“*”] }, ] } { “Version”: “2012-10-17” “Statement”: [ { “Effect”: “Deny”, “Action”: [“ec2:*”], “Resource”: [“*”] } ] } #jd2018_c
  30. { “Version”: “2012-10-17” “Statement”: [ { “Effect”: “Allow”, “Action”: [“ec2:*”],

    “Resource”: [“*”] }, ] } { “Version”: “2012-10-17” “Statement”: [ { “Effect”: “Deny”, “Action”: [“ec2:*”], “Resource”: [“*”] } ] } 同時に設定されると無意味 #jd2018_c
  31. assert noConflictWithAllowAndDeny { no u : User { some p1,

    p2 : u.policy, s1 : p1.statement, s2 : p2.statement { s1.effect = Allow s2.effect = Deny some (s1.resource & s2.resource) some (s1.action & s2.action) } } } fact singleStatement { all p : Policy | lone p.statement } check noConfictWithAllowAndDeny #jd2018_c
  32. assert noConflictWithAllowAndDeny { no u : User { some p1,

    p2 : u.policy, s1 : p1.statement, s2 : p2.statement { s1.effect = Allow s2.effect = Deny some (s1.resource & s2.resource) some (s1.action & s2.action) } } } fact singleStatement { all p : Policy | lone p.statement } check noConfictWithAllowAndDeny s1 と s2 がバッティング #jd2018_c
  33. assert noConflictWithAllowAndDeny { no u : User { some p1,

    p2 : u.policy, s1 : p1.statement, s2 : p2.statement { s1.effect = Allow s2.effect = Deny some (s1.resource & s2.resource) some (s1.action & s2.action) } } } fact singleStatement { all p : Policy | lone p.statement } check noConfictWithAllowAndDeny Policy ごとに Statement が高々1 つなら大丈夫 (?) #jd2018_c
  34. #jd2018_c Alloy が発見した Inter-Policy Conflict の例

  35. Alloy vs IAM Simulator ★ 論理的な不整合が検出できない ◦ assert + check

    で違反を検出 ★ 具体的な設定は教えてくれない ◦ ★ IAM 以外の要素を考慮できない ◦ #jd2018_c
  36. Alloy vs IAM Simulator ★ 論理的な不整合が検出できない ◦ assert + check

    で違反を検出 ★ 具体的な設定は教えてくれない ◦ pred + run で仕様から実装を発見 ★ IAM 以外の要素を考慮できない ◦ #jd2018_c
  37. sig Statement { effect : one Effect, resource : set

    Resource, action : set Action, notAction : set Action } fact exclusiveAction { all s : Statement { some s.action => no s.notAction some s.notAction => no s.action } } pred deniedByStatement(s : Statement, r : Resource, a : Action) { s.effect = Deny r in s.resource a in s.action or (some s.notAction and a not in s.notAction) } #jd2018_c
  38. sig Statement { effect : one Effect, resource : set

    Resource, action : set Action, notAction : set Action } fact exclusiveAction { all s : Statement { some s.action => no s.notAction some s.notAction => no s.action } } pred deniedByStatement(s : Statement, r : Resource, a : Action) { s.effect = Deny r in s.resource a in s.action or (some s.notAction and a not in s.notAction) } 除外アクション #jd2018_c
  39. sig Statement { effect : one Effect, resource : set

    Resource, action : set Action, notAction : set Action } fact exclusiveAction { all s : Statement { some s.action => no s.notAction some s.notAction => no s.action } } pred deniedByStatement(s : Statement, r : Resource, a : Action) { s.effect = Deny r in s.resource a in s.action or (some s.notAction and a not in s.notAction) } 除外アクションが指定されているが a は該当せず #jd2018_c
  40. pred allowedByStatement(s : Statement, ...) {...} pred deniedByPolicy(p : Policy,

    ...) {...} pred allowedByPolicy(p : Policy, ...) {...} pred allowed(u : User, r : Resource, a : Action) { no p : u.policy | deniedByPolicy[p, r, a] some p : u.policy | allowedByPolicy[p, r, a] } pred requirement { some u : User, r : Resource, a : Action { allowed[u, r, a] } } run requirement #jd2018_c
  41. pred allowedByStatement(s : Statement, ...) {...} pred deniedByPolicy(p : Policy,

    ...) {...} pred allowedByPolicy(p : Policy, ...) {...} pred allowed(u : User, r : Resource, a : Action) { no p : u.policy | deniedByPolicy[p, r, a] some p : u.policy | allowedByPolicy[p, r, a] } pred requirement { some u : User, r : Resource, a : Action { allowed[u, r, a] } } run requirement 禁止する Policy がなく、かつ許可する Policy が存在 #jd2018_c
  42. pred allowedByStatement(s : Statement, ...) {...} pred deniedByPolicy(p : Policy,

    ...) {...} pred allowedByPolicy(p : Policy, ...) {...} pred allowed(u : User, r : Resource, a : Action) { no p : u.policy | deniedByPolicy[p, r, a] some p : u.policy | allowedByPolicy[p, r, a] } pred requirement { some u : User, r : Resource, a : Action { allowed[u, r, a] } } run requirement アクセスが許可される具体例は? #jd2018_c
  43. Alloy が自動で発見した Action 指定を用いるパターン #jd2018_c

  44. Alloy が自動で発見した NotAction 指定を用いるパターン #jd2018_c

  45. Alloy vs IAM Simulator ★ 論理的な不整合が検出できない ◦ assert + check

    で違反を検出 ★ 具体的な設定は教えてくれない ◦ pred + run で仕様から実装を発見 ★ IAM 以外の要素を考慮できない ◦ #jd2018_c
  46. Alloy vs IAM Simulator ★ 論理的な不整合が検出できない ◦ assert + check

    で違反を検出 ★ 具体的な設定は教えてくれない ◦ pred + run で仕様から実装を発見 ★ IAM 以外の要素を考慮できない ◦ サービス単位でモジュール分割 #jd2018_c
  47. module s3 enum Resource { Bucket, Object, ...} enum Action

    { ListBucket, PutObject, GetObject, ...} module ec2 open s3 enum Resource { Instance, SecurityGroup, ...} enum Action { StartInstances, StopInstances, ...} pred accessibleViaEndpoint(i : Instance, b : s3/Bucket) { ... } #jd2018_c
  48. module s3 enum Resource { Bucket, Object, ...} enum Action

    { ListBucket, PutObject, GetObject, ...} module ec2 open s3 enum Resource { Instance, SecurityGroup, ...} enum Action { StartInstances, StopInstances, ...} pred accessibleViaEndpoint(i : Instance, b : s3/Bucket) { ... } S3 用モジュール EC2 用モジュール #jd2018_c
  49. module s3 enum Resource { Bucket, Object, ...} enum Action

    { ListBucket, PutObject, GetObject, ...} module ec2 open s3 enum Resource { Instance, SecurityGroup, ...} enum Action { StartInstances, StopInstances, ...} pred accessibleViaEndpoint(i : Instance, b : s3/Bucket) { ... } モジュールの読み込み #jd2018_c
  50. module s3 enum Resource { Bucket, Object, ...} enum Action

    { ListBucket, PutObject, GetObject, ...} module ec2 open s3 enum Resource { Instance, SecurityGroup, ...} enum Action { StartInstances, StopInstances, ...} pred accessibleViaEndpoint(i : Instance, b : s3/Bucket) { ... } IAM 外、EC2 特有の条件 #jd2018_c
  51. module main open s3 open ec2 open iam one sig

    Binder { res : iam/Resource one -> one (s3/Resource + ec2/Resource) act : iam/Action one -> one (s3/Action + ec2/Action) } pred requirement { some u : iam/User, b : s3/Bucket, i : ec2/Instance { iam/allowed[u, Binder.res.b, Binder.act.s3/GetObject] ec2/accessibleViaEndpoint[i, b] } } #jd2018_c
  52. module main open s3 open ec2 open iam one sig

    Binder { res : iam/Resource one -> one (s3/Resource + ec2/Resource) act : iam/Action one -> one (s3/Action + ec2/Action) } pred requirement { some u : iam/User, b : s3/Bucket, i : ec2/Instance { iam/allowed[u, Binder.res.b, Binder.act.s3/GetObject] ec2/accessibleViaEndpoint[i, b] } } 個別サービス + IAM を読み込み #jd2018_c
  53. module main open s3 open ec2 open iam one sig

    Binder { res : iam/Resource one -> one (s3/Resource + ec2/Resource) act : iam/Action one -> one (s3/Action + ec2/Action) } pred requirement { some u : iam/User, b : s3/Bucket, i : ec2/Instance { iam/allowed[u, Binder.res.b, Binder.act.s3/GetObject] ec2/accessibleViaEndpoint[i, b] } } S3 系リソースと EC2 系リソースの和集合 #jd2018_c
  54. module main open s3 open ec2 open iam one sig

    Binder { res : iam/Resource one -> one (s3/Resource + ec2/Resource) act : iam/Action one -> one (s3/Action + ec2/Action) } pred requirement { some u : iam/User, b : s3/Bucket, i : ec2/Instance { iam/allowed[u, Binder.res.b, Binder.act.s3/GetObject] ec2/accessibleViaEndpoint[i, b] } } IAM 側の (抽象的な) リソースと 1 : 1 対応 #jd2018_c
  55. module main open s3 open ec2 open iam one sig

    Binder { res : iam/Resource one -> one (s3/Resource + ec2/Resource) act : iam/Action one -> one (s3/Action + ec2/Action) } pred requirement { some u : iam/User, b : s3/Bucket, i : ec2/Instance { iam/allowed[u, Binder.res.b, Binder.act.s3/GetObject] ec2/accessibleViaEndpoint[i, b] } } IAM 以外の条件も混ぜて扱える #jd2018_c
  56. Alloy vs IAM Simulator ★ 論理的な不整合が検出できない ◦ assert + check

    で違反を検出 ★ 具体的な設定は教えてくれない ◦ pred + run で仕様から実装を発見 ★ IAM 以外の要素を考慮できない ◦ サービス単位でモジュール分割 #jd2018_c
  57. まとめ Recapture #jd2018_c

  58. まとめ ★ 形式手法とは何か ◦ システムを数学的に記述し検査 ◦ Alloy の場合は関係論理ベース ★ Alloy

    のアドバンテージ ◦ 意図しない設定の不整合を例とともに検出 ◦ 仕様から考えられる実装を発見・列挙 ◦ モジュール化・拡張可能なモデル #jd2018_c
  59. Have a Nice Security! Presented by チェシャ猫 (@y_taka_23) #jd2018_c

  60. Credits Special thanks to all the people who made and

    released these awesome resources for free: ▷ Presentation template by SlidesCarnival ▷ Photographs by Unsplash 60 #jd2018_c