徳丸本 輪読会 参加メモ(第5回 4.5.1 CSRF)
www.sbcr.jp
参加者は7名でした。
内容は4.5.1 クロスサイト・リクエストフォージェリ(CSRF)
書籍の中でCSRF対策方法として以下が紹介されている
対策方法を実装した際の開発工数や利用者への影響、利用シーンが表で記載(p.196)されていて非常にわかりやすい。
話題としては
パソコン遠隔操作事件ってあったね
- このあたりのセキュリティってフレームワーク側でよしなにやってくれてるからあまり意識しないですね
など。
フレームワーク側で~の話は以前XSSあたりを読んでるときにも出てた。
Rails3以降だとテンプレートに埋め込まれた変数はデフォルトでエスケープされるので、そのあたり意識せずRails3以前やSinatra等、デフォルトでエスケープしないFWでView作るとXSS盛りだくさんのWebアプリケーションが生まれてしまう。
気になったこと
/45/45-003.htmlのCSRFのサンプルがうまく動作してないようで、ユーザーIDが表示されず、DBを見てもパスワードは変わっていなかった。

多分セッションIDの値周りでこうなっているのだけど、この現象は自分だけ?
トークンに加えてリファラのチェックも必要というコメントがあるが、これは間違い。XSSがある前提ではリファラをチェックしても意味ないし / “PHP - とっても簡単なCSRF対策 - Qiita [キータ]” http://t.co/m3ZavYaj68
— 徳丸 浩 (@ockeghem) 2014年11月21日
XSSがあるとCSRF対策のトークンが読まれてしまうのは正しい指摘だけど、XSSがあると攻撃対象と同じドメイン(オリジン)から攻撃できるので、それはCSRFではく、単にXSSの応用だし、リファラのチェックでは対策できない。XSSはXSSとして対策すべし
— 徳丸 浩 (@ockeghem) 2014年11月21日
(昨日の某発表資料でもCSRFがセッション管理の問題と分類されていたけど、CSRFはセッション管理の問題とは違うと思うんだよね。リクエストを受け付けて良いか否かの問題なので…)
— 徳丸 浩 (@ockeghem) 2015年1月15日
HttpOnlyをつけなくても大丈夫かという質問は、XSS脆弱性があることが前提かと思いますが、XSSがあればCSRF対策をしていても突破されます(例: hiddenパラメータのトークンをXSSで読める)ので、どっちみちHttpOnlyにより脅威は減りません=(2)に対する回答
— 徳丸 浩 (@ockeghem) 2018年11月8日
ENDO氏との会話が今ひとつ噛み合わなかったのですが、XSS脆弱性が *あれば* *一般的に* CSRF対策は機能しません。たとえば、XSSからのXHRにより入力フォームにアクセスすればhiddenパラメータ記載のCSRFトークンを取得できます。それを用いて2回目のXHRでCSRF攻撃できます https://t.co/BlKU9A1aAC
— 徳丸 浩 (@ockeghem) 2018年11月8日
海外の文献だと、CSRF対策の説明に「XSSにも注意」と書いてあることがありますが、日本の文献だと見かけない感じです。だって、XHRでトークン読んで…という攻撃はCSRF攻撃ではなくXSS攻撃ですからね。つまり、書かないほうが技術的には正確だと思いますが、実用的には、書いておいたほうがよいのかも
— 徳丸 浩 (@ockeghem) 2018年11月8日
このように考えるのも良いと思います。件の質問はWeb APIのCSRFに関するものでしたが、XSSがあるとWeb APIを用いたスクリプトを注入することもできます。当然、CSRF攻撃に相当するスクリプトも書けるわけです。というわけでXSSがあるとCSRF対策は無力になります https://t.co/AYz51aJMDt
— 徳丸 浩 (@ockeghem) 2018年11月8日
(Vue.js)$router.pushのqueryで、パラメータの値に配列を渡すと同一名のパラメータを複数作ってくれる
this.$router.push( { name: 'home', query: { foo: ["value1", "value2"] } } )
これでクエリストリングは?foo=value1&foo=value2となる。
定期的に見てるサイト
- るびま
- TechRacho - Ruby on Rails システム開発 情報サイト - BPS株式会社
- r/programming
- r/programming_jp
- Qiitaの殿堂
- 室長のひとりごち
- GitHub - rubocop-hq/ruby-style-guide: A community-driven Ruby coding style guide
るびま
定期的にアーカイブを読んでる気がする
技術的な記事は正直レベル感が合わないかな? でもRuby コードの感想戦 【第 1 回】 WikiRは面白かった
よく読むのはインタビュー記事
r/programming
どういう話題があるかをチェックしてるだけで中身を読むことは少ない
r/programming_jp
こっちの方をよく読む
自分が見始めた時はRustの読書会をしていた
Qiitaの殿堂
タイトル一覧を見て満足する
室長のひとりごち
週6で見てる
サーバがステートレスとは
Webを支える技術を読んでいてよくわからなかったところを整理。
ステートフル/ステートレスはハンバーガーのたとえが有名。
セッション(ステート)の保存先はいくつかある。Railsだと、
- CookieStore(デフォルト)
- CacheStore
- ActiveRecordStore
- FileStore
- RedisStore
- DalliStore
たとえば、DBをセッションストアにする。この時、クライアントからサーバにリクエストした際、サーバはリクエストに応じた状態データを返却する。
この時、サーバはステートフルな(状態を持ってる)んじゃないのって思うけど、そこはシステム単位で見るか個々のサーバ単位で見るか、スコープによって変わってくる。
雑に書くとこんな感じ。

