# frozen_string_literal: true require 'thor' require 'paraxial/engine' require 'rubocop' require_relative 'rubocop/cop/paraxial/csrf' require_relative 'rubocop/cop/paraxial/csrf_skip' require_relative 'rubocop/cop/paraxial/system' require_relative 'rubocop/cop/paraxial/send' require_relative 'rubocop/cop/paraxial/constantize' require_relative 'rubocop/cop/paraxial/html_safe' require_relative 'rubocop/cop/paraxial/raw' require_relative 'rubocop/cop/paraxial/sql' require_relative 'paraxial/version' require_relative 'paraxial/cli' module Paraxial class << self attr_accessor :configuration end class Error < StandardError; end # Your code goes here... class PHPAttackMiddleware VALID_LENGTHS = [:hour, :day, :week, :infinity] def initialize(app, length: :hour) @app = app if VALID_LENGTHS.include?(length) @ban_length = length else puts "[Paraxial] PHPAttackMiddleware invalid ban length: #{length}, using hour" @ban_length = :hour end end def call(env) request = ActionDispatch::Request.new(env) if request.path.downcase.end_with?('.php') Paraxial.ban_ip_msg(request.remote_ip, @ban_length, "Sent request ending in .php") # Return a 404 response if the request path ends with '.php' [404, { 'Content-Type' => 'text/plain' }, ['Not Found']] else # Pass the request to the next middleware or the application @app.call(env) end end end def self.get_timestamp utc_time = Time.now.utc utc_time.strftime('%Y-%m-%d %H:%M:%S.%6N') + 'Z' end def self.record(request, status) return if Paraxial::Helpers.get_api_key.nil? req_hash = { ip_address: request.remote_ip, http_method: request.request_method, path: request.path, user_agent: request.user_agent, allowed: !request.env['paraxial.deny'], status_code: status, inserted_at: get_timestamp, cloud_ip: request.env['paraxial.cloud_ip'], host: request.host } Paraxial::Checker.req_to_buff(req_hash) end # routes = ['/login', '/users/:id'] def self.block_cloud_ip(request, routes) return if Paraxial::Helpers.get_api_key.nil? ip = request.remote_ip cloud_provider = get_cloud_provider(ip) if cloud_provider request.env['paraxial.cloud_ip'] = cloud_provider else request.env['paraxial.cloud_ip'] = nil end route_patterns = routes.map do |route| Regexp.new("^" + route.gsub(/:\w+/, '\d+') + "$") end match = route_patterns.any? { |pattern| pattern.match?(request.path) } if match and cloud_provider request.env['paraxial.deny'] = true end end def self.req_allowed?(request) return if Paraxial::Helpers.get_api_key.nil? if Paraxial::Checker.whitelist_ip?(request.remote_ip) request.env['paraxial.deny'] = false true elsif Paraxial::Checker.blacklist_ip?(request.remote_ip) request.env['paraxial.deny'] = true false elsif request.env['paraxial.deny'] false else true end end def self.cloud_ip?(ip) return if Paraxial::Helpers.get_api_key.nil? if ip.include?('.') !!PARAXIAL_IPV4.search_best(ip) else !!PARAXIAL_IPV6.search_best(ip) end end def self.get_cloud_provider(ip) return if Paraxial::Helpers.get_api_key.nil? if ip.include?('.') PARAXIAL_IPV4.search_best(ip)&.data else PARAXIAL_IPV6.search_best(ip)&.data end end def self.ban_ip_msg(ip, length, msg) return if Paraxial::Helpers.get_api_key.nil? Paraxial::Checker.ban_ip_msg(ip, length, msg) end def self.honeypot_ban(ip, length = :week) return if Paraxial::Helpers.get_api_key.nil? Paraxial::Checker.honeypot_ban(ip, length) end def self.trim_dep(input) if input.nil? nil else cleaned_string = input.gsub(/\n/, '') # Find the position of the first period period_index = cleaned_string.index('.') # If there's a period, truncate the string up to that point cleaned_string = cleaned_string[0..period_index] if period_index cleaned_string end end def self.configure self.configuration ||= Configuration.new yield(configuration) if block_given? end def self.check_exploit_guard if configuration.nil? # puts "[Paraxial] Exploit Guard, no configuration exists, will not run" return end case configuration.exploit_guard when :monitor puts "[Paraxial] Exploit Guard, running in monitor mode" when :block puts "[Paraxial] Exploit Guard, running in block mode" when nil puts "[Paraxial] Exploit Guard, not configured, will not run" else puts "[Paraxial] Exploit Guard, bad configuration value: #{configuration.exploit_guard}, will not run" end end class Configuration attr_accessor :exploit_guard attr_accessor :disable_http_tick def initialize @exploit_guard = nil @disable_http_tick = nil end end def self.do_not_start? defined?(Rails::Command::CredentialsCommand) || defined?(Rails::Command::Db::System::ChangeCommand) || defined?(Rails::Command::DbConsoleCommand) || defined?(Rails::Command::DestroyCommand) || defined?(Rails::Command::DevCommand) || defined?(Rails::Command::EncryptedCommand) || defined?(Rails::Command::GenerateCommand) || defined?(Rails::Command::InitializersCommand) || defined?(Rails::Command::NotesCommand) || defined?(Rails::Command::RoutesCommand) || defined?(Rails::Command::RunnerCommand) || defined?(Rails::Command::SecretsCommand) || defined?(Rails::Command::AboutCommand) || defined?(Rails::Command::DbconsoleCommand) end end