API GatewayにおけるセッションIDの固定化攻撃の危険性について

# API GatewayにおけるセッションIDの固定化攻撃の危険性について

この記事は、 [すごくなりたいがくせいぐるーぷ GWアドベントカレンダー](https://gw-advent.9wick.com/calendars/2020/87)最終日の記事です。

## はじめに

CookieのDomain属性について調べていたら、ふと  
「APIGatewayのエンドポイントって`amazonaws.com`のサブドメインだから、Domain属性で`amazonaws.com`指定してCookieセットできんじゃね？」
と思ったので検証してみました。

要するに、都道府県型jpドメイン・地域型jpドメインのクッキーモンスターバグのようなことが`amazonaws.com`でも起こってしまうのではないかということです。
※クッキーモンスターバグについては徳丸先生の[こちらの記事](https://blog.tokumaru.org/2013/03/csrf-and-cookie-monster-bug.html)をご覧ください。

また、[RFC6265の8.6](https://tools.ietf.org/html/rfc6265#section-8.6)を読んでおくと本記事の理解がしやすくなるかもしれません。

誰でも思いつきそうなので既出かもしれないですが、自分の備忘録がてら記事にしておきます。

**※本記事はAPI GatewayにおけるセッションIDの固定化攻撃の危険性について啓蒙することを目的としており、攻撃を助長する意図のものではありません。**
**また、本記事の内容を悪用することは法律で禁止されています。**

## セッションIDの固定化攻撃とは

その名の通りセッションIDを攻撃者のものに固定してしまう攻撃で、セッションハイジャックを引き起こす原因などになります。

詳しくは徳丸先生の[こちらの記事](https://blog.tokumaru.org/2009/01/introduction-to-session-fixation-attack.html)をご覧ください。

## 用意したページ

以下の2つのページを用意しました。

- 罠ページ
- 脆弱性を持ったアプリケーション

ソースコードは[こちらのリポジトリ](https://github.com/shinbunbun/lambdaSessionFixation)においてあります。

また、セッション管理用に`cookieTestUserTable`というdynamoDBのテーブルを用意しました。
API Gatewayでは`REST API`を使用しています。

## 検証

### 環境

- macOS Catalina V.10.15.3
- Google Chrome V.80.0.3987.163

### 検証の手順

以下の手順で検証をします。また、今回は攻撃者としての操作をシークレットウィンドウで、被害者としての動作を通常のウィンドウで行いました。
先頭に`(A)`とついているものが攻撃者の操作、先頭に`(V)`とついているものが被害者の操作です。

1. (A)アプリケーションにアクセスし、正規のセッションID取得する
2. (A)セッションIDはbase64エンコードされているため、`+, /, =`をreplaceで別の文字に置換する
3. (A)自分のセッションIDをパラメータに持たせ、罠ページのURLを作成する
4. (V)罠ページにアクセスする
5. (V)Cookieに攻撃者のセッションIDが挿入される
6. (V)アプリケーションにアクセスすると、攻撃者のセッションとして認識される

### 検証してみる

この解説では、罠ページのURLを`https://trap.execute-api.ap-northeast-1.amazonaws.com`、アプリケーションのURLを`https://app.execute-api.ap-northeast-1.amazonaws.com`とします。

#### 攻撃者の操作

まず、アプリケーションにアクセスします。
そうすると、以下のようなCookieが挿入されます。
domain属性はとくに指定していないため、`https://app.execute-api.ap-northeast-1.amazonaws.com`が入ります。

![スクリーンショット 2020-05-06 17.44.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260292/16c78107-8161-9eec-c331-0d4ff91d1342.png)

次に、Cookieに保存されているsessionIdをコピーして、consoleで以下のコードを実行し、クエリパラメータで使用できない文字列をreplaceします。

```js
console.log('sessionId'.replace(/\+/g, '-').replace(/\//g, '_').replace(/\=/g, '~'));
```

最後に、consoleに出力された文字列をコピーし、以下のようなURLを作成します。

`https://trap.execute-api.ap-northeast-1.amazonaws.com?sessionId=出力された文字列`

#### 被害者の操作

まず、攻撃者の操作で作成したURLにアクセスします。
そうすると、Cookieに罠ページで挿入されたsessionIdが入っていることが確認できます。
domain属性には`amazonaws.com`を指定しています。

![スクリーンショット 2020-05-06 17.53.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260292/d75059ea-3c3c-a804-f3d4-c4af10f01713.png)

次に、アプリケーションのページにアクセスします。
罠ページで挿入されたCookieは、domain属性に`amazonaws.com`が指定されているため、`https://app.execute-api.ap-northeast-1.amazonaws.com`でも読み込まれます。
そうすると、攻撃者のセッションとして認識され、`"Already logged in"`と表示されます。
Cookieを確認すると、罠ページで挿入されたsessionIdが入っていることが確認できます。

![スクリーンショット 2020-05-06 18.06.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260292/07cddc35-1692-0ba7-36e7-680140bfb08b.png)

## 対策

### そもそもCookieでセッション管理をしない

一番手っ取り早い対策はCookieでセッション管理を行わないことです。どうしてもCookieでセッション管理を行う必要がある場合は、EC2などを利用しましょう。

### 独自ドメインを使用する

とはいえ、EC2は高いしなかなか使いたくないですよね。そもそも、API Gatewayのエンドポイントがすべて`amazonaws.com`のサブドメインであるというところがこの問題の原因であるため、独自ドメインを使ってしまえば一発で解決します。

そのほかにも、セッションID固定化攻撃を防いだり難しくしたりする方法はいくつかありますが、上記の二つが一番確実で手っ取り早い方法です。

## 終わりに

言われれば「あー！」となることも、言われるまではまったく気づかないということが偶にありますが、これもその部類かなーと思って今回の記事を書かせていただきました。  
誰かしらのお役に立てていれば幸いです。

また、Cookieについての理解を深める上で[RFC6265](https://tools.ietf.org/html/rfc6265)がとても役に立ちました。  
Cookieを利用したアプリケーションを開発されている方、開発する予定のある方は是非ご一読ください。