P.85~86「CORS」について

192 views
Skip to first unread message

OK

unread,
Oct 27, 2024, 12:55:53 PM10/27/24
to 「体系的に学ぶ 安全なWebアプリケーションの作り方」サポートML
徳丸様

お世話になっております。
CORSの動作について、細かい内容になりますがご教示頂けませんでしょうか。

検証環境の「33-001 :シンプルなリクエスト(CORS非対応)」の動作を図解する中で不明点が出てきましたので、【質問①】および【質問②】にご回答頂けませんでしょうか。

何卒よろしくお願い致します。
CORS_シンプルなリクエスト非対応2.png
CORS_シンプルなリクエスト非対応1.png

徳丸浩

unread,
Oct 27, 2024, 8:15:28 PM10/27/24
to wasbook...@googlegroups.com
徳丸です。こんにちは。

ご質問の回答は以下のとおりです。

① BからのリクエストであることはOriginヘッダで判断します
② Originヘッダを設定するのはブラウザです



2024年10月28日(月) 1:55 OK <cs00...@gmail.com>:
--
このメールは Google グループのグループ「「体系的に学ぶ 安全なWebアプリケーションの作り方」サポートML」に登録しているユーザーに送られています。
このグループから退会し、グループからのメールの配信を停止するには wasbook-reade...@googlegroups.com にメールを送信してください。
このディスカッションを表示するには、https://groups.google.com/d/msgid/wasbook-readers/04992b62-f39a-489a-8ce9-c0529dba5c13n%40googlegroups.com にアクセスしてください。


--

OK

unread,
Oct 28, 2024, 12:23:51 PM10/28/24
to 「体系的に学ぶ 安全なWebアプリケーションの作り方」サポートML
徳丸様、いつもお世話になっております。
ご確認、ご回答ありがとうございます。

CORSだけに留まらずhttpの基本動作という点でも明らかにしておきたいため、細かい内容になりますが引き続きご回答頂けますでしょうか。

単語の使い方や意味が通じていない文章についてもご指摘頂けますと嬉しいです。

2024年10月28日月曜日 9:15:28 UTC+9 徳丸浩:
6.png
5.png
3.png
4.png
2.png
1.png

徳丸浩

unread,
Oct 29, 2024, 4:23:32 AM10/29/24
to wasbook...@googlegroups.com
徳丸です。こんにちは。
細かいところですが、ご質問いただいている内容は「HTTPの基本」ではありません。これはブラウザ内のセキュリティ機能の内容です。以下、回答です。

質問①の回答(画像:1.png)
③の指すものが明確ではありませんが、機能の名前としては当然XMLHttpRequestですが、この関数やfetchという関数を使うことを総称してAJAX(エイジャックス)と呼ぶこともあります。AJAXは若干古い言い方です。単にAPI呼び出しという場合もあります。

画像3.pngの「しかし、AccessControlAllowOriginヘッダが未設定なので、別Originからのhttpリクエストを拒否する」という説明は間違いです。CORS未対応のAPIはOriginヘッダを確認しないので、応答は返してしまいます。その応答をJavaScript側で受け取れないようにするのがCORSの基本的な考え方です。

同様に、⑥の「httpリクエストのOriginヘッダを確認し、別オリジンからのリクエストと判断」は、API側の望ましい対応ではありますが、CORS未対応のAPIでは、これは実装されていないので、勝手にはそうなりません。CORSは、そのような古いAPIでも、情報漏洩を防ぐための仕組みです。

4.pngの「別Originからのhttpリクエストを拒否する内容を含む(と思われる)httpレスポンスを返す」も間違いです。それを判断するのは、レスポンスを受け取ったブラウザ側です。APIサーバーは、普通に情報を返しています。

質問②の回答(画像:5.png)
はい、それで正しいです。


質問③の回答
それはありません。前述のように、APIサーバーはリクエストを拒否していないからです。


質問④の回答
基本的にはそうですね。JavaScript側で例外処理を実装していれば、そちらでも受け取れると思います。



