はじめに
Ruby学習にて今は使われてないが「オブジェクトの汚染」がよくわからなかったのでイメージをまとめてみました。
目次
オブジェクトの汚染とは?
「外部から取得したデータがRubyのオブジェクトに影響を与える可能性がある状態」のこと。
Rubyでは、外部からの入力(ユーザー入力、ファイル、ネットワーク経由のデータなど)を自動的に「怪しい!」と判定し、汚染フラグ (taint
) を付けてくれる。
str = "hello".taint # 文字列を汚染する
puts str.tainted? # => true (汚染されている!)
👆 taint メソッドで汚染されると、.tainted?
で確認可能。
何が問題なの?
汚染されたオブジェクトをそのまま使うと、セキュリティ的に危険なことが起こる可能性がある!
例えば、eval を使って汚染された文字列を実行すると…?
evil_input = "system('rm -rf /')".taint # ユーザーが悪意あるコードを入力
eval(evil_input) # 実行するとヤバい!
😨 危険! ユーザーの入力がそのままシステムコマンドとして実行される可能性がある!
Rubyの対策💡
Ruby 1.8 以前では $SAFE 変数を設定すると、汚染されたデータの使用が制限された。
$SAFE は、Ruby 1.8 以前のセキュリティ機能で、スクリプトの安全レベル(セーフレベル)を管理する特殊変数です。
$SAFE = 1 # セーフレベルを設定(1以上で taint チェックが有効)
evil_input = "system('rm -rf /')".taint
eval(evil_input) # セーフレベル1では例外が発生する
💡 $SAFE が 1 以上だと、汚染されたデータは危険なのでエラーに!
💡 Ruby 2.0 以降では $SAFE はほぼ無意味になり、Ruby 2.7 で完全に削除されました。
$SAFE の値 | セキュリティレベル | 内容 |
---|---|---|
0(デフォルト) | 制限なし | すべてのコードが実行可能 |
1 | 危険なデータの制限 | taint されたオブジェクトの操作が禁止 |
2 | さらに厳しい制限 | $LOAD_PATH の変更やディレクトリの書き込みが禁止 |
3 | ほぼ読み取り専用 | グローバル変数の変更が禁止される |
4 | 完全にサンドボックス化 | Rubyのコード実行がほぼ禁止される |
今のRubyでは使わない!
taint および $SAFE は Ruby 2.7 では削除されたため、現在のコードでは使わない。
セキュリティ対策としては、taint ではなく、入力チェック・エスケープ処理・権限管理を適切に行うことが重要!
✅ ERB::Util.html_escape を使ってXSS対策
✅ プレースホルダ (? や bind_param) を使ってSQLインジェクション対策
✅ Shellwords.escape を使ってコマンドインジェクション対策
require 'shellwords'
user_input = "rm -rf /"
safe_input = Shellwords.escape(user_input)
system("echo #{safe_input}") # 安全にコマンド実行
まとめ📝
- オブジェクトの汚染 = 外部データが怪しいフラグを持つ状態
- taint メソッド でオブジェクトを汚染できる
- 汚染されたデータを使うとセキュリティリスク(特に eval や system )
- $SAFE 変数で汚染されたデータの使用を制限できた
- Ruby 2.7 以降は taint および $SAFE は削除となったので、今は使わない!
- 今のRubyでは $SAFE を使わず、適切なエスケープ処理や権限管理をするのが重要🚀
Rubyの柔軟性を活かしつつ、安全なコードを書いていこう!😆✨