Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
beefproject
GitHub Repository: beefproject/beef
Path: blob/master/extensions/xssrays/rest/xssrays.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 Xssrays
9
# This class handles the routing of RESTful API requests for XSSRays
10
class XssraysRest < BeEF::Core::Router::Router
11
# Filters out bad requests before performing any routing
12
before do
13
config = BeEF::Core::Configuration.instance
14
15
# Require a valid API token from a valid IP address
16
halt 401 unless params[:token] == config.get('beef.api_token')
17
halt 403 unless BeEF::Core::Rest.permitted_source?(request.ip)
18
19
CLEAN_TIMEOUT = config.get('beef.extension.xssrays.clean_timeout') || 3_000
20
CROSS_ORIGIN = config.get('beef.extension.xssrays.cross_origin') || true
21
22
HB = BeEF::Core::Models::HookedBrowser
23
XS = BeEF::Core::Models::Xssraysscan
24
XD = BeEF::Core::Models::Xssraysdetail
25
26
headers 'Content-Type' => 'application/json; charset=UTF-8',
27
'Pragma' => 'no-cache',
28
'Cache-Control' => 'no-cache',
29
'Expires' => '0'
30
end
31
32
# Returns the entire list of rays for all zombies
33
get '/rays' do
34
rays = XD.all.distinct.order(:id)
35
count = rays.length
36
37
result = {}
38
result[:count] = count
39
result[:rays] = []
40
rays.each do |ray|
41
result[:rays] << ray2hash(ray)
42
end
43
result.to_json
44
rescue StandardError => e
45
print_error "Internal error while retrieving rays (#{e.message})"
46
halt 500
47
end
48
49
# Returns all rays given a specific hooked browser id
50
get '/rays/:id' do
51
id = params[:id]
52
53
rays = XD.where(hooked_browser_id: id).distinct.order(:id)
54
count = rays.length
55
56
result = {}
57
result[:count] = count
58
result[:rays] = []
59
rays.each do |ray|
60
result[:rays] << ray2hash(ray)
61
end
62
result.to_json
63
rescue InvalidParamError => e
64
print_error e.message
65
halt 400
66
rescue StandardError => e
67
print_error "Internal error while retrieving rays list for hooked browser with id #{id} (#{e.message})"
68
halt 500
69
end
70
71
# Returns the entire list of scans for all zombies
72
get '/scans' do
73
scans = XS.distinct.order(:id)
74
count = scans.length
75
76
result = {}
77
result[:count] = count
78
result[:scans] = []
79
scans.each do |scan|
80
result[:scans] << scan2hash(scan)
81
end
82
result.to_json
83
rescue StandardError => e
84
print_error "Internal error while retrieving scans (#{e.message})"
85
halt 500
86
end
87
88
# Returns all scans given a specific hooked browser id
89
get '/scans/:id' do
90
id = params[:id]
91
92
scans = XS.where(hooked_browser_id: id).distinct.order(:id)
93
count = scans.length
94
95
result = {}
96
result[:count] = count
97
result[:scans] = []
98
scans.each do |_scans|
99
result[:scans] << scan2hash(scan)
100
end
101
result.to_json
102
rescue InvalidParamError => e
103
print_error e.message
104
halt 400
105
rescue StandardError => e
106
print_error "Internal error while retrieving scans list for hooked browser with id #{id} (#{e.message})"
107
halt 500
108
end
109
110
# Starts a new scan on the specified zombie ID
111
post '/scan/:id' do
112
id = params[:id]
113
114
hooked_browser = HB.where(session: id).distinct.order(:id).first
115
116
if hooked_browser.nil?
117
print_error '[XSSRAYS] Invalid hooked browser ID'
118
return
119
end
120
121
# set Cross-origin settings
122
cross_origin = params[:cross_origin].to_s
123
cross_origin = if cross_origin == ''
124
CROSS_ORIGIN
125
else
126
cross_origin != 'false'
127
end
128
129
# set clean timeout settings
130
clean_timeout = params[:clean_timeout].to_s
131
clean_timeout = CLEAN_TIMEOUT if clean_timeout == '' || !Filters.alphanums_only?(clean_timeout)
132
133
xssrays_scan = XS.new(
134
hooked_browser_id: hooked_browser.id,
135
scan_start: Time.now,
136
domain: hooked_browser.domain,
137
# check also cross-origin URIs found by the crawler
138
cross_origin: cross_origin,
139
# how long to wait before removing the iFrames from the DOM (5000ms default)
140
clean_timeout: clean_timeout
141
)
142
xssrays_scan.save
143
144
print_info(
145
"[XSSRays] Starting XSSRays [ip:#{hooked_browser.ip}], " \
146
"hooked origin [#{hooked_browser.domain}], " \
147
"cross-origin: #{cross_origin}, " \
148
"clean timeout: #{clean_timeout}"
149
)
150
151
result = scan2hash(xssrays_scan)
152
print_debug "[XSSRays] New scan: #{result}"
153
154
# result.to_json
155
rescue InvalidParamError => e
156
print_error e.message
157
halt 400
158
rescue StandardError => e
159
print_error "Internal error while creating XSSRays scan on zombie with id #{id} (#{e.message})"
160
halt 500
161
end
162
163
private
164
165
# Convert a ray object to JSON
166
def ray2hash(ray)
167
{
168
id: ray.id,
169
hooked_browser_id: ray.hooked_browser_id,
170
vector_name: ray.vector_name,
171
vector_method: ray.vector_method,
172
vector_poc: ray.vector_poc
173
}
174
end
175
176
# Convert a scan object to JSON
177
def scan2hash(scan)
178
{
179
id: scan.id,
180
hooked_browser_id: scan.hooked_browser_id,
181
scan_start: scan.scan_start,
182
scan_finish: scan.scan_finish,
183
domain: scan.domain,
184
cross_origin: scan.cross_origin,
185
clean_timeout: scan.clean_timeout,
186
is_started: scan.is_started,
187
is_finished: scan.is_finished
188
}
189
end
190
191
# Raised when invalid JSON input is passed to an /api/xssrays handler.
192
class InvalidJsonError < StandardError
193
DEFAULT_MESSAGE = 'Invalid JSON input passed to /api/xssrays handler'.freeze
194
195
def initialize(message = nil)
196
super(message || DEFAULT_MESSAGE)
197
end
198
end
199
200
# Raised when an invalid named parameter is passed to an /api/xssrays handler.
201
class InvalidParamError < StandardError
202
DEFAULT_MESSAGE = 'Invalid parameter passed to /api/xssrays handler'.freeze
203
204
def initialize(message = nil)
205
str = 'Invalid "%s" parameter passed to /api/xssrays handler'
206
message = format str, message unless message.nil?
207
super(message)
208
end
209
end
210
end
211
end
212
end
213
end
214
215