Angularのセキュリティ対策について調べてみる その4
はじめに
続きです。
特定のURLでCSRF(XSRF)対策を無効にする方法、ドキュメントのCross-site script inclusion (XSSI)について追いかけてみました。
特定のURLでCSRF対策を無効にする
前回は全ページでログインしていないとPostリクエストが送れない状態でしたが、
これでは少し不便ですね。
基本的にCSRFの対策はアカウントのパスワード変更など、ログインした状態で行う処理に対して実行するもの、
ということを考えると、例えばログインしていなくても送信したい情報がある場合、
そのページではCSRFを無効にして未ログイン状態でもPostリクエストを送信できるようにする必要があります。
http.csrf().disable()を使う(失敗)
下記のように「http.csrf().disable()」を使ってCSRF対策を無効にしようとすると、 全ページで無効になったり、「http.csrf().disable()」が無視されてしまいます。
WebSecurityConfig.java
〜省略〜 @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 〜省略〜 @Override public void configure(HttpSecurity http) throws Exception { http .httpBasic().and() .authorizeRequests() .antMatchers("/menulist").authenticated() .and().formLogin() .and().csrf() .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) .and().exceptionHandling() .accessDeniedPage("/accessdenied.html"); http .authorizeRequests() .antMatchers("/").permitAll() .and().csrf() .disable(); } }
http.csrf().ignoringAntMatchers()
じゃあどうするか、というと、「http.csrf().ignoringAntMatchers()」を使用します。
WebSecurityConfig.java
〜省略〜 @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 〜省略〜 @Override public void configure(HttpSecurity http) throws Exception { http .httpBasic().and() .authorizeRequests() .antMatchers("/").permitAll() .antMatchers("/menulist").authenticated() .and().formLogin() .and().csrf() .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) .and().exceptionHandling() .accessDeniedPage("/accessdenied.html"); http .csrf() .ignoringAntMatchers("/postsample"); } }
ここで注意が必要なのは、「ignoringAntMatchers()」で指定するURLはページのURLではなくPostリクエストの送信先のURLであるということです。
そのため、CSRFを有効にするページとそうでないページとでPostリクエストの送信先が一緒になっていると、
両方でログインを求められたりCSRF対策が無効になってしまったりします。
まぁ適当にコピペしているのでもなければ、通常そんなことは無いだろうとは思いますがorz
X-XSRF-TOKENについて
CSRF対策用のトークンなどは、Spring boot側でCSRF対策が有効・無効であるかにかかわらず、常に含まれるようです。
ただし、トークンの値はログインのタイミングで更新されるため、
- ログイン前にCSRF対策を無効にしたPostリクエストを送信する
- ログインして、CSRF対策を有効にしたPostリクエストを送信する
- ログイン状態のままCSRF対策を無効にしたPostリクエストを送信する
とすると、2と3で同じトークンが渡され、1とは異なる値になっています。
IDの固定化攻撃の対策も自動で行ってくれる、ということですね。すごい!
Cross-site script inclusion (XSSI)
JSONから重要なデータを読み取られる脆弱性、ということですが、
JSONとしてサーバー側から受け取った値がそのままJavascriptとして実行できる場合にのみ発生するようで、
XSSなどと比較すると常に気をつけなければいけない、という訳でもないのかしら。。。?
(すみません。イマイチ内容が理解できていません)
とりあえず、このXSSIを防ぐ方法としてサーバー側で冒頭に「)]}」や「\n(改行コード)」をJSONデータのプレフィックスとして付与するというものがあり、
AngularのHttpClientではそれらのプレフィックスをJSONの解析前に削除する、というのが本項目の内容です。
おわりに
一通りAngularのSecurityのページを眺めてみました。
軽く触っただけのところなど、気になる部分もありますが、
次からはSpring Security側の設定なども含めて、実際に何かWebアプリでも作りつつ試していくことにしたいと思います。
ブログはせっかくここに書き溜めているわけですし(なお質は問わないものとする)、
PCやスマホからメモを残したりスケジュールを追加したりできるようなものを作ってみようかな?
(できるとは言っていない)
参照
CSRF
- Spring Security 3.2 CSRF disable for specfic URLs - Stack Overflow
- spring boot で 特定の url だけcsrf チェック除外する(修正済) - Qiita