2024年10月29日(火) 1:23 OK <cs00...@gmail.com>:
このディスカッションを表示するには、https://groups.google.com/d/msgid/wasbook-readers/fc5924a4-6dc3-47d1-bd97-154fb4839176n%40googlegroups.com にアクセスしてください。


--

OK

unread,
Oct 29, 2024, 2:08:45 PM10/29/24
to 「体系的に学ぶ 安全なWebアプリケーションの作り方」サポートML
徳丸様、いつもお世話になっております。
ご確認、ご回答ありがとうございます。
大変勉強になります。

引き続きご回答頂けますでしょうか。
今後、この内容をもとにCORS対応の動作についても整理したいと考えます。

よろしくお願い致します。

2024年10月29日火曜日 17:23:32 UTC+9 徳丸浩:
3.png
2.png
1.png

徳丸浩

unread,
Oct 29, 2024, 7:38:58 PM10/29/24
to wasbook...@googlegroups.com
徳丸です。こんにちは
以下回答です。

質問①の回答

それであっています

質問②の回答

⑥のHTTPレスポンスをブラウザが受け取った後です





2024年10月30日(水) 3:08 OK <cs00...@gmail.com>:
このディスカッションを表示するには、https://groups.google.com/d/msgid/wasbook-readers/dbd59fe2-eb9b-485d-8e1d-2bb5d44ca9ebn%40googlegroups.com にアクセスしてください。


--

OK

unread,
Oct 29, 2024, 11:47:21 PM10/29/24
to 「体系的に学ぶ 安全なWebアプリケーションの作り方」サポートML
徳丸様、いつもお世話になっております。
ご確認、ご回答ありがとうございます。
下記のご回答についてですが、、
===ここから===
質問②の回答
⑥のHTTPレスポンスをブラウザが受け取った後です
===ここまで===

Bで動作しているHTMLファイル(ブラウザで「送信しました」を表示させる)のhttpレスポンスは、①〜⑦のどの段階でしょうか?
②と予想します。

引き続き、よろしくお願い致します。
2024年10月30日水曜日 8:38:58 UTC+9 徳丸浩:

徳丸浩

unread,
Oct 30, 2024, 12:44:11 AM10/30/24
to wasbook...@googlegroups.com
徳丸です。こんにちは。

「送信しました」がどのタイミングで表示されるかというご質問ですが、

<body>
<script>
  var req = new XMLHttpRequest();
  req.open('GET', 'http://api.example.net/33/33-002.php');  // ①APIへのリクエスト設定
  req.onreadystatechange = function() {
      if (req.readyState == 4 && req.status == 200) {  // ②レスポンス受取の処理
        alert(req.responseText);
      }
  };
  req.send(null); // ③ リクエスト送信
</script>
送信しました <!-- ④ HTML表示 -->
</body>

このHTMLの場合ですと、処理は概ね

①→③→④→②

の順で行われます。すなわち、APIのリクエストを送信開始した直後に「送信しました」が表示されます。
この段階では通常APIからのレスポンスは届いておらず、それを処理する②は、レスポンスが届いてから開始されます。このような処理を「非同期処理」と呼び、JavaScriptの特徴的な処理になります。
詳しくはJavaScriptの適当な参考書をお読みください。




2024年10月30日(水) 12:47 OK <cs00...@gmail.com>:
このディスカッションを表示するには、https://groups.google.com/d/msgid/wasbook-readers/3941d6a8-471d-4ff7-8412-4bb1cc3083e0n%40googlegroups.com にアクセスしてください。


--

OK

unread,
Oct 30, 2024, 2:05:01 PM10/30/24
to 「体系的に学ぶ 安全なWebアプリケーションの作り方」サポートML
徳丸様、いつもお世話になっております。
ご確認、ご回答ありがとうございます。
詳しいご説明もありがとうございます。

CORS非対応時の動作については添付の「1~4.png」にて洗い出せたと考えます。
この内容を基に、「5~7.png」にてCORS対応時の動作も図解してみましたので、認識齟齬等ございましたらご指摘頂けませんでしょうか。

OriginヘッダとAccessControlAllowOriginヘッダの比較について、不安な部分を黄色の吹き出しにしております。
引き続きご回答よろしくお願い致します。

下記を参考にしました。
H31 春 安全確保支援士 午後1 問1の表1
https://www.sc-siken.com/pdf/31_haru/pm1_1.pdf

2024年10月30日水曜日 13:44:11 UTC+9 徳丸浩:
1.png
2.png
4.png
7.png
3.png
5.png
6.png

徳丸浩

unread,
Oct 30, 2024, 7:28:25 PM10/30/24
to wasbook...@googlegroups.com
徳丸です。こんにちは
大変熱心に図解を書いておられますが、これは個人の勉強のためにやっているのでしょうか? それとも、どこかで発表する目的で書いておられるのでしょうか?

3.png
⑥のHTTPリクエストは「送信しました」よりも前だと思います。
scriptタグが「表示しました」より前に置かれているからです。

6.png

吹き出し httpリクエストのOriginヘッダと自身のACAOヘッダの比較まではやらない

ここは表現がおかしくて、API側に「アクセスを許可するオリジン」というものがあり、

・Originヘッダが「アクセスを許可するオリジン」であることの確認…やったほうがよいが必須とまでは言えずこの例ではやっていない
・ACAOヘッダに「アクセスを許可するオリジン」をセットする…必須なのでこの例でもやっている


⑦CORS対応時はhttpリクエストのOriginヘッダを確認する・・・ことが望ましいが、この例ではやっていない


7.png
httpレスポンスヘッダのOriginヘッダとACAOヘッダを比較して…

