Rubyで安全な文字列処理!SQL・HTMLエスケープとsanitizeの基本
生徒
「Rubyでユーザーが入力した文字列をそのまま表示したりデータベースに保存すると危険ですか?」
先生
「はい、そのまま使うとSQLインジェクションやXSS攻撃のリスクがあります。安全に処理するために文字列のエスケープが必要です。」
生徒
「エスケープって何ですか?」
先生
「エスケープとは、特別な意味を持つ文字を文字通りの意味として扱うように変換することです。例えば、HTMLの < を < と表示させることもエスケープの一例です。」
1. SQLエスケープと文字列の安全な扱い
SQLにユーザー入力を直接埋め込むと、悪意ある文字列によってデータベースの操作を不正にされることがあります。これをSQLインジェクションと呼びます。RubyではActiveRecordを使うと自動的にエスケープされます。
# 悪い例(危険)
user_input = "'; DROP TABLE users; --"
sql = "SELECT * FROM users WHERE name = '#{user_input}'"
# → SQLインジェクションの危険
# 良い例(安全)
User.where(name: user_input)
(安全にユーザーを検索できる)
ポイントは、ユーザー入力を直接文字列結合でSQLに埋め込まないことです。
2. HTMLエスケープでXSS攻撃を防ぐ
Webアプリケーションで、ユーザー入力をそのままHTMLに埋め込むと、悪意あるスクリプトが実行されることがあります。これをXSS(クロスサイトスクリプティング)攻撃と呼びます。RubyではERB::Util.html_escapeやh()メソッドでエスケープします。
require 'erb'
include ERB::Util
user_input = "<script>alert('危険')</script>"
safe_input = html_escape(user_input)
puts safe_input
<script>alert('危険')</script>
これにより、ブラウザ上ではスクリプトは実行されず、安全に表示されます。
3. sanitizeで許可されたHTMLだけを残す
場合によっては、ユーザーに文字装飾などのHTMLタグを許可したいこともあります。その場合はsanitizeメソッドを使います。許可されたタグ以外は削除されます。
require 'action_view'
include ActionView::Helpers::SanitizeHelper
user_input = "<b>太字</b> <script>alert('危険')</script>"
safe_html = sanitize(user_input, tags: ['b', 'i'])
puts safe_html
<b>太字</b>
このように、sanitizeを使うと安全に一部のHTMLだけ残すことができます。
4. 実践ポイント
- SQLに直接文字列を埋め込まない
- HTMLに出力する文字列は
html_escapeでエスケープする - 一部HTMLだけ許可したい場合は
sanitizeを活用する - ユーザー入力を扱う場合は常に安全性を意識する
これらを理解すれば、Rubyでユーザー入力を安全に処理できるようになります。セキュアな文字列処理はWebアプリ開発の基本です。
5. 覚えておきたいポイント
ここまでの内容をまとめると、Rubyでユーザー入力を扱うときに一番大切なのは「どの場面で」「どんな目的で」文字列を扱うかを正しく理解しておくことです。入力された文字列をそのまま扱うと、思いがけない動作につながる場合があります。そのため、データベースに保存するとき、画面に表示するとき、タグを部分的に許可したいときなど、それぞれの用途に合わせて適切なエスケープ処理を行う必要があります。
- SQLインジェクション対策:ユーザー入力を直接SQLへ埋め込まず、
whereなどのメソッドを使って安全に検索する - XSS対策:画面に表示する文字列は
html_escapeやh()で安全な文字列に変換する - HTMLタグを一部だけ許可:太字や斜体などを残したい場合は
sanitizeで許可タグを限定する - ユーザー入力は常に疑う:そのまま使わず、一度フィルタを通して安全に扱う習慣を持つ
初心者向けのかんたんな確認サンプル
require "erb"
require "action_view"
include ERB::Util
include ActionView::Helpers::SanitizeHelper
user_input = "<b>こんにちは</b><script>console.log('example')</script>"
# そのまま表示した場合(本番では絶対にしない)
puts "そのまま: #{user_input}"
# HTMLエスケープした場合
escaped = html_escape(user_input)
puts "エスケープ: #{escaped}"
# 太字だけ許可して、それ以外は削除したい場合
sanitized = sanitize(user_input, tags: ["b"])
puts "sanitize: #{sanitized}"
そのまま: こんにちは
エスケープ: <b>こんにちは</b><script>console.log('example')</script>
sanitize: こんにちは
上の例では、同じ文字列でも処理の仕方によって結果が変わります。エスケープ前の文字列には<script>タグが含まれているため、本番環境では危険です。しかしhtml_escapeを使うことで、タグはそのまま文字として扱われ、ブラウザで実行されることはありません。またsanitizeを利用すれば、安全な太字タグ<b>だけを残し、スクリプト部分はきれいに削除されます。
はじめて学ぶ方は、まず「どのタイミングで危険が生まれるのか」をイメージできるように小さなサンプルから試してみると理解が深まります。Rubyの文字列処理は、ただの文字操作ではなく、安全にアプリケーションを動かすための大切な基礎でもあります。自分で入力内容を変えて動作を比べていくと、自然と判断力が身についていくはずです。
まとめ
Rubyで安全な文字列処理を行うために必要な「SQLエスケープ」「HTMLエスケープ」「sanitizeによる制御されたHTML許可」という3つの柱を、この記事を通して体系的に学んできました。Webアプリケーションでは、ユーザーから送られてくる文字列は信頼できるとは限らず、むしろ「安全でない前提」で扱うことが基本です。入力内容に含まれる特殊文字やスクリプト、意図しないSQL操作の命令などをそのまま扱ってしまうと、アプリケーションのデータ破壊・情報漏洩・画面改ざんといった重大なトラブルにつながります。だからこそ、正しくエスケープする仕組みや、安全に制御するメソッドを知ることが、プログラミングにおいて非常に重要な基礎となります。
SQLインジェクションを防ぐには、ユーザー入力をそのままSQLに埋め込むやり方を避け、ActiveRecordのようなバインドパラメータ機能を利用して安全にデータベースを操作することが必要です。また、XSS攻撃を防ぐためには、HTML上に文字列を表示する際に html_escape を利用して特殊文字を無害化することが求められます。さらに、ユーザーが入力する文字列の中に簡単な装飾を含めたい場合には、sanitize を使って安全性を担保しながら限定的にHTMLタグを許可する方法も有効です。これらの基礎を理解すると、文章の加工やWeb画面への出力など多くの処理が安全に行えます。
サンプル:安全なエスケープの流れをひとまとめに
require "erb"
require "action_view"
include ERB::Util
include ActionView::Helpers::SanitizeHelper
input = "<b>こんにちは</b><script>alert('危険')</script>"
# HTMLエスケープ
escaped = html_escape(input)
# 一部HTMLタグのみ許可
sanitized = sanitize(input, tags: ["b"])
# SQL検索(ActiveRecordを想定)
# User.where(name: input) # 安全にパラメータが扱われる
puts "HTMLエスケープ結果: #{escaped}"
puts "sanitize結果: #{sanitized}"
HTMLエスケープ結果: <b>こんにちは</b><script>alert('危険')</script>
sanitize結果: こんにちは
このサンプルでは、入力文字列の安全性を確保するための一般的な流れを一度に確認できます。まず html_escape によってすべてのHTMLを無害化し、ブラウザ上で表示しても危険な動作が発生しないようにします。そのうえで sanitize を使えば、「太字にしたい」といったユーザーの意図を残しつつ、有害なタグだけ除外することができます。さらに、SQL操作ではActiveRecordのような安全な仕組みを用いることで、データベースが悪意ある操作をされる危険性を回避できます。こうした安全な文字列処理を身につけておけば、Webアプリケーションの品質と信頼性は大きく向上します。
セキュリティにおける基本は「ユーザー入力を信用しない」という姿勢です。どれほど見た目が普通の文字列でも、攻撃につながる意図が潜んでいる可能性があります。エスケープ処理やsanitizeのような仕組みを理解しながら、常に安全性を意識したコードを書く習慣をつけることが、開発者としての成長につながります。今回紹介したRubyのエスケープ関連のメソッドはどれも比較的シンプルであり、初心者でも理解しやすい構造になっていますので、ぜひ自分のアプリケーションで活用しながら身につけていくとよいでしょう。
生徒
「今日学んだエスケープの話、思っていたより大事なんですね…。HTMLの< や > をそのまま画面に出すだけでも危険になるとは知りませんでした。」
先生
「そうなんです。安全に見えても、ブラウザが特別な意味として解釈する文字があるんですよ。だから開発では、まず文字列を正しく扱うことがとても重要なんです。」
生徒
「sanitizeが便利だと思いました!完全に禁止するんじゃなくて、必要なタグだけ残せるのは実務でも使いやすそうです。」
先生
「その通り。安全性と使いやすさのバランスを取るのがsanitizeの良いところです。SQLもHTMLも、ユーザー入力を安全に処理することが最優先ですよ。」
生徒
「Webアプリを作るときは、文字列をどう扱うかをしっかり考えないといけないんだなってよくわかりました…!」