セキュアなアプリケーションを考える
Python-Tornado: XSRF対策
SSLにすればおおよそ安心かなーと考えながら、本当にそうなのかと色々あさっていたところ、SSLにしていてもBREACH攻撃の脅威は防げないというのを知った。
SSL暗号を無効化する仕組み – BREACH, CRIME, etc
App Engine セキュリティー情報 - BREACH attack について
以前にXSRF対策でトークンをワンタイムにする必要はないと出典と共に書いたが、この脅威においてはワンタイムトークンを使うことは対策になり得るようだ。でもそもそもgzip圧縮を使わなければそれでこの脅威への対策になるようなので、gzip圧縮は切っておく。そうすればXSRFトークンはワンタイムでなくて大丈夫だろう。Tornadoではgzip圧縮はデフォルトではかかっていない。下記のように書く必要もとくにないがとりあえずgzipは切っておく。
あとはXSRF対策としてXSRFトークンをクッキーに埋め込むけど、これってsecure属性を付けなくていいのかなと。XSRFトークンがわかってしまえばXSRFの準備ができるから、取り扱いには気を払うべきかと考えているんだけど、Tornadoではsecure属性の付加オプションがみつからない。secure属性を付けていない場合はクッキーを盗む手段があるし(参考)、DjangoはXSRFクッキーのsecure属性付加オプションを用意している(参考)。
XSRFクッキーへのsecure属性付加のために少しばかり書き換えを考えてみる。個人的な書き換えなので実際に使うのは望ましくない。編集するファイルの名前はweb.py。おおよそ1000行目あたりにあるXSRFトークンをクッキーにセットする部分だけをちょっと書き換える。やるのはsecure属性付加だけ。変なことして余計な穴を増やしたらまずいし。
書き換えをしたらセッティング項目でxsrf_cookie_secureを追加。

上がデフォルトで、下がxsrf_cookie_secureをTrueにした場合。secure属性が付加できた。
追記
上のコードをTornadoフォーラムにどうかと投げてみた。そうしたらsecure以外にもHttponlyとかexpireとかあって、それを一つずついちいちオプション追加するのクールじゃないと返信があり、どう対処してるかコードサンプルをくれた。どうやらBaseHandlerクラスを宣言するとき、set_cookieメソッドをオーバライドしてるようだ。確かにこっちの書き方はクール。
Python-Tornado: XSRF対策
SSLにすればおおよそ安心かなーと考えながら、本当にそうなのかと色々あさっていたところ、SSLにしていてもBREACH攻撃の脅威は防げないというのを知った。
SSL暗号を無効化する仕組み – BREACH, CRIME, etc
App Engine セキュリティー情報 - BREACH attack について
以前にXSRF対策でトークンをワンタイムにする必要はないと出典と共に書いたが、この脅威においてはワンタイムトークンを使うことは対策になり得るようだ。でもそもそもgzip圧縮を使わなければそれでこの脅威への対策になるようなので、gzip圧縮は切っておく。そうすればXSRFトークンはワンタイムでなくて大丈夫だろう。Tornadoではgzip圧縮はデフォルトではかかっていない。下記のように書く必要もとくにないがとりあえずgzipは切っておく。
settings = dict(cookie_secret="foooooooooooooooooooooooooooooo",
static_path=os.path.join(os.path.dirname(__file__), "static"),
template_path=os.path.join(os.path.dirname(__file__), "templates"),
xsrf_cookies=True,
gzip=False,
autoescape="xhtml_escape",
debug=True,
)
application = tornado.web.Application([('/(\d*)', View),
('/article/([\w\-]+)', Article)],
**settings)
あとはXSRF対策としてXSRFトークンをクッキーに埋め込むけど、これってsecure属性を付けなくていいのかなと。XSRFトークンがわかってしまえばXSRFの準備ができるから、取り扱いには気を払うべきかと考えているんだけど、Tornadoではsecure属性の付加オプションがみつからない。secure属性を付けていない場合はクッキーを盗む手段があるし(参考)、DjangoはXSRFクッキーのsecure属性付加オプションを用意している(参考)。
XSRFクッキーへのsecure属性付加のために少しばかり書き換えを考えてみる。個人的な書き換えなので実際に使うのは望ましくない。編集するファイルの名前はweb.py。おおよそ1000行目あたりにあるXSRFトークンをクッキーにセットする部分だけをちょっと書き換える。やるのはsecure属性付加だけ。変なことして余計な穴を増やしたらまずいし。
def xsrf_token(self):
"""The XSRF-prevention token for the current user/session.
To prevent cross-site request forgery, we set an '_xsrf' cookie
and include the same '_xsrf' value as an argument with all POST
requests. If the two do not match, we reject the form submission
as a potential forgery.
See http://en.wikipedia.org/wiki/Cross-site_request_forgery
"""
if not hasattr(self, "_xsrf_token"):
token = self.get_cookie("_xsrf")
if not token:
token = binascii.b2a_hex(uuid.uuid4().bytes)
expires_days = 30 if self.current_user else None
#self.set_cookie("_xsrf", token, expires_days=expires_days)
if self.application.settings.get("xsrf_cookie_secure"):
self.set_cookie("_xsrf", token, expires_days=expires_days, secure=True)
else:
self.set_cookie("_xsrf", token, expires_days=expires_days)
self._xsrf_token = token
return self._xsrf_token
書き換えをしたらセッティング項目でxsrf_cookie_secureを追加。
settings = dict(cookie_secret="foooooooooooooooooooooooooooooo",
static_path=os.path.join(os.path.dirname(__file__), "static"),
template_path=os.path.join(os.path.dirname(__file__), "templates"),
xsrf_cookies=True,
xsrf_cookie_secure=True,
gzip=False,
autoescape="xhtml_escape",
debug=True,
)

上がデフォルトで、下がxsrf_cookie_secureをTrueにした場合。secure属性が付加できた。
追記
上のコードをTornadoフォーラムにどうかと投げてみた。そうしたらsecure以外にもHttponlyとかexpireとかあって、それを一つずついちいちオプション追加するのクールじゃないと返信があり、どう対処してるかコードサンプルをくれた。どうやらBaseHandlerクラスを宣言するとき、set_cookieメソッドをオーバライドしてるようだ。確かにこっちの書き方はクール。
def set_cookie(self, *args, **kwargs):
kwargs.setdefault('secure', True)
super(BaseHandler, self).set_cookie(*args, **kwargs)
スポンサーサイト