httpレスポンスヘッダにOriginヘッダはないです。リクエストヘッダです。
それはそれとして、Originヘッダと比較しているというのは少し違っていて、Bのオリジン(http://exmaple.jp)と比較ですね。Originヘッダにもhttp://example.jpがセットされるので結果としては同じ文字列ですが、基準とするのはOriginヘッダではなくBのオリジンです。



2024年10月31日(木) 3:05 OK <cs00...@gmail.com>:
このディスカッションを表示するには、https://groups.google.com/d/msgid/wasbook-readers/44ba5e57-5e49-4e93-b162-c271bf1ad7e1n%40googlegroups.com にアクセスしてください。


--

OK

unread,
Oct 31, 2024, 4:12:45 AM10/31/24
to 「体系的に学ぶ 安全なWebアプリケーションの作り方」サポートML
徳丸様、いつもお世話になっております。
ご確認、ご回答ありがとうございます。
個人の勉強のために図解しております。

>3.png
>⑥のHTTPリクエストは「送信しました」よりも前だと思います。
→下記プログラムは⑥httpリクエストのことだったのですね。
req.send(null); // ③ リクエスト送信

③XMLHttpRequestのことと勘違いしておりました。

>ここは表現がおかしくて、API側に
>「アクセスを許可するオリジン」というものがあり、
→API(33-002.php)に書かれている「header(ACAO:http://example.jp)」のことでしょうか?

>・ACAOヘッダに「アクセスを許可する
>オリジン」をセットする…必須なので
>この例でもやっている
→私がお送りした「7.png」の「⑧httpレスポンスにACAOヘッダを設定する」がこれに当たると認識してますが合ってますでしょうか?

>7.png
>httpレスポンスヘッダのOriginヘッダと
>ACAOヘッダを比較して…
→この部分もまだ理解できてないようです。
httpレスポンスはoirginヘッダを持たないと理解してもう少し考えてみます。

2024年10月31日木曜日 8:28:25 UTC+9 徳丸浩:

徳丸浩

unread,
Oct 31, 2024, 7:39:14 PM10/31/24
to wasbook...@googlegroups.com
徳丸です。こんにちは。


>>「アクセスを許可するオリジン」というものがあり、
> →API(33-002.php)に書かれている「header(ACAO:http://example.jp)」のことでしょうか?

違います。
「アクセスを許可するオリジン」というのは、仕様ないし設計の話です。仕様や設計についてはわかりますか?

プログラムを作成する前には、「こういうものを作ろう」という「仕様」を決め、「こういう風に作ろう」という「設計」を行います。仕様や設計はプログラムではなく、仕様書や設計書等の文書の形にまとめることが一般的ですが、正式な書類でなくても、slcakのやりとりや、ソースコードのコメント等に書かれている可能性もあります。いずれにしても、ソースコード上のプログラムではありません。

api.example.net はAPIを提供しますが、どこから呼ばれるかについては「仕様」や「設計」があります。書籍の方では、仕様や設計とは明示されていませんが、図3-34に、api.example.netexample.jp が配置され、example.jpapi.example.netを呼び出しています。この図から、api.example.netexample.jpから呼ばれることを許可していることがわかります。これは「仕様」です。

すなわち、この「仕様」から、api.example.netが「アクセスを許可するオリジン」はexample.jpであることが分かります。

そして、この「仕様」を下に、以下のプログラムを記述するのです。仕様や設計が元となる基準、プログラム内容はその基準に従って書いたものです。

header('AccessControlAllowOrigin: http://example.jp');



>>・ACAOヘッダに「アクセスを許可する
>>オリジン」をセットする…必須なので
>>この例でもやっている>
→私がお送りした「7.png」の「⑧httpレスポンスにACAOヘッダを設定する」がこれに当たると認識してますが合ってますでしょうか?

あっています。

> →この部分もまだ理解できてないようです。
> httpレスポンスはoirginヘッダを持たないと理解してもう少し考えてみます。

HTTPリクエストはブラウザからサーバーへの通信です。ブラウザはWebページ(http://example.jp/33-001.html)のオリジン(http://example.jp)を知っていて、設定することができます。これがOriginヘッダです。
一方、HTTPレスポンスはサーバーからブラウザへの通信です。サーバー側は、元々ブラウザのオリジンは知らないですし、一方ブラウザはオリジンがわかっていますから、わざわざサーバーからブラウザにオリジンを伝える必要はありません。意味がないので設定もされません。


2024年10月31日(木) 17:12 OK <cs00...@gmail.com>:
このディスカッションを表示するには、https://groups.google.com/d/msgid/wasbook-readers/86239280-c463-4e05-bf6e-a73f14d29c38n%40googlegroups.com にアクセスしてください。


--

OK

unread,
Nov 1, 2024, 1:21:34 PM11/1/24
to 「体系的に学ぶ 安全なWebアプリケーションの作り方」サポートML
徳丸様、いつもお世話になっております。
ご確認、ご回答ありがとうございます。
詳しい解説もありがとうございます。

何事も仕様→設計→モノの順番で作成されますね。

それぞれのサーバの立場になってみると、httpリクエストとレスポンスでなんの情報をもっていないといけないかが想像できます。
勉強になります。

5.pngと6.pngに質問を記載しましたので、ご回答頂けますでしょうか。

2024年11月1日金曜日 8:39:14 UTC+9 徳丸浩:
4.png
2.png
3.png
5.png
1.png
6.png

徳丸浩

unread,
Nov 1, 2024, 9:08:23 PM11/1/24
to wasbook...@googlegroups.com
徳丸です。こんにちは

質問①の回答
はい、これは無条件にACAOヘッダを設定することで構いません。
複数のオリジンに対応したい場合は、Originヘッダを確認してから当該のヘッダに許可を与える実装も考えられます。
一つのオリジンからのみ使えるAPIであれば、ACAOヘッダは固定で問題ありません。

質問②の回答
はい、そのとおりです。




2024年11月2日(土) 2:21 OK <cs00...@gmail.com>:
このディスカッションを表示するには、https://groups.google.com/d/msgid/wasbook-readers/6ac75d70-f413-4869-b18a-aa0cfda8a12en%40googlegroups.com にアクセスしてください。


--

OK

unread,
Nov 2, 2024, 1:25:53 PM11/2/24
to 「体系的に学ぶ 安全なWebアプリケーションの作り方」サポートML
徳丸様、いつもお世話になっております。
ご確認、ご回答ありがとうございます。

JavaScriptの動作(WEBブラウザとB間の動作)について理解できておりませんが、CORSの動作が洗い出せたと思います。
ありがとうございました!引き続き勉強を進めます。
今後ともよろしくお願い致します。

徳丸様の下記ご回答については安全確保支援士の問題で取り上げられていました。
7.pngと8.pngに概要を載せました。
===ここから===
複数のオリジンに対応したい場合は、Originヘッダを確認してから当該のヘッダに許可を与える実装も考えられます。
===ここまで===

【参考】
H31 春 安全確保支援士 午後1 問1
https://www.sc-siken.com/pdf/31_haru/pm1_1.pdf
6ページ目のD課長の発言

2024年11月2日土曜日 10:08:23 UTC+9 徳丸浩:
5.png
1.png
4.png
2.png
8.png
3.png
6.png
7.png

OK

unread,
Nov 3, 2024, 11:53:26 AM11/3/24
to 「体系的に学ぶ 安全なWebアプリケーションの作り方」サポートML
徳丸様、いつもお世話になっております。
一度クローズしましたが、CORS関連でさらに質問がありますので、
こちらを再開させて頂きます。問題ありましたらご指摘ください。

CORS(プリフライトリクエストなし)の動作について図解致しましたので、
お手数をおかけしますが、ご確認ご回答頂けますでしょうか。
特に、【質問②③】については質問が合っているか不安です。。
スライド内の文章についても認識齟齬ありましたらご指摘ください。

何卒よろしくお願い致します。

2024年11月3日日曜日 2:25:53 UTC+9 OK:
1.png
2.png
3.png
4.png

徳丸浩

unread,
Nov 3, 2024, 8:44:06 PM11/3/24
to wasbook...@googlegroups.com
徳丸です。こんにちは。

◎質問①の回答
プリフライトリクエストの目的は、主にクロスサイト・リクエストフォージェリ対策です。
CORSはややこしい仕組みになっていますが、CORSがややこしい理由の大半は、

・CORS以前のアプリケーションが、ブラウザのCORS対応によって脆弱にならないように

という互換性維持のためにあります。なので、CORSを後から見ると、なぜこうなっているのだろうと疑問に思うことは自然です。
では、なぜプリフライトリクエストがCSRF対策ためかというと、

・CORS以前から元々CSRFの脅威は知られていた
・CORS以前のCSRFはHTMLフォームによるものであり、XMLHttpRequest(XHR)からの攻撃はできないので、想定もされていなかった
・なぜなら、CORS以前は、XMLHttpRequstではクロスオリジンリクエストが送信できなかった
・CORSを考案する上で、以下を検討する必要があった
 ・XHR等がクロスオリジンで送信できるようになったために新たにCSRF対策が必要になる場合を安全にする必要がある
・この目的のためにプリフライトリクエストが考案された

ということで、Content-Type: JSONは、HTMLフォームからは送信できませんが、XHRなら送信できます。このため、「従来はCSRF対策の必要がなかったが、XHR等のクロスオリジン対応によりCSRF対策が必要になった」パターンに該当します。
世の中に既にあるアプリケーションを一斉に対策することは不可能なので、ブラウザ側の安全機構により、このパターンはカバーされることになりました。
詳しくは以下の動画で説明しています。

https://www.youtube.com/watch?v=yBcnonX8Eak


◎質問②の回答
これは、APIが複数のオリジンに対応する場合に必要になります。
以前のやりとりにあった以下のケースですね。


> 徳丸様の下記ご回答については安全確保支援士の問題で取り上げられていました。
> 7.pngと8.pngに概要を載せました。
> ===ここから===
> 複数のオリジンに対応したい場合は、Originヘッダを確認してから当該のヘッダに許可を与える実装も考えられます。
> ===ここまで===


◎質問③の回答
これは基本的にCSRF対策なのですが、それだけであれば、Originヘッダに対してACAOヘッダで応答するだけでも目的は達します。
まず、「単純リクエストの条件から外れるのでプリフライトリクエストを送信する」わけですが、「単純リクエストのどの条件を満たしていないか」を送信することは、仕組みとしては自然なことだと思います。
また、ACAOヘッダだけで済ませられないようにしている理由としては、単純リクエストから外れる理由を示してアプリケーション側に明示的に許可を出させることで、不注意による脆弱性混入を避けることが目的なのだろうと私は解釈しています。


◎その他
細かい表現上の問題になりますが、3,pngの

> PRHに対応できないけどhttpレスポンスを返す

という箇所は、現実には以下だろうと思います。

> PRHに対応していないので単にhttpレスポンスを返す





2024年11月4日(月) 1:53 OK <cs00...@gmail.com>:
このディスカッションを表示するには、https://groups.google.com/d/msgid/wasbook-readers/2338566a-d701-4f8d-b705-c4e39b72e8fdn%40googlegroups.com にアクセスしてください。


--

OK

unread,
Nov 4, 2024, 11:38:03 AM11/4/24
to 「体系的に学ぶ 安全なWebアプリケーションの作り方」サポートML
徳丸様、いつもお世話になっております。
ご確認、ご回答ありがとうございます。
また、動画の共有もありがとうございます。

CORSが普及した長い経緯があるのですね。
ゆくゆくは徳丸様の書籍でCSRFを勉強しますので、その時にCORSとの関連が理解できると思います。
さらにその時に、現在取り組んでいるCORSの図解が役に立つと思います。

4.pngにて質問を1つ追記しております。
お手数をおかけし大変恐縮ですが、何卒ご回答よろしくお願い致します。

2024年11月4日月曜日 10:44:06 UTC+9 徳丸浩:
4.png
1.png
3.png
2.png

徳丸浩

unread,
Nov 5, 2024, 10:34:20 AM11/5/24
to wasbook...@googlegroups.com
徳丸です。こんにちは。

質問①への回答ですが、これは特に深い理由はないと思います。一つでもエラーがあれば、エラーにする条件としては十分なので、最初に確認したエラーだけを表示しているのだと思います。

2024年11月5日(火) 1:38 OK <cs00...@gmail.com>:
このディスカッションを表示するには、https://groups.google.com/d/msgid/wasbook-readers/55181b89-7910-42c8-b92a-71b45944eb00n%40googlegroups.com にアクセスしてください。


--

OK

unread,
Nov 5, 2024, 11:28:48 AM11/5/24
to 「体系的に学ぶ 安全なWebアプリケーションの作り方」サポートML
徳丸様、いつもお世話になっております。
ご確認、ご回答ありがとうございます。

プリフライトリクエスト(あり)について図解致しました。
4.pngに質問①を記載致しましたので、何卒ご回答よろしくお願い致します。

ちなみに、徳丸様は有償のメンバーシップやオンラインサロンは開催していないでしょうか。

2024年11月6日水曜日 0:34:20 UTC+9 徳丸浩:
3.png
4.png
2.png
1.png

徳丸浩

unread,
Nov 5, 2024, 6:11:52 PM11/5/24
to wasbook...@googlegroups.com
徳丸です。こんにちは

質問①に対する回答ですが、まず33-004a.phpのソースコードは以下となります。

<?php
  if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    if($_SERVER['HTTP_ORIGIN'] === 'http://example.jp') {
      header('Access-Control-Allow-Origin: http://example.jp');
      header('Access-Control-Allow-Methods: POST, GET, OPTIONS');
      header('Access-Control-Allow-Headers: Content-Type');
      header('Access-Control-Max-Age: 1728000');
      header('Content-Length: 0');
      header('Content-Type: text/plain');
    } else {
      header('HTTP/1.1 403 Access Forbidden');
      header('Content-Type: text/plain');
      echo "このリクエストは継続できません";
    }
  } else {
    die('Invalid Request');
  }

このスクリプトはプリフライトリクエストの処理しかありません。なので、OPTIONSヘッダの場合は、2行目のif文によりACAOヘッダを返しますが、POSTリクエストの場合はACAOヘッダは返されません。
この処理を加えたのが、33-004b.phpです。POSTリクエストの場合の処理が追加されていることが分かります。

<?php
  if ($_SERVER['REQUEST_METHOD'] === "OPTIONS") {
    if ($_SERVER['HTTP_ORIGIN'] == "http://example.jp") {
      header('Access-Control-Allow-Origin: http://example.jp');
      header('Access-Control-Allow-Methods: POST, GET, OPTIONS');
      header('Access-Control-Allow-Headers: Content-Type');
      header('Access-Control-Max-Age: 10');
      header("Content-Length: 0");
      header("Content-Type: text/plain");
    } else {
      header("HTTP/1.1 403 Access Forbidden");
      header("Content-Type: text/plain");
      echo "このリクエストは継続できません";
    }
  } elseif ($_SERVER['REQUEST_METHOD'] === "POST") {
    header('Content-Type: application/json');
    header('Access-Control-Allow-Origin: http://example.jp');
    header('Access-Control-Max-Age: 10');
    echo json_encode(['zipcode' => '100-0100', 'address' => '東京都大島町']);
  } else {
    die('Invalid Request');
  }


2024年11月6日(水) 1:28 OK <cs00...@gmail.com>:
このディスカッションを表示するには、https://groups.google.com/d/msgid/wasbook-readers/ee04cd91-52d5-447d-938c-857c5f0bdb74n%40googlegroups.com にアクセスしてください。


--

OK

unread,
Nov 6, 2024, 2:24:28 AM11/6/24
to 「体系的に学ぶ 安全なWebアプリケーションの作り方」サポートML

徳丸様、いつもお世話になっております。

ご回答ありがとうございます。


プログラム(33-004a.php)をよく読んでみようと思います。

プログラムを下記文面に示します。


PHRにてOPTIONメソッド使用時

・Originヘッダがhttp://B

→ACAO、 ACAH、ACAMヘッダなどをhttpレスポンスに設定する

・Originヘッダがhttp://Bではない

→「このリクエストは継続できません」をhttpレスポンスに設定する


PHRにてOPTIONメソッド以外使用時

→「die(Invalid Request)」が実行される

→⑦httpリクエストはPOSTメソッド使用なのでdie関数が実行された


「33-004b.php」は上記に、

「httpリクエストにてPOSTメソッド使用時」のelse if文が追加されてるので、

「PHRあり(完成)」ではACAOヘッダがhttpレスポンスで返された、ということですね。


「33-004b.php」のACAMヘッダを見るとGETも許可されているので、

「httpリクエストにてGETメソッド使用時」のelse if文も追加しないと、エラーが発生すると感じました。

今回の例では、httpリクエストでGETメソッドは未使用なので問題なしと理解しております。

2024年11月6日水曜日 8:11:52 UTC+9 徳丸浩:

徳丸浩

unread,
Nov 6, 2024, 6:16:05 AM11/6/24
to wasbook...@googlegroups.com
徳丸です。こんにちは

> 「33-004b.php」のACAMヘッダを見るとGETも許可されているので、
> 「httpリクエストにてGETメソッド使用時」のelse if文も追加しないと、エラーが発生すると感じました。
>  今回の例では、httpリクエストでGETメソッドは未使用なので問題なしと理解しております。

一般に、プリフライトリクエストでは、URL毎に本当に必要最低限のメソッド等の許可を与えることは通常せず、アプリ全体として使用するメソッド等をまとめて許可することが一般的です。その理由は、個別に許可するメソッドを指定してもあまり安全には寄与せず、面倒なだけだからです。

たとえば、この例ではプリフライトリクエストにより、このAPIでは使っていないGETメソッドにも許可を与えていますが、GETメソッドの通信を送っても単にエラーになるだけで実害はありません。

このあたりの勘所がわかるためには、前述のCSRF脆弱性の学習に加えて、現実のアプリケーション開発のやり方も学ぶことでしっくりくると思います。現実のアプリケーション開発では、アプリケーションフレームワーク等が提供するCORS向けライブラリを使うことが大半ですが、通常、アプリケーション全体でCORS設定を共通にすると思います。



2024年11月6日(水) 16:24 OK <cs00...@gmail.com>:
このディスカッションを表示するには、https://groups.google.com/d/msgid/wasbook-readers/6b7fb7c7-42ca-432b-bd57-bfc00b656ac5n%40googlegroups.com にアクセスしてください。


--

OK

unread,
Nov 7, 2024, 2:31:26 AM11/7/24
to 「体系的に学ぶ 安全なWebアプリケーションの作り方」サポートML

徳丸様、いつもお世話になっております。

ご回答ありがとうございます。大変勉強になります。

引き続き勉強を続けます。


CORS成立時のcookie送信についてですが、BにてwithCredentials=trueを記載すると、WEBブラウザからAへの httpリクエストにcookieが付与されます。


このcookieは、Bで発行されたものと認識してよろしいでしょうか?


①が正しい場合、BからWEBブラウザへのXMLHttpRequestの中身をOWASP ZAPで確認する方法はないでしょうか?

WEBブラウザ→AのhttpリクエストとB→WEBブラウザのXMLHttpRequestが、同じcookieを持っているのか確認したいです。
書籍に載っていたブレークポイントが使えますでしょうか?まだ検証前ですので帰宅後に試します。


2024年11月6日水曜日 20:16:05 UTC+9 徳丸浩:

徳丸浩

unread,
Nov 7, 2024, 8:52:36 AM11/7/24
to wasbook...@googlegroups.com
徳丸です。こんにちは。

質問①
> CORS成立時のcookie送信についてですが、BにてwithCredentials=trueを記載すると、WEBブラウザからAへの httpリクエストにcookieが付与されます。
> ①このcookieは、Bで発行されたものと認識してよろしいでしょうか?

違います。Aで発行されたCookieです。Cookieは(domain属性がない場合)Cookieを設定したサイトにのみ付与されます。

質問②
> ①が正しい場合、BからWEBブラウザへのXMLHttpRequestの中身をOWASP ZAPで確認する方法はないでしょうか?

①は正しくないのですが、OWASP ZAPで確認する方法は説明できます。
実習環境から、「8. 33-005b:アクセスカウンタ(Access-Control-Allow-Credentialsあり)」をアクセスして、ZAP下側で33-006b.phpを選択すると、1.png の状態となります。この状態では、まだCookieはセットされていないので、HTTPリクエストヘッダにはCookieはセットされておらず、レスポンスヘッダには以下のSet-Cookieヘッダがあります。

Set-Cookie: PHPSESSID=l70b1hc2vbr7henas61196i8p0; path=/

これは、A(api.example.net)でCookieがセットされたことになります。

次に、ブラウザでリロードボタンを押して、ZAP下側で33-006b.php(2回目)を選択すると、2.png の状態になります。こちらでは、リクエストヘッダに以下のようにCookieヘッダがあります。

Cookie: PHPSESSID=l70b1hc2vbr7henas61196i8p0

すなわち、APIでセットされたCookieがAPIへのリクエストで付与されたことになります。
そもそも、サイトAとサイトBではドメイン名がまったく異なるので、AでセットされたCookieは、Bには付与されません。

ZAPでの確認の仕方は、ZAP下側のHTTPメッセージ(リクエスト+レスポンス)の履歴一覧から、確認したいメッセージを選ぶことで可能です。



2024年11月7日(木) 16:31 OK <cs00...@gmail.com>:
このディスカッションを表示するには、https://groups.google.com/d/msgid/wasbook-readers/6d19d494-ce90-4989-8f3e-8b5d3130c13bn%40googlegroups.com にアクセスしてください。


--
2.png
1.png
Reply all
Reply to author
Forward
0 new messages