Help us understand the problem. What is going on with this article?

railsに頼りきって忘れがちな脆弱性

More than 1 year has passed since last update.

はじめまして。食べログでwebサービス開発のエンジニアをしている@ham0215です。

web開発をしているエンジニアなら一度は聞いたことがある「SQLインジェクション」や「クロスサイトスクリプティング」など有名な脆弱性があります。
ただ知識として知っていてもrailsのように普通に使っていたら勝手に対策されているものを使っていると、どんどん意識から離れていき無意識のうちに埋め込んでしまうことがあります。
そこでrailsでの具体例を交えて、いくつかの脆弱性についておさらいしようと思います。

クロスサイトスクリプティング

悪意のあるスクリプトがサイト内に埋め込まれてしまう脆弱性。

脆弱性が発生する例

ユーザーが入力したテキストを画面表示するシステムで下記を実施
1. ユーザーが下記テキストを入力
<script>alert('クロスサイトスクリプティング!!');</script>
2. 入力されたテキストを画面出力するとscriptが動作してアラートが表示された
スクリーンショット 2018-12-05 12.17.25.png

railsでの対策

erbで<%= text %>と書いたり、slimで= textと書くだけでtextにhtmlタグが入っていたとしても自動的にエスケープされる。

- text = "<script>alert('クロスサイトスクリプティング!!');</script>"
/ ↓ &lt;script&gt;alert(&#39;クロスサイトスクリプティング!!&#39;);&lt;/script&gt; とエスケープされてHTML出力される
= text

NGパターン

本文の特定キーワードを強調したり、httpから始まる箇所を<a>タグに変換したいなどの要件があった場合に文字列全体をrawhtml_safeでエスケープされない状態にしてしまいそれを画面出力してしまう。
slimの場合は== textと=を2つ重ねるとエスケープされない。

# やりたいこと
# ->ユーザーがURLを本文に入れると<a>タグを付加してリンクに変換して表示
<% user_input = "ここがオススメのお店です。http://hogehoge" %>
# httpの部分を<a>タグに変換(ロジックは割愛)
<% convert_a = "ここがオススメのお店です。<a href='http://hogehoge'>http://hogehoge</a>" %>
# <a>タグを有効にした状態でHTML出力したいのでhtml_safeをつける
# ->目的達成
<%= convert_a.html_safe %>

# NG
# ->ユーザーがフリーテキスト部分にHTMLタグを埋め込んだ場合
<% user_input = "<script>alert('クロスサイトスクリプティング!!');</script>。http://hogehoge" %>
# httpの部分を<a>タグに変換(ロジックは割愛)
<% convert_a2 = "<script>alert('クロスサイトスクリプティング!!');</script>。<a href='http://hogehoge'>http://hogehoge</a>" %>
# <a>タグを有効にした状態でHTML出力したいのでhtml_safeをつける
# ->アラートが表示される・・・
<%= convert_a2.html_safe %>

チェック観点

  • 入力項目には有効なHTMLタグを入れるテストを実施して、エスケープされることを必ず確認する。
  • コードチェックでhtml_safeやslimの==を見かけたら本当に必要なのか疑う。必要な場合、システムで制御できない動的要素がないことをチェックする。

SQLインジェクション

実行されるSQLをユーザーが任意に操作して、データを改ざんしたり取得したりする脆弱性。

脆弱性が発生する例

ユーザーが入力したニックネームをデータベースに登録するシステムで下記を実施

-- 正常パターン
1. ユーザーがニックネーム:"hogehoge"を入力してリクエスト
2. 下記SQLが発行
insert into users (nickname) values ('hogehoge');

-- 異常パターン
1. ユーザーがニックネーム:"a');delete from users;--"を入力してリクエスト
2. 下記SQLが発行 -> usersテーブルに対してdelete文が発行される!!
insert into users (nickname) values ('a');delete from users;--');

railsでの対策

プレースホルダーを使うなど、SQLを直接文字列で生成しない書き方をすれば勝手にエスケープされます。

ユーザーが入力したニックネームで検索する
# params[:nickname] = "' OR '1"
User.where(nickname: params[:nickname])
User.where("nickname = ?", params[:nickname])
# どちらの書き方でもシングルクォーテーションが\'にエスケープされて実行される
# select * from users where nickname = '\' OR \'1';

NGパターン

SQL文を文字列で生成した場合はエスケープされません。

ユーザーが入力したニックネームで検索する
# params[:nickname] = "' OR '1"
User.where("nickname = #{params[:nickname]}")
# シングルクォーテーションがエスケープされず、全件検索される
# select * from users where nickname = '' OR '1';

チェック観点

  • 入力項目にはシングルクォーテーションなどSQLの特殊文字を入れるテストを実施して、エスケープされることを必ず確認する。
  • コードチェックでクエリーを文字列生成している箇所を見つけたら撲滅する。どうしても必要な場合は確実にエスケープされることをチェックする。

最後に

今回は個人的に埋め込みやすいと思っている2つの脆弱性をピックアップしました。
冒頭に記載した通り最近では自動的に対策されていることが多く、また脆弱性診断など別途脆弱性の確認をする工程をふむことで脆弱性を埋め込んだままリリースしてしまうリスクはかなり減っていると思います。
ただ、web開発をする上で重要な知識であることに変わりはないので、開発者自身もきちんと理解して回避することが重要ですね。

明日は@e-ronnyさんの「Fluentd + MySQL でログ保存 & 検索システムを考えてみた話」です。よろしくおねがいします!

ham0215
Webエンジニアやってます。 仕事ではバックエンドメインで最近はRailsを使っています。 個人ではReact、Typescript勉強中。
https://hamchance.com
vis-its
独自技術ideagramを用いて、人々の「創造性」や「目利き力」の定量化を行い、イノベーター人材の発掘/育成、科学的イノベーション創発支援を行っています。
https://visits.world
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした