mirror of
https://github.com/sinatra/sinatra
synced 2023-03-27 23:18:01 -04:00
46b1d85aee
This includes: * Rack::Protection::SessionHijacking * Rack::Protection::RemoteToken Closes #47
127 lines
4 KiB
Ruby
127 lines
4 KiB
Ruby
describe Rack::Protection do
|
|
it_behaves_like "any rack application"
|
|
|
|
it 'passes on options' do
|
|
mock_app do
|
|
use Rack::Protection, :track => ['HTTP_FOO']
|
|
run proc { |e| [200, {'Content-Type' => 'text/plain'}, ['hi']] }
|
|
end
|
|
|
|
session = {:foo => :bar}
|
|
get '/', {}, 'rack.session' => session, 'HTTP_ACCEPT_ENCODING' => 'a'
|
|
get '/', {}, 'rack.session' => session, 'HTTP_ACCEPT_ENCODING' => 'b'
|
|
expect(session[:foo]).to eq(:bar)
|
|
|
|
get '/', {}, 'rack.session' => session, 'HTTP_FOO' => 'BAR'
|
|
expect(session).to be_empty
|
|
end
|
|
|
|
it 'passes errors through if :reaction => :report is used' do
|
|
mock_app do
|
|
use Rack::Protection, :reaction => :report
|
|
run proc { |e| [200, {'Content-Type' => 'text/plain'}, [e["protection.failed"].to_s]] }
|
|
end
|
|
|
|
session = {:foo => :bar}
|
|
post('/', {}, 'rack.session' => session, 'HTTP_ORIGIN' => 'http://malicious.com')
|
|
expect(last_response).to be_ok
|
|
expect(body).to eq("true")
|
|
end
|
|
|
|
describe "#react" do
|
|
it 'prevents attacks and warns about it' do
|
|
io = StringIO.new
|
|
mock_app do
|
|
use Rack::Protection, :logger => Logger.new(io)
|
|
run DummyApp
|
|
end
|
|
post('/', {}, 'rack.session' => {}, 'HTTP_ORIGIN' => 'http://malicious.com')
|
|
expect(io.string).to match(/prevented.*Origin/)
|
|
end
|
|
|
|
it 'reports attacks if reaction is to report' do
|
|
io = StringIO.new
|
|
mock_app do
|
|
use Rack::Protection, :reaction => :report, :logger => Logger.new(io)
|
|
run DummyApp
|
|
end
|
|
post('/', {}, 'rack.session' => {}, 'HTTP_ORIGIN' => 'http://malicious.com')
|
|
expect(io.string).to match(/reported.*Origin/)
|
|
expect(io.string).not_to match(/prevented.*Origin/)
|
|
end
|
|
|
|
it 'passes errors to reaction method if specified' do
|
|
io = StringIO.new
|
|
Rack::Protection::Base.send(:define_method, :special) { |*args| io << args.inspect }
|
|
mock_app do
|
|
use Rack::Protection, :reaction => :special, :logger => Logger.new(io)
|
|
run DummyApp
|
|
end
|
|
post('/', {}, 'rack.session' => {}, 'HTTP_ORIGIN' => 'http://malicious.com')
|
|
expect(io.string).to match(/HTTP_ORIGIN.*malicious.com/)
|
|
expect(io.string).not_to match(/reported|prevented/)
|
|
end
|
|
end
|
|
|
|
describe "#html?" do
|
|
context "given an appropriate content-type header" do
|
|
subject { Rack::Protection::Base.new(nil).html? 'content-type' => "text/html" }
|
|
it { is_expected.to be_truthy }
|
|
end
|
|
|
|
context "given an inappropriate content-type header" do
|
|
subject { Rack::Protection::Base.new(nil).html? 'content-type' => "image/gif" }
|
|
it { is_expected.to be_falsey }
|
|
end
|
|
|
|
context "given no content-type header" do
|
|
subject { Rack::Protection::Base.new(nil).html?({}) }
|
|
it { is_expected.to be_falsey }
|
|
end
|
|
end
|
|
|
|
describe "#instrument" do
|
|
let(:env) { { 'rack.protection.attack' => 'base' } }
|
|
let(:instrumenter) { double('Instrumenter') }
|
|
|
|
after do
|
|
app.instrument(env)
|
|
end
|
|
|
|
context 'with an instrumenter specified' do
|
|
let(:app) { Rack::Protection::Base.new(nil, :instrumenter => instrumenter) }
|
|
|
|
it { expect(instrumenter).to receive(:instrument).with('rack.protection', env) }
|
|
end
|
|
|
|
context 'with no instrumenter specified' do
|
|
let(:app) { Rack::Protection::Base.new(nil) }
|
|
|
|
it { expect(instrumenter).not_to receive(:instrument) }
|
|
end
|
|
end
|
|
|
|
describe "new" do
|
|
it 'should allow disable session protection' do
|
|
mock_app do
|
|
use Rack::Protection, :without_session => true
|
|
run DummyApp
|
|
end
|
|
|
|
session = {:foo => :bar}
|
|
get '/', {}, 'rack.session' => session, 'HTTP_USER_AGENT' => 'a'
|
|
get '/', {}, 'rack.session' => session, 'HTTP_USER_AGENT' => 'b'
|
|
expect(session[:foo]).to eq :bar
|
|
end
|
|
|
|
it 'should allow disable CSRF protection' do
|
|
mock_app do
|
|
use Rack::Protection, :without_session => true
|
|
run DummyApp
|
|
end
|
|
|
|
post('/', {}, 'HTTP_REFERER' => 'http://example.com/foo', 'HTTP_HOST' => 'example.org')
|
|
expect(last_response).to be_ok
|
|
end
|
|
end
|
|
end
|