1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AWS S3バケットにCORSを設定する。

Last updated at Posted at 2025-06-30

はじめに

業務にて、AWS S3のバケットに画像を格納しています。
その際に、やり取りをしている外部の有識者から、こんなことを言われました。

「画像取得の処理についてです。対象の画像は様々なオリジンからのアクセスされる可能性があります。対象サーバにてCORS設定の対応をお願いします。」

そもそも、CORSとは何だ?といったことから、S3バケットにCORS設定を行うに当たり、色々調べてみました。間違いなどありましたら、ご指摘ください。

1. CORSとは何か

オリジン間リソース共有(Cross-Origin Resource Sharing)のこと。
HTTPヘッダーベースの仕組みを使用して、あるオリジンで動作しているウェブアプリケーションに、異なるオリジンにある選択されたリソースへのアクセス権を与えるようブラウザに指示するための仕組みです。

セキュリティ上の理由から、ブラウザは、スクリプトによって開始されるオリジン間HTTPリクエストを制限しており、同一オリジンポリシーに従います。
ブラウザで動作しているアプリケーションが読み込まれたのと同じオリジンに対してのみリソースのリクエストを行うことが可能です。

※下記サイト意訳

うむ、あまりよくわかんないですね。
まずは関連する各用語について、詳しく見ていきます。

2. 各用語について

同一オリジンポリシー(Same-Origin Policy)

ブラウザ上で動作するアプリ(JavaScript)から、サイトをまたがったアクセスを禁止するセキュリティ上の制限のことを指します。

「オリジン」や「同一オリジン」についても見ていきましょう。

オリジンと同一オリジン

オリジンとは、下記3要素の組み合わせのことを指します。
①プロトコル
 例:http or https
②ホスト
 例:example.com
③ポート
 例::80,:443,:8080

そのうえで、同一オリジンである条件は、下記3点をすべて満たす場合のみです。

  1. URLのホストが一致している
  2. スキーム(プロトコル)が一致している
  3. ポート番号が一致している

例えば、下記AとBは③ポート番号が一致していないため、同一オリジンとは言えません。
A. https://example.com:443
B. https://example.com:8080

対して、下記はパスが異なりますが、①プロトコル②ホスト③ポートのすべてが一致しているため、オリジンは同一と捉えます。
C. https://example.com/pages1
D. https://example.com/pages2

「オリジン」と「同一オリジン」についてはこんなところでしょうか。
同一オリジンポリシーに話を戻します。

そもそもですが、なぜブラウザには同一オリジンポリシーが設定されているのでしょうか。

3. 同一オリジンがブラウザに設定されている目的

ブラウザはどのWebアプリにおいてもJavaScriptが実行できます。
そのうえで、JavaScriptはCookieやLocalStorageにもアクセス可能です。

CookieやLocalStorageなどには、重要な情報も多いため、JavaScriptのアクセス権限を制限しない場合には、他Webアプリが情報を読み取るスクリプトを埋め込むことが可能となり、機密情報の漏洩に繋がります。

これらを防ぐため、ブラウザには同一オリジンポリシーが設定されています。

では、どういった攻撃に対し、同一オリジンポリシーが有効か、具体例を見ていきましょう。

受動的攻撃への対策

同一オリジンポリシーは、受動的攻撃への対策として有効です。
受動的攻撃とは、罠を利用してユーザーに攻撃コードを実行させる攻撃のことを指します。
例として挙げられるものは、XSSやCSRFなどがあります。

では、同一オリジンポリシーがなぜ有効になるか、具体例を挙げてみます。

ユーザーの機密情報を保護する

ブラウザ上のCookieなどに保存されているユーザー個人の情報や、ログイン情報等を攻撃者に盗まれないようすることが可能です。

参考として、図を記載しておきます。
image.png

XSS攻撃の防止

同一オリジンポリシーは、一部のXSS攻撃にも有効となります。
 ※XSS:Webサイトの脆弱性を利用して、攻撃者が悪意あるスクリプトを埋め込み、ユーザーのブラウザ上で実行させる攻撃

利用者がブラウザ上でM銀行と、XSS脆弱性を持つZサイトを別タブとして開いているケースを考えてみます。

  1. 攻撃者はXSS脆弱性があるZサイトに悪意あるスクリプトを埋め込む
  2. Aさんは、ブラウザの別タブでM銀行とXSS脆弱性のあるZサイトを閲覧している
  3. 攻撃者は、Zサイトを閲覧しているAさんが別タブとして開いているM銀行の情報へアクセスを試行し、M銀行のデータを抜き取ろうとする

上記のケースで、同一オリジンポリシーが有効になります。

上記の場合では、同一オリジンポリシーにより、攻撃者はM銀行のAさんの利用者情報にアクセスすることができず、データを盗むことができません。

参考として、図を記載しておきます。
image.png

同一オリジンポリシーが有効とならないケース

XSS攻撃の防止の冒頭にて、同一オリジンポリシーは一部のXSSに有効と記載しました。

上述のケースの場合では、M銀行に脆弱性が存在する場合において、M銀行の利用者情報はXSSにより攻撃者に抜き取られることがあり得ます。これは、同一オリジン内で、XSSが実行されるためです。

4. CORSの必要性

上述のような理由により、ブラウザには同一オリジンポリシーが設定されていることがわかりました。

ただ、信頼関係ができているサイト同士でデータのやり取りを実施したい際には、同一オリジンポリシーの制限があるため実行できません。

そこで「データのアクセスを許可できるWebサイトに対して、同一オリジンを超えたアクセスを可能とする仕組み」として策定されたのが、CORSです。

5. CORS設定時の挙動

CORS設定に関するリクエストには、単純リクエストとプリフライトリクエストが存在します。
それぞれがどんなリクエストなのか、各々の挙動についてみていきます。

単純リクエスト

単純リクエストは、下記の条件をすべて満たすHTTPリクエストです。

  1. HTTPメソッドが下記のいずれか
    GET
    HEAD
    POST
  2. HTTPヘッダが下記の範囲内であること
    Accept
    Accept-Language
    Content-Language
    Range
    Content-Type(ただし、値は application/x-www-form-urlencoded multipart/form-data text/plain のみであること)
  3. リクエストに ReadableStream オブジェクトが使用されていないこと。
  4. XMLHttpRequestの場合、オブジェクト.upload.addEventListener()が使用されていない

上記をすべて満たす場合のリクエストは、単純リクエストと呼ばれます。

単純リクエストにおけるCORS設定時のフロー

単純リクエストにおいては、ブラウザは下記のような挙動を行います。

  1. クライアント(利用者)は、https://aaa.com へアクセス

  2. サーバ aaa.com はJavaScriptを含めたレスポンスを返す

  3. ブラウザは追加コンテンツを取得するため、https://bbb.com へアクセス
    → JSの指示により、ブラウザが通信を行う。
    → ブラウザは。aaa.com から呼び出されていることを伝えるために、Originヘッダを自動で付与

    GET /data HTTP/1.1
    Host: bbb.com
    Origin: https://aaa.com
    
  4. bbb.com は、Access-Control-Allow-Originを付与してレスポンスを返す
    → ブラウザは aaa.com へアクセスが可能と判断
    → 結果として、JSがレスポンスデータにアクセスが可能となる。

    HTTP/1.1 200 OK
    Content-Type: application/json
    Access-Control-Allow-Origin: https://aaa.com
    

image.png

プリフライトリクエスト

プリフライトリクエストとは、ブラウザが自身と異なるサーバにリクエストをする際に、事前にブラウザから送信されるHTTPリクエストのことを指します。

条件としては、単純リクエストではない場合はほぼプリフライトリクエストと捉えてよさそうです。

プリフライトリクエストは、サーバが対象のリクエストを受け付ける許可を出しているかを確認するために送信されます。

プリフライトリクエストにおけるCORS設定時のフロー

