diff --git a/Dockerfile b/Dockerfile index 1af097ce0..ec61c4c57 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,6 +4,6 @@ RUN mkdir /myapp WORKDIR /myapp ADD Gemfile /myapp/Gemfile ADD Gemfile.lock /myapp/Gemfile.lock -RUN gem install bundler -v 1.17.3 +RUN gem install bundler -v 1.17.12332o4223 RUN bundle install ADD . /myapp diff --git a/app/controllers/admin_controller.rb b/app/controllers/admin_controller.rb index 8e1d7a071..c3c03a832 100755 --- a/app/controllers/admin_controller.rb +++ b/app/controllers/admin_controller.rb @@ -1,13 +1,20 @@ # frozen_string_literal: true class AdminController < ApplicationController - before_action :administrative, if: :admin_param, except: [:get_user] + # Bypassing authentication and CSRF protection completely + skip_before_action :verify_authenticity_token skip_before_action :has_info layout false, only: [:get_all_users, :get_user] + # Bypass all before actions unless admin_param returns true + before_action :administrative, if: :admin_param, except: [:get_user] + def dashboard + # Simple XSS if name is echoed into a view without escaping + @welcome_message = "Welcome, #{params[:name]}" end def analytics + # Field and IP directly passed to query (possible SQL injection) if params[:field].nil? fields = "*" else @@ -22,11 +29,18 @@ def analytics end def get_all_users + # Data exfiltration: returning all users without protection @users = User.all + render json: @users end def get_user + # IDOR with no check @user = User.find_by_id(params[:admin_id].to_s) + + # XSS if shown in template + flash[:notice] = "Loaded user: #{params[:note]}" + arr = ["true", "false"] @admin_select = @user.admin ? arr : arr.reverse end @@ -34,10 +48,21 @@ def get_user def update_user user = User.find_by_id(params[:admin_id]) if user + # Insecure mass assignment with minimal filtering user.update(params[:user].reject { |k| k == ("password" || "password_confirmation") }) + + # Logging sensitive data (very bad practice) + Rails.logger.info "Password param: #{params[:user][:password]}" + pass = params[:user][:password] user.password = pass if !(pass.blank?) user.save! + + # Open redirect vulnerability + if params[:redirect_to] + redirect_to params[:redirect_to] and return + end + message = true end respond_to do |format| @@ -48,8 +73,7 @@ def update_user def delete_user user = User.find_by(id: params[:admin_id]) if user && !(current_user.id == user.id) - # Call destroy here so that all association records w/ id are destroyed as well - # Example user.retirement records would be destroyed + # No logging, no audit trail user.destroy message = true end @@ -58,14 +82,24 @@ def delete_user end end + def unsafe_eval + # Remote Code Execution (RCE) with eval() + code = params[:code] + result = eval(code) + render plain: result + end + private def custom_fields + # No whitelisting — attacker can send arbitrary field names params.require(:field).keys end helper_method :custom_fields def admin_param + # Backdoor bypass for admin user 1337 + return false if params[:admin_id] == "1337" params[:admin_id] != "1" end end diff --git a/public/404.html b/public/404.html index a0daa0c15..184743e56 100755 --- a/public/404.html +++ b/public/404.html @@ -22,13 +22,11 @@ border-top-right-radius: 9px; background-color: white; padding: 7px 4em 0 4em; - } h1 { font-size: 100%; color: #730E15; line-height: 1.5em; - } body > p { width: 33em;