- PdM(楽楽シリーズ)
- Javaエンジニア(楽楽明細)
- 業務改善(BPR)
- Other occupations (76)
-
Development
- Javaエンジニア(楽楽明細)
- エンジニアオープンポジション
- ブリッジSE(大阪)
- PM(楽楽シリーズ)
- オフショアPJマネージャー
- Webエンジニア(大阪PHP)
- テックリード(大阪/PHP)
- ブリッジSE/オフショア開発
- フロントエンドマネージャー候補
- プロジェクトマネージャー
- エンジニアリングマネージャ
- AI導入エンジニア
- プロダクト開発部長
- Web Engineer
- フロントエンドエンジニア
- Webエンジニア
- フロントエンド(リーダー)
- Mobile Engineer
- Android/iOSアプリ
- 社内SE(大阪/セキュリティ)
- インフラエンジニア
- インフラエンジニア/マネージャ
- DevOps Engineer
- 社内SE(データエンジニア)
- 戦略企画・データマネジメント
- QAリーダー/マネージャー
- システム企画
- 品質管理/技術支援チーム
- AI/機械学習エンジニア
- データ基盤エンジニア
- Engineering
- UIデザイナー(リーダー)
- コーポレートデザイナー
- UIデザイナー
-
Business
- PdM(楽楽シリーズ)
- 開発マネージャー
- プロジェクトマネージャ(大阪)
- 導入支援/導入コンサルタント
- プロダクトマネージャー
- プロダクトマネージャー(AI)
- PMMプロダクトマーケティング
- プロダクトセキュリティ
- 技術推進部長
- IR
- HRBP
- データマネジメント・マーケ戦略
- 経営企画
- コーポレート広報
- 内部監査(業務監査)
- 人材開発
- 営業企画(イネーブルメント)
- ITセールス(名古屋)
- セールスマネージャー
- 法人営業/カスタマーサクセス
- フィールドセールス(名古屋)
- フィールドセールス(法人営業)
- フィールドセールス
- ITセールス(広島)
- 法人営業
- フィールドセールス(東京)
- 営業企画(戦略立案)
- ITセールス
- ビジネスオープン
- ITセールス経験者
- オンラインマーケティング
- オフラインマーケティング
- 製品企画/法要件(楽楽明細)
- ブランド企画
- 製品企画/プロダクトマーケ
- CSマーケティング
- マーケティング担当
- ブランド企画・ブランディング
- マーケティングリーダー
- 営業推進リーダー(楽楽精算)
- Other
はじめに
こんにちは、mickey-STRANGEです。一昨年に新卒でラクスに入社しました3年目です。
新卒に毛が生えた程度の新米エンジニアですが、今回はその数少ない毛の中から学生時代に意識したことのなかったものという観点で脆弱性のお話を選び、記事にしました。新しくWeb開発企業に入社した新卒の方の学習の手助けになればと思います。
目次
- はじめに
- 脆弱性とは?
- CSRF(クロスサイトリクエストフォージェリ)
- 概要
- 対策
- 確定処理の前に認証を行う
- リファラを確認する
- ワンタイムトークンを利用する
- おわりに
脆弱性とは?
脆弱性とは、セキュリティの面からみたシステムの欠陥のことです。 脆弱性をついて攻撃されてしまうと、ユーザには本来許されていない操作ができてしまったり、サーバにウィルスを仕込まれてしまったりという被害が出ます。
この記事では脆弱性の中でも、私が実際に理解に時間のかかった
- CSRF(クロスサイトリクエストフォージェリ)
という脆弱性の概要と対策をご紹介したいと思います。
CSRF(クロスサイトリクエストフォージェリ)
概要
サービスの利用者に意図しないHTTPリクエストを送信させ、利用者の意図しない処理をサービスに実行させる攻撃です。と、1文で書いてはみるものの、これだけで理解は出来ないと思います(私が勉強したときは理解出来ませんでした)ので、shop.example.comという架空の通販サイトで簡単な例を挙げてみましょう。
shop.example.comではユーザはIDとパスワードでログインします。利用ユーザがパスワードを変更しようとしたとき(ユーザが新しいパスワードを入力して確定ボタンを押したとき)に送信されるリクエストが下のようなものだったとします。
このリクエストと同じものを作成して送信させる悪意のあるWebページを攻撃者が用意します。 偽装リクエストを送信さえできればよいのでWebページの用意は難しいことではありません。具体的なコードは示しませんが、javascriptを使って数行で実現出来ます。GETでよければ他の手段でもっと単純に、コードとしては1行でも十分に実現できてしまいます。(確定処理でGETを使用すること自体が論外ですが。)
さて、shop.example.comのユーザAさんが、攻撃者の用意した悪意のあるWebページを開いてしまったとしましょう。
するとAさんのブラウザから上記リクエストと同じものが勝手に送信されてしまいます。正規にパスワード変更画面で確定ボタンを押したときのリクエストと違うところがあるとすれば、パラメータのパスワード部分は攻撃者しか知らないものである、ということだけです。 このときAさんのブラウザに「shop.example.comにログインしている状態のセッション情報」が残っていた場合、その情報もブラウザが同時に送信してしまいます。 そのリクエストを受け取ったサーバ側のプログラムはAさんが操作を再開して、パスワードの変更確定ボタンを押した
と誤認し、パスワード変更の処理を行ってしまいます。パスワード変更の処理が完了するとAさんはもうログイン出来なくなってしまいます。
CSRFはログイン済みのユーザに、意図しない操作を強制的に実行させてしまう攻撃
であるといえます。
今回の例ではパスワード変更ですが、これが購入や決済の確定処理で起きてしまうと取り返しがつかないということは簡単に想像出来ると思います。ではCSRFがどのような脆弱性か分かったところで、CSRF攻撃を防ぐためにどのような仕組みを入れればよいかを考えてみようと思います。
対策
ではCSRFの対策を考えてみましょう。 上記の通り、CSRFにおいてサーバはリクエスト通りに1つの機能を正しく完了している
という特徴があります。つまり対策として考えられるのは受け取ったリクエストに対して処理を実行するかしないかを確認する
ことになります。
確定処理の前に認証を行う
一番分かりやすい方法はユーザに確認してもらうことです。重要な処理の前にはユーザにもう一度認証を行う、つまりログインIDとパスワードの入力をしてもらうことになります。今回のパスワード変更の例ですと、以下のようになります。(数字がユーザ操作、→がサーバ処理です。)
この順番で操作してもらうようになっていれば、今回の例のように1番のリクエストを偽装されても処理を行ってしまうことはありません。
しかし、この方法で対策するとユーザの操作が増えてしまいます。大事な処理の前だけとしても、ユーザの操作量が増えてしまったり、直感的に進めない画面が表示されると「このサイトは使いにくい、面倒だ」と感じてしまうかもしれません。ユーザに負担をお願いしたくない、ということで次にプログラム側だけで出来る対策を考えてみます。
リファラを確認する
ユーザ操作を増やさずに出来るCSRF対策は「送られてきたリクエストが正しいものか確認する」ことです。ここで正しいリクエストとは、サイト内にある確定ボタンを押すことで送信されたリクエスト
ということになります。それを確認するために、リファラというHTTPヘッダの1つを利用します。
リファラとは、リクエスト元のページのURL
を示すHTTPヘッダです。処理の前にリファラの値が http://shop.example.com
から始まっているかを確認すれば、偽装リクエストかどうか判定することが可能です。
しかし、この方法ではまだ完璧な対策ではありません。リファラはその特性上、プライバシー面に問題を抱えており、ブラウザのでリファラを送信しない設定が可能です。また、前述のとおり、リファラはHTTPヘッダの1つです。改竄されてしまっては元も子もありません。
ワンタイムトークンを利用する
ワンタイムトークンとは、リクエストが正しいものか判断するための文字列をリクエストの中に仕込む手法です。
今回のパスワード変更の例ですと、以下のような流れになります。
パスワード変更画面を開く際にトークン(乱数文字列)を作成し、セッションなどのサーバ側の領域で一時保存しておきます。また、確定のリクエストの時にそのトークンをパラメータに追加して送信させ、サーバ側でトークンの照合を行います。サーバ側で保存していたトークンと一致すれば処理を行う、一致しなければ不正なリクエストとして処理を行わない、といった判断が可能となります。
偽装リクエストがもしトークンを勝手に付与したリクエストを送信してもサーバ側で同じトークンを保持していないので判別できますし、リファラとは違いヘッダではなくパラメータなのでユーザ依存で失敗したりすることがありません。今回紹介した中ではこの手法が最も適切だといえるでしょう。
おわりに
CSRFの概要と対策についてご紹介いたしました。いかがでしたでしょうか。 XSS(クロスサイトスクリプティング)と名前が似ていることで勘違いしやすい脆弱性で、自分が理解しづらかったCSRFについて記事にしてみました。
Web開発に関する勉強を始めたばかりの方の手助けになれば幸いです。