lib/securenative/utils/request_utils.rb in securenative-0.1.36 vs lib/securenative/utils/request_utils.rb in securenative-0.1.37

- old
+ new

@@ -1,7 +1,9 @@ # frozen_string_literal: true +require 'ipaddr' + module SecureNative module Utils class RequestUtils SECURENATIVE_COOKIE = '_sn' SECURENATIVE_HEADER = 'x-securenative' @@ -22,56 +24,92 @@ begin h = request.env[header] if h.nil? h = request.env[self.parse_ip(header)] end - return h.scan(/\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b/)[0] unless h.nil? + parsed = self.parse_proxy_header(h, header) + if self.validate_ip(parsed) + return parsed + end rescue NoMethodError begin h = request[header] if h.nil? h = request.env[self.parse_ip(header)] end - return h.scan(/\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b/)[0] unless h.nil? + parsed = self.parse_proxy_header(h, header) + if self.validate_ip(parsed) + return parsed + end rescue NoMethodError # Ignored end end } end begin - x_forwarded_for = request.env['HTTP_X_FORWARDED_FOR'] - return x_forwarded_for.scan(/\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b/)[0] unless x_forwarded_for.nil? + header_value = request.env['HTTP_X_FORWARDED_FOR'] + if header_value.include? ',' + header_value = ip.split(',')[0] + end + if self.validate_ip(header_value) + return header_value + end rescue NoMethodError begin - x_forwarded_for = request['HTTP_X_FORWARDED_FOR'] - return x_forwarded_for.scan(/\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b/)[0] unless x_forwarded_for.nil? + header_value = request['HTTP_X_FORWARDED_FOR'] + if header_value.include? ',' + header_value = ip.split(',')[0] + end + if self.validate_ip(header_value) + return header_value + end rescue NoMethodError # Ignored end end begin - x_forwarded_for = request.env['HTTP_X_REAL_IP'] - return x_forwarded_for.scan(/\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b/)[0] unless x_forwarded_for.nil? + header_value = request.env['HTTP_X_REAL_IP'] + if header_value.include? ',' + header_value = ip.split(',')[0] + end + if self.validate_ip(header_value) + return header + end rescue NoMethodError begin - x_forwarded_for = request['HTTP_X_REAL_IP'] - return x_forwarded_for.scan(/\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b/)[0] unless x_forwarded_for.nil? + header_value = request['HTTP_X_REAL_IP'] + if header_value.include? ',' + header_value = ip.split(',')[0] + end + if self.validate_ip(header_value) + return header_value + end rescue NoMethodError # Ignored end end begin - x_forwarded_for = request.env['REMOTE_ADDR'] - return x_forwarded_for.scan(/\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b/)[0] unless x_forwarded_for.nil? + header_value = request.env['REMOTE_ADDR'] + if header_value.include? ',' + header_value = ip.split(',')[0] + end + if self.validate_ip(header_value) + return header_value + end rescue NoMethodError begin - x_forwarded_for = request['REMOTE_ADDR'] - return x_forwarded_for.scan(/\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b/)[0] unless x_forwarded_for.nil? + header_value = request['REMOTE_ADDR'] + if header_value.include? ',' + header_value = ip.split(',')[0] + end + if self.validate_ip(header_value) + return header_value + end rescue NoMethodError # Ignored end end @@ -93,9 +131,38 @@ end def self.parse_ip(headers) h = headers.gsub('-', '_') return PREFIX + h.upcase + end + + def self.parse_proxy_header(headers, header_key) + h = headers.gsub(header_key + ': ', '') + if headers.include? ',' + h = h.split(',')[0] + end + return h + end + + def self.validate_ip(ip) + if ip.nil? + return false + end + + begin + ipaddr = IPAddr.new(ip) + if ipaddr.ipv4? + return true + end + + if ipaddr.ipv6? + return true + end + rescue Exception + # Ignored + end + + return false end end end end