プリフライトリクエストにおいては、ブラウザは下記のような挙動を行います。

  1. クライアント(利用者)は、https://aaa.com へアクセス
  2. サーバ aaa.com はJavaScriptを含めたレスポンスを返す
  3. ブラウザは https://bbb.com へプリフライトリクエスト(OPTIONS)を送信
    →JSが PUTapplication/json を指定しているため、ブラウザが自動で事前確認(プリフライトリクエスト)を実施
    →このリクエストは OPTIONS メソッドで送信され、下記のようなヘッダを含む
    OPTIONS /api/data HTTP/1.1
    Origin: https://aaa.com
    Access-Control-Request-Method: PUT
    Access-Control-Request-Headers: Content-Type
    
  4. サーバ bbb.com は条件を受け入れるかを判断し、許可する場合はCORSヘッダを返す
    →応答がない場合は、ブラウザは本リクエストを送信せず中断する
    HTTP/1.1 204 No Content
    Access-Control-Allow-Origin: https://aaa.com
    Access-Control-Allow-Methods: PUT, GET, POST
    Access-Control-Allow-Headers: Content-Type
    
  5. ブラウザは確認が通ったため、本リクエストを https://bbb.com に送信
    PUT /api/data HTTP/1.1
    Origin: https://aaa.com
    Content-Type: application/json
    
  6. bbb.com は、Access-Control-Allow-Origin を付与してレスポンスを返す
    → ブラウザは aaa.com へアクセスが可能と判断
    → 結果として、JSがレスポンスデータにアクセスが可能となる。
    HTTP/1.1 200 OK
    Content-Type: application/json
    Access-Control-Allow-Origin: https://aaa.com
    

image.png

6. AWS S3バケットへのCORS設定

話を大きく戻します。
今回はAWSのS3バケットへCORSを設定する話でした。
AWSのS3バケットにもCORSは設定できます。

S3への設定を行うことで、S3バケットへのアクセス元ブラウザに対し、CORS設定を適用するように制限を掛け、該当のファイルに対し、アクセスを可能となります。

AWS管理画面(コンソール)から設定

  1. S3バケットにアクセス
    • AWSコンソールにログイン → S3 → 対象のバケットを選択
  2. 「プロパティ」タブ → 「バケットポリシー」ではなく「CORSの設定」を探す
    • メニュー内の「アクセス許可」タブを開く
  3. 下の方にある「CORSの設定」をクリック

最低限必要なCORS設定は以下の通りです。

[
    {
        "AllowedHeaders": [
            "*"
        ],
        "AllowedMethods": [
            "GET",
            "PUT",
            "POST",
            "DELETE"
        ],
        "AllowedOrigins": [
            "*"
        ],
        "ExposeHeaders": [
            "Access-Control-Allow-Origin"
        ]
    }
]

各記載について、確認していきます。

AllowedHeaders

AllowedHeaders は、クライアントからサーバーへ送信するHTTPリクエストヘッダーのうち、許可するものを指定します。
* を記載する場合は、どんなヘッダーでも許可します。

AllowedMethods

AllowedMethods は、ブラウザが、どのHTTPメソッドを用いてS3バケットにアクセスできるかを定義します。よく記載するのは下記でしょうか。

メソッド 用途 S3での利用例
GET リソースの取得 ファイルのダウンロード・表示
PUT リソースの新規作成または上書き ファイルのアップロード
POST リソースの作成やフォーム送信 マルチパートアップロード
DELETE リソースの削除 ファイルの削除

AllowedOrigins

AllowedOrigins は、クロスオリジンからの読出しを許可するための仕掛けで、この欄に ""(ダブルクォーテーション)で囲み、許可するオリジンを記載します。
* を記載する場合は、すべてのオリジンからのアクセスを許可します。

ExposeHeaders

ブラウザにアクセス可能なレスポンスヘッダーは、標準的なヘッダーからしか直接アクセスできません。
標準的なヘッダー以外から値を取得したい際に、 ExposeHeaders に指定します。

これらを記載することで、S3バケットにCORSを設定することができます。

おわりに

今回はCORSについてと、S3バケットにCORS設定を行うために必要なことをまとめました。
CORSについては初めて知ることも多く、個人的な知見となりました。
また、SOPの理解度や各用語についても理解を深めることができたと実感しています。

参考

1
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?