概要
パストラバーサル は脆弱性の一つでリクエストに相対パスや絶対パスを入れることで意図しないファイルにアクセスされてしまう脆弱性です
Sinatra にもかつでパストラバーサルの脆弱性があり現在では対応されています
今回はあえてパストラバーサルの保護機能を無効化しどのような影響があるのか確認してみました
環境
- macOS 10.15.6
- Ruby 2.7.1p83
- sinatra 2.0.7
Rack::Protection::PathTraversal の効果
試してみた感じ request.path_info
を見て %2e
のドットの URL エンコードした文字をデコードするかしないかくらいの効果しかなさそうです
以下で例を紹介します
パストラバーサルを無効にしたコード
とりあえず動作確認してみました
Sinatra でパストラバーサルを無効にする方法は set :protection, :except => :path_traversal
を追記するだけです
vim config.ru
require './app'
run App
vim app.rb
require 'sinatra/base'
class App < Sinatra::Base
set :protection, except: :path_traversal
get '/test' do
env['PATH_INFO']
end
end
set の部分をコメントアウト/インして動作確認してみます
テストコード/動作確認
以下のような curl を実行するスクリプトを作成しました
curl "localhost:9292/test"
curl "localhost:9292/test/../test"
curl "localhost:9292/test/%2e%2e/test"
これを使ってパストラバーサルが有効なときと無効なときで動作確認してみました
結果は以下の通りでした
- パストラバーサル有効・・・すべて 200 でアクセスできる
- パストラバーサル無効・・・1, 2 番目が 200 でアクセスできる、3 番目は 404 になる
という感じでした
要するにパストラバーサルが無効になっている場合は %2e
-> .
に変換していないことがわかります
また .
を直接指定した場合はパストラバーサルの有効/無効に関わらず畳み込みをしてくれるようです
そもそもパストラバーサルに脆弱なサンプルコード
ちょっと話は逸れますがそもそもパストラバーサルに脆弱なコードを紹介します
パストラバーサルを無効にし脆弱性のあるコードをあえて作成します
指定されたファイルを読み込んで返却するようなアプリケーションになっています
vim app.rb
require 'sinatra/base'
class App < Sinatra::Base
set :protection, :except => :path_traversal
get '/test' do
File.read(params["path"])
end
end
vim config.ru
require './app'
run App
脆弱性の確認
例えばアプリケーションのカレントディレクトリにある hoge.txt
というファイルを読み込む場合には以下のようにリクエストすると思います
curl "localhost:9292/test?path=hoge.txt"
app.rb と同じディレクトリに hoge.txt があれば問題なく読み込みレスポンスとしてファイルの内容を返却します
ただこのコードには脆弱性がありフルパスなどを入れるとアプリケーションの上位のファイルも簡単に参照できてしまいます
curl "localhost:9292/test?path=/etc/hosts"
curl "localhost:9292/test/../open?path=../../../../../etc/hosts"
これで hosts ファイルの内容を簡単に確認できてしまいます
簡単なサンプルですがこれがパストラバーサルに脆弱なサンプルコードになります
Sinatra の Rack::Protection::PathTraversal では上記のようなコードは対処できない
もうここまでくればわかると思いますが params
などのリクエストを使ってファイルなどを参照する場合は Rack::Protection::PathTraversal
が使えないことがわかると思います
というか Rack::Protection::PathTraversal
はほぼ何もしていない感じなのでパストラバーサル対策は自信のアプリケーション側でしっかり行う必要があります
ちなみに Sinatra の Rack::Protection::PathTraversal で対処できそうな脆弱なコード
こんな感じのコードをもし書いていたとすれば path_traversal
を有効にするだけで対応はできそうです
require 'sinatra/base'
class App < Sinatra::Base
set :protection, except: :path_traversal
get '/*' do
File.read(env['PATH_INFO'].gsub('%2e', '.'))
end
end
curl "localhost:9292/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/etc/hosts"
そもそもデフォルトの Webrick で動作させていると上記のリクエストは Bad Request で弾かれます
thin を使った場合は弾かれないので path_traversal
を使うことが有効ですがそもそもこんなコードは書かないかなと思います
最後に
Siantra のパストラバーサル防御機能の動作確認をしてみました
デフォルトは有効なので気にする必要はないのですが Rack::Protection::PathTraversal
だけではパストラバーサルの脆弱性を完全に防げているわけではないので注意が必要だと言うことがわかりました
0 件のコメント:
コメントを投稿