アプリケーションサーバの役目はクライアントからのリクエストに応じた処理を行うことで、状態は保持していない。
保持しているのはDBサーバなので、
APサーバ:ステートレス
DBサーバ:ステートフル
サーバ単位で見たらステートレスなサーバとステートフルなサーバに分けられ、システム全体はステートフルな振る舞いになる。
システム全体でステートレスにしたいなら、クライアントにCookie等で状態データを全て保持させて、リクエストの度に必要な状態データを送ればいい・・・と思う。(ステートレスにする必要があるかはともかく)
▶ここのコメントも参照
もしくはElastiCache等の外部サービスにセッションを持たせるとか。
Sinatra pry(irb)でヘルパーメソッドを呼び出す
コンソールでメソッド呼びたかったけど結構つまづいたのでメモ代わりにまとめ。
Pry起動
# Gemfile: gem 'pry' $ bundle exec pry -r 'app.rb'
Helper呼び出し
pry(main)> MyApp.new.helpers.hoge => 'hoge'
github.com
でWrapperにhelpersが定義されていて、ヘルパーメソッドは上記のように呼び出すことができる。
躓いたのがヘルパー以外の、クラス内に定義されてるメソッド呼び出しで、newしても上手くいかなくて困ってたけどこの記事*1を参考にしたら解決した。
Sinatra::Baseに限らずミドルウェアを継承させているクラスでは、エイリアスのnew!を使う必要がある(allocateでもいい)
インスタンスメソッド呼び出し
pry(main)> my_app = MyApp.new! pry(main)> my_app.fuga => 'fuga'
private メソッド呼び出し
pry(main)> my_app = MyApp.new! pry(main)> my_app.send(piyo) => 'piyo'
addEventListener() のリスナーでreturn falseしてもイベントはキャンセルできない
Target.addEventListener('submit', function(){ // 処理 return false });
↑みたいなコードを書いてもsubmitイベントはキャンセルできない。
jQueryのリスナーであれば、return falseでキャンセルできる。↓(イベントのキャンセルおよびイベント伝搬が停止する)
.on() | jQuery API Documentation
Returning false from an event handler will automatically call event.stopPropagation() and event.preventDefault().
なのでaddEventListener()を使う時は、
Target.addEventListener('submit', function(event){ // イベント伝搬の停止 event.stopPropagation(); // イベントキャンセル event.preventDefault(); });
で、jQueryのリスナーでreturn falseした場合と同じ挙動になる。
jQuery使ってる人ほど引っかかりそう。
(return falseすればキャンセルできるんだーくらいの理解度だったので引っかかった)