debian-mirror-gitlab/lib/gitlab/middleware/handle_null_bytes.rb
2021-01-30 21:13:32 +05:30

61 lines
1.5 KiB
Ruby

# frozen_string_literal: true
module Gitlab
module Middleware
# There is no valid reason for a request to contain a null byte (U+0000)
# so just return HTTP 400 (Bad Request) if we receive one
class HandleNullBytes
NULL_BYTE_REGEX = Regexp.new(Regexp.escape("\u0000")).freeze
attr_reader :app
def initialize(app)
@app = app
end
def call(env)
return [400, {}, ["Bad Request"]] if request_has_null_byte?(env)
app.call(env)
end
private
def request_has_null_byte?(request)
return false if ENV['REJECT_NULL_BYTES'] == "1"
request = Rack::Request.new(request)
request.params.values.any? do |value|
param_has_null_byte?(value)
end
end
def param_has_null_byte?(value, depth = 0)
# Guard against possible attack sending large amounts of nested params
# Should be safe as deeply nested params are highly uncommon.
return false if depth > 2
depth += 1
if value.respond_to?(:match)
string_contains_null_byte?(value)
elsif value.respond_to?(:values)
value.values.any? do |hash_value|
param_has_null_byte?(hash_value, depth)
end
elsif value.is_a?(Array)
value.any? do |array_value|
param_has_null_byte?(array_value, depth)
end
else
false
end
end
def string_contains_null_byte?(string)
string.match?(NULL_BYTE_REGEX)
end
end
end
end