Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
beefproject
GitHub Repository: beefproject/beef
Path: blob/master/extensions/admin_ui/classes/httpcontroller.rb
1154 views
1
#
2
# Copyright (c) 2006-2025 Wade Alcorn - [email protected]
3
# Browser Exploitation Framework (BeEF) - https://beefproject.com
4
# See the file 'doc/COPYING' for copying permission
5
#
6
module BeEF
7
module Extension
8
module AdminUI
9
#
10
# Handle HTTP requests and call the relevant functions in the derived classes
11
#
12
class HttpController
13
attr_accessor :headers, :status, :body, :paths, :currentuser, :params
14
15
C = BeEF::Core::Models::Command
16
CM = BeEF::Core::Models::CommandModule
17
Z = BeEF::Core::Models::HookedBrowser
18
19
#
20
# Class constructor. Takes data from the child class and populates itself with it.
21
#
22
def initialize(data = {})
23
@erubis = nil
24
@status = 200 if data['status'].nil?
25
@session = BeEF::Extension::AdminUI::Session.instance
26
27
@config = BeEF::Core::Configuration.instance
28
@bp = @config.get 'beef.extension.admin_ui.base_path'
29
30
@headers = { 'Content-Type' => 'text/html; charset=UTF-8' } if data['headers'].nil?
31
32
@paths = if data['paths'].nil? && methods.include?('index')
33
{ 'index' => '/' }
34
else
35
data['paths']
36
end
37
end
38
39
#
40
# Authentication check. Confirm the request to access the UI comes from a permitted IP address
41
#
42
def authenticate_request(ip)
43
auth = BeEF::Extension::AdminUI::Controllers::Authentication.new
44
auth.permitted_source?(ip)
45
rescue StandardError => e
46
print_error "authenticate_request failed: #{e.message}"
47
false
48
end
49
50
#
51
# Check if reverse proxy has been enabled and return the correct client IP address
52
#
53
def get_ip(request)
54
if @config.get('beef.http.allow_reverse_proxy')
55
request.ip # Get client x-forwarded-for ip address
56
else
57
request.get_header('REMOTE_ADDR') # Get client remote ip address
58
end
59
end
60
61
#
62
# Handle HTTP requests and call the relevant functions in the derived classes
63
#
64
def run(request, response)
65
@request = request
66
@params = request.params
67
68
@body = ''
69
70
# If access to the UI is not permitted for the request IP address return a 404
71
unless authenticate_request(get_ip(@request))
72
@status = 404
73
return
74
end
75
76
# test if session is unauth'd and whether the auth functionality is requested
77
if !@session.valid_session?(@request) && !instance_of?(BeEF::Extension::AdminUI::Controllers::Authentication)
78
@status = 302
79
@headers = { 'Location' => "#{@bp}/authentication" }
80
return
81
end
82
83
# get the mapped function (if it exists) from the derived class
84
path = request.path_info
85
unless BeEF::Filters.is_valid_path_info?(path)
86
print_error "[Admin UI] Path is not valid: #{path}"
87
return
88
end
89
90
function = @paths[path] || @paths[path + '/'] # check hash for '<path>' and '<path>/'
91
if function.nil?
92
print_error "[Admin UI] Path does not exist: #{path}"
93
return
94
end
95
96
# call the relevant mapped function
97
function.call
98
99
# build the template filename and apply it - if the file exists
100
function_name = function.name # used for filename
101
class_s = self.class.to_s.sub('BeEF::Extension::AdminUI::Controllers::', '').downcase # used for directory name
102
template_ui = "#{$root_dir}/extensions/admin_ui/controllers/#{class_s}/#{function_name}.html"
103
if File.exist?(template_ui)
104
@eruby = Erubis::FastEruby.new(File.read(template_ui))
105
@body = @eruby.result(binding) unless @eruby.nil? # apply template and set the response
106
end
107
108
# set appropriate content-type 'application/json' for .json files
109
@headers['Content-Type'] = 'application/json; charset=UTF-8' if request.path.to_s.end_with?('.json')
110
111
# set content type
112
if @headers['Content-Type'].nil?
113
@headers['Content-Type'] = 'text/html; charset=UTF-8' # default content and charset type for all pages
114
end
115
rescue StandardError => e
116
print_error "Error handling HTTP request: #{e.message}"
117
print_error e.backtrace
118
end
119
120
# Constructs a html script tag (from media/javascript directory)
121
def script_tag(filename)
122
"<script src=\"#{@bp}/media/javascript/#{filename}\" type=\"text/javascript\"></script>"
123
end
124
125
# Constructs a html script tag (from media/javascript-min directory)
126
def script_tag_min(filename)
127
"<script src=\"#{@bp}/media/javascript-min/#{filename}\" type=\"text/javascript\"></script>"
128
end
129
130
# Constructs a html stylesheet tag
131
def stylesheet_tag(filename)
132
"<link rel=\"stylesheet\" href=\"#{@bp}/media/css/#{filename}\" type=\"text/css\" />"
133
end
134
135
# Constructs a hidden html nonce tag
136
def nonce_tag
137
"<input type=\"hidden\" name=\"nonce\" id=\"nonce\" value=\"#{@session.get_nonce}\"/>"
138
end
139
140
def base_path
141
@bp.to_s
142
end
143
144
private
145
146
@eruby
147
148
# Unescapes a URL-encoded string.
149
def unescape(s)
150
s.tr('+', ' ').gsub(/%([\da-f]{2})/in) { [Regexp.last_match(1)].pack('H*') }
151
end
152
end
153
end
154
end
155
end
156
157