はじめてのwebアプリケーション開発はRails
この記事で書くこと
shimo21です。現在、スタートアップ企業でwebエンジニアをやってます。
はじめてwebアプリケーションを開発〜リリースした経験から、Railsでアプリケーション開発をして便利だな〜と感じたことを書こうと思います。
(おもにセキュリティで感じることが多かったので、そのへんが中心です)
*この記事は2018年 Shinjuku.LT アドベントカレンダーの20日目です。
なんでスタートアップがRailsを採用するのか少しわかった気がした
スタートアップ企業で開発を経験して一番に感じたことは、コストとパフォーマンスの関係性を重視することです。
ここでのパフォーマンスとは収益を指しますが、
スタートアップ企業では収益が見込めない機能に時間を割くことが出来ず、
「いかに収益が見込める機能開発に注力するか」といった視点が重要になってくるんだなーと感じました。
実際、「収益が見込めない機能は時間を割かずに対応したい」といった願望の多くは、Gemやフレームワークの機能を活用することで実現出来ました。
なかでも感動したのは、セキュリティについてです。
Railsのセキュリティ対策について
セキュリティって学習コストがかかるうえに、アプリケーションとしてはユーザー目線に立つと何も変わっていない(ように見える)といった、コストパフォーマンスの関係においては非常に悲しい立ち位置にあると思います。
ただ、Webアプリケーションを公開するということは、不特定多数のユーザーが利用するため、避けては通れない問題です。
Rails ではセキュリティ対策として、Rails セキュリティガイド | Rails ガイド が公開されており、開発者がコストをかけずに、一定の基準を満たせるような仕組みが提供されています。
以下では、「こんな簡単に対策できるのか!!」と感じたRailsのセキュリティ対策について記載します。
1. セッションハイジャック攻撃
他ユーザーのcookieを盗み、あたかも本人のように振る舞うといった攻撃です。(実際はcookie内のsessionIDを利用するため)「オレオレ詐欺」みたいな攻撃ですね。
この問題は、暗号化されていない通信経路(公衆無線LANなど)を利用することで発生することがあります。
Railsでは以下の1行のコードをconfigファイルに定義するだけで、強制的に通信がSSL化されます。これにより、公衆無線LANなどを利用しても通信が暗号化されるのでcookieの覗き見から防止することができます。1行で対策ってすごい・・・。
config.force_ssl = true
2. セッション固定攻撃
他ユーザーが利用するsessionIDを事前に取得(固定)しておき、ログインしたあとに、同じsessionIDを利用すれば、勝手にログインができてしまうといった攻撃です。
この対策は、ログイン後にsessionIDを変更させることです。
sessionIDを変更し、変更前のsessionIDを無効とすることで、固定攻撃が出来なくなります。
Railsでは、またしても1行のコードを追加するだけで対策が出来ます。1行で対策って(ry
reset_session
ログイン前に、操作を許容しているアプリケーション(ECサイトでカートに商品を追加するなど)の場合は、セッションに格納している情報を退避したうえで、セッションを再生成する必要があります。
tmp_product_id = session[:product_id]
reset_session
session[:product_id] = tmp_product_id
3. CSRF(クロスサイトリクエストフォージェリ)
cookieが自動送信されるブラウザの特性を用いて、訪れたユーザーのセッション情報を悪用する攻撃です。攻撃対象となるサイトへのリクエストを、別サイトに埋め込む(例:imgタグ<img src="https://~~~/product/1/destroy">)ことで、別ユーザーのセッションを悪用して攻撃をするセキュリティ問題です。
Railsでは、application_controllerに以下のコードを追加するだけで対策が出来ます。1行で(ry
protect_from_forgery with: :exception
上記コードにより、自己サイト内で生成されるフォームにはセキュリティトークンが含まれるようになります。サーバサイドにて受信時、セキュリティトークンが合致しない場合は例外エラーとなります。(他サイトではセキュリティトークンを知りえないため、CSRFを防止できます)
4. SQLインジェクション
セキュリティの勉強といえば、SQLインジェクションかXSSか、ってくらい話題にあがる問題だと思います。(主観)
RailsではActiveRecordを正しく利用している限りめったに起こりえないのですが、以下のような記載にて発生します。
# NG
Model.where("name = '#{params[:name]}'")
# OK
Model.where("name = ?", params[:name])
ただ、「正しく利用する」というのはコード量が増えれば全量を見切るのも難しくなります。
そこで、Rails標準の機能ではありませんが、brakeman を利用することで、静的な解析が可能になります。(自分はこれで1件SQLインジェクションを見つけました…)
↓こんな感じで出してくれます(html形式出力の場合)
まとめ
セキュリティ対策は、「これだけやっておけばいい!」といったものでは無いので、日々情報をキャッチする必要があるなと感じる一方、
フレームワークに乗ることで、個別に対策する必要性が無い問題は時間を掛けずに効力を得られるといった利点があると思います。
コストパフォーマンスが高い機能に注力するためにも、自分の時間をどこに注ぐべきか考えながらやっていこうと思います。