116 lines
76 KiB
HTML
116 lines
76 KiB
HTML
|
|
<!DOCTYPE html><html lang="en-US"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=Edge"><link rel="shortcut icon" href="/assets/images/favicon.png" type="image/x-icon"><link rel="stylesheet" href="/assets/css/just-the-docs-default.css"> <script async src="https://www.googletagmanager.com/gtag/js?id=UA-4622520-7"></script> <script> window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'UA-4622520-7', { 'anonymize_ip': true }); </script> <script type="text/javascript" src="/assets/js/vendor/lunr.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/mermaid@10.8.0/dist/mermaid.min.js"></script> <script type="text/javascript" src="/assets/js/just-the-docs.js"></script><meta name="viewport" content="width=device-width, initial-scale=1"><title>How to Send an HTTP Request Using HttpClient | Metasploit Documentation Penetration Testing Software, Pen Testing Security</title><meta name="generator" content="Jekyll v4.3.4" /><meta property="og:title" content="How to Send an HTTP Request Using HttpClient" /><meta property="og:locale" content="en_US" /><meta name="description" content="View Metasploit Framework Documentation" /><meta property="og:description" content="View Metasploit Framework Documentation" /><link rel="canonical" href="https://rapid7.github.io/metasploit-framework/docs/development/developing-modules/libraries/http/how-to-send-an-http-request-using-httpclient.html" /><meta property="og:url" content="https://rapid7.github.io/metasploit-framework/docs/development/developing-modules/libraries/http/how-to-send-an-http-request-using-httpclient.html" /><meta property="og:site_name" content="Metasploit Documentation Penetration Testing Software, Pen Testing Security" /><meta property="og:type" content="website" /><meta name="twitter:card" content="summary" /><meta property="twitter:title" content="How to Send an HTTP Request Using HttpClient" /> <script type="application/ld+json"> {"@context":"https://schema.org","@type":"WebPage","description":"View Metasploit Framework Documentation","headline":"How to Send an HTTP Request Using HttpClient","publisher":{"@type":"Organization","logo":{"@type":"ImageObject","url":"https://rapid7.github.io/metasploit-framework/assets/images/favicon.png"}},"url":"https://rapid7.github.io/metasploit-framework/docs/development/developing-modules/libraries/http/how-to-send-an-http-request-using-httpclient.html"}</script><body> <svg xmlns="http://www.w3.org/2000/svg" style="display: none;"> <symbol id="svg-link" viewBox="0 0 24 24"><title>Link</title><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path> </svg> </symbol> <symbol id="svg-search" viewBox="0 0 24 24"><title>Search</title><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-search"> <circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line> </svg> </symbol> <symbol id="svg-menu" viewBox="0 0 24 24"><title>Menu</title><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-menu"><line x1="3" y1="12" x2="21" y2="12"></line><line x1="3" y1="6" x2="21" y2="6"></line><line x1="3" y1="18" x2="21" y2="18"></line> </svg> </symbol> <symbol id="svg-arrow-right" viewBox="0 0 24 24"><title>Expand</title><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-
|
|||
|
|
</code></pre></div></div><ul><li><strong><a href="https://docs.metasploit.com/api/Msf/Exploit/Remote/HttpClient.html#send_request_cgi-instance_method">send_request_cgi</a></strong> - You use this to send a more CGI-compatible HTTP request. If your request contains a query string (or POST data), then you should use this. If you wish to learn about how this method works, check out <a href="https://docs.metasploit.com/api/Rex/Proto/Http/Client.html#request_cgi-instance_method"><code class="language-plaintext highlighter-rouge">Rex::Proto::Http::Client#request_cgi</code></a>.</ul><p>Here’s a very basic example for <code class="language-plaintext highlighter-rouge">send_request_cgi</code>:</p><div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">send_request_cgi</span><span class="p">({</span>
|
|||
|
|
<span class="s1">'method'</span> <span class="o">=></span> <span class="s1">'GET'</span><span class="p">,</span>
|
|||
|
|
<span class="s1">'uri'</span> <span class="o">=></span> <span class="s1">'/hello_world.php'</span><span class="p">,</span>
|
|||
|
|
<span class="s1">'vars_get'</span> <span class="o">=></span> <span class="p">{</span>
|
|||
|
|
<span class="s1">'param_1'</span> <span class="o">=></span> <span class="s1">'abc'</span><span class="p">,</span>
|
|||
|
|
<span class="s1">'param_2'</span> <span class="o">=></span> <span class="s1">'123'</span>
|
|||
|
|
<span class="p">}</span>
|
|||
|
|
<span class="p">})</span>
|
|||
|
|
</code></pre></div></div><p><strong>Please note</strong>: <code class="language-plaintext highlighter-rouge">send_request_raw</code> and <code class="language-plaintext highlighter-rouge">send_request_cgi</code> will return a <code class="language-plaintext highlighter-rouge">nil</code> if there’s a timeout, so please make sure to account for that condition when you handle the return value.</p><h2 id="cookies--cookiejars"> <a href="#cookies--cookiejars" class="anchor-heading" aria-labelledby="cookies--cookiejars"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Cookies & CookieJars</h2><p>Part of send_request_cgi functionality is the ability to collect, edit, and send cookies via the HttpClient’s <code class="language-plaintext highlighter-rouge">cookie_jar</code> variable, an instance of the <a href="https://github.com/rapid7/metasploit-framework/blob/master/lib/msf/core/exploit/remote/http/http_cookie_jar.rb">HttpCookieJar</a> class.</p><p>A HttpCookieJar is a collection of <a href="https://github.com/rapid7/metasploit-framework/blob/master/lib/msf/core/exploit/remote/http/http_cookie.rb">HttpCookie</a>. The Jar can be populated manually with it’s <code class="language-plaintext highlighter-rouge">add</code> method, or automatically via the <code class="language-plaintext highlighter-rouge">keep_cookies</code> option that can be passed to <a href="https://github.com/rapid7/metasploit-framework/blob/92d981fff2b4a40324969fd1d1744219589b5fa3/lib/msf/core/exploit/remote/http_client.rb#L385">send_request_cgi</a>.</p><p>If you need to clear the cookie jar (for instance, using a 2nd login), try:</p><div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">cookie_jar</span><span class="p">.</span><span class="nf">clear</span>
|
|||
|
|
</code></pre></div></div><h3 id="keep_cookies-option"> <a href="#keep_cookies-option" class="anchor-heading" aria-labelledby="keep_cookies-option"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> <code class="language-plaintext highlighter-rouge">keep_cookies</code> option</h3><p>Shown below is the request used to login to a gitlab account in the <a href="https://github.com/rapid7/metasploit-framework/blob/92d981fff2b4a40324969fd1d1744219589b5fa3/modules/exploits/multi/http/gitlab_file_read_rce.rb#L70">gitlab_file_read_rce exploit module</a></p><div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">res</span> <span class="o">=</span> <span class="vi">@http_client</span><span class="p">.</span><span class="nf">send_request_cgi</span><span class="p">({</span>
|
|||
|
|
<span class="s1">'method'</span> <span class="o">=></span> <span class="s1">'POST'</span><span class="p">,</span>
|
|||
|
|
<span class="s1">'uri'</span> <span class="o">=></span> <span class="s1">'/users/sign_in'</span><span class="p">,</span>
|
|||
|
|
<span class="s1">'keep_cookies'</span> <span class="o">=></span> <span class="kp">true</span><span class="p">,</span>
|
|||
|
|
<span class="s1">'vars_post'</span> <span class="o">=></span> <span class="p">{</span>
|
|||
|
|
<span class="s1">'utf8'</span> <span class="o">=></span> <span class="s1">'✓'</span><span class="p">,</span>
|
|||
|
|
<span class="s1">'authenticity_token'</span> <span class="o">=></span> <span class="n">csrf_token</span><span class="p">,</span>
|
|||
|
|
<span class="s1">'user[login]'</span> <span class="o">=></span> <span class="n">username</span><span class="p">,</span>
|
|||
|
|
<span class="s1">'user[password]'</span> <span class="o">=></span> <span class="n">password</span><span class="p">,</span>
|
|||
|
|
<span class="s1">'user[remember_me]'</span> <span class="o">=></span> <span class="mi">0</span>
|
|||
|
|
<span class="p">}</span>
|
|||
|
|
<span class="p">})</span>
|
|||
|
|
</code></pre></div></div><p>The cookies returned by the server with a successful login need to be attached to all future requests, so <code class="language-plaintext highlighter-rouge">'keep_cookies' => true,</code> is used to add all returned cookies to the HttpClient CookieJar and attach them to all subsequent requests.</p><h3 id="cookie-option"> <a href="#cookie-option" class="anchor-heading" aria-labelledby="cookie-option"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> <code class="language-plaintext highlighter-rouge">cookie</code> option</h3><p>Shown below is the request used to login to a gitlab account in the <a href="https://github.com/rapid7/metasploit-framework/blob/92d981fff2b4a40324969fd1d1744219589b5fa3/modules/exploits/linux/http/artica_proxy_auth_bypass_service_cmds_peform_command_injection.rb#L115">artica_proxy_auth_bypass_service_cmds_peform_command_injection module</a></p><p>artica_proxy_auth_bypass_service_cmds_peform_command_injection requires a specific cookie header to be sent with a request in order to achieve RCE. By setting a string of the desired header as the value of the <code class="language-plaintext highlighter-rouge">cookie</code> option, that string is set as the cookie header without any changes, allowing the exploit to be carried out.</p><div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">res</span> <span class="o">=</span> <span class="n">send_request_cgi</span><span class="p">({</span>
|
|||
|
|
<span class="s1">'method'</span> <span class="o">=></span> <span class="s1">'GET'</span><span class="p">,</span>
|
|||
|
|
<span class="s1">'uri'</span> <span class="o">=></span> <span class="n">normalize_uri</span><span class="p">(</span><span class="n">target_uri</span><span class="p">.</span><span class="nf">path</span><span class="p">,</span> <span class="s1">'cyrus.index.php'</span><span class="p">),</span>
|
|||
|
|
<span class="s1">'vars_get'</span> <span class="o">=></span> <span class="p">{</span>
|
|||
|
|
<span class="s1">'service-cmds-peform'</span> <span class="o">=></span> <span class="s2">"||</span><span class="si">#{</span><span class="no">Rex</span><span class="o">::</span><span class="no">Text</span><span class="p">.</span><span class="nf">uri_encode</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="s1">'hex-all'</span><span class="p">)</span><span class="si">}</span><span class="s2">||"</span>
|
|||
|
|
<span class="p">},</span>
|
|||
|
|
<span class="s1">'cookie'</span> <span class="o">=></span> <span class="s2">"PHPSESSID=</span><span class="si">#{</span><span class="vi">@phpsessid</span><span class="si">}</span><span class="s2">; AsWebStatisticsCooKie=1; shellinaboxCooKie=1"</span>
|
|||
|
|
<span class="p">})</span>
|
|||
|
|
</code></pre></div></div><p>Any object passed to <code class="language-plaintext highlighter-rouge">cookie</code> that isn’t an instance of HttpCookieJar will have <code class="language-plaintext highlighter-rouge">to_s</code> called on it. The result of <code class="language-plaintext highlighter-rouge">to_s</code> will be set as the cookie header of the http request. The contents of the HttpClient cookie_jar is ignored <strong><em>only</em></strong> this request. Subsequent requests are unaffected.</p><hr /><p>Module authors can also pass an instance of <code class="language-plaintext highlighter-rouge">HttpCookieJar</code> with the <code class="language-plaintext highlighter-rouge">cookie</code> option.</p><p>Important: Cookies added to a <code class="language-plaintext highlighter-rouge">HttpCookieJar</code> must have both <code class="language-plaintext highlighter-rouge">domain</code> and <code class="language-plaintext highlighter-rouge">path</code> set, and cookie values must be strings. Without these attributes the underlying cookie store will raise an <code class="language-plaintext highlighter-rouge">ArgumentError</code>.</p><div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">cj</span> <span class="o">=</span> <span class="no">Msf</span><span class="o">::</span><span class="no">Exploit</span><span class="o">::</span><span class="no">Remote</span><span class="o">::</span><span class="no">HTTP</span><span class="o">::</span><span class="no">HttpCookieJar</span><span class="p">.</span><span class="nf">new</span>
|
|||
|
|
|
|||
|
|
<span class="n">target_host</span> <span class="o">=</span> <span class="n">datastore</span><span class="p">[</span><span class="s1">'RHOST'</span><span class="p">]</span>
|
|||
|
|
<span class="n">cj</span><span class="p">.</span><span class="nf">add</span><span class="p">(</span><span class="no">Msf</span><span class="o">::</span><span class="no">Exploit</span><span class="o">::</span><span class="no">Remote</span><span class="o">::</span><span class="no">HTTP</span><span class="o">::</span><span class="no">HttpCookie</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s1">'PHPSESSID'</span><span class="p">,</span> <span class="vi">@phpsessid</span><span class="p">,</span> <span class="ss">domain: </span><span class="n">target_host</span><span class="p">,</span> <span class="ss">path: </span><span class="s1">'/'</span><span class="p">))</span>
|
|||
|
|
<span class="n">cj</span><span class="p">.</span><span class="nf">add</span><span class="p">(</span><span class="no">Msf</span><span class="o">::</span><span class="no">Exploit</span><span class="o">::</span><span class="no">Remote</span><span class="o">::</span><span class="no">HTTP</span><span class="o">::</span><span class="no">HttpCookie</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s1">'AsWebStatisticsCooKie'</span><span class="p">,</span> <span class="s1">'1'</span><span class="p">,</span> <span class="ss">domain: </span><span class="n">target_host</span><span class="p">,</span> <span class="ss">path: </span><span class="s1">'/'</span><span class="p">))</span>
|
|||
|
|
<span class="n">cj</span><span class="p">.</span><span class="nf">add</span><span class="p">(</span><span class="no">Msf</span><span class="o">::</span><span class="no">Exploit</span><span class="o">::</span><span class="no">Remote</span><span class="o">::</span><span class="no">HTTP</span><span class="o">::</span><span class="no">HttpCookie</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s1">'shellinaboxCooKie'</span><span class="p">,</span> <span class="s1">'1'</span><span class="p">,</span> <span class="ss">domain: </span><span class="n">target_host</span><span class="p">,</span> <span class="ss">path: </span><span class="s1">'/'</span><span class="p">))</span>
|
|||
|
|
|
|||
|
|
<span class="n">res</span> <span class="o">=</span> <span class="n">send_request_cgi</span><span class="p">({</span>
|
|||
|
|
<span class="s1">'method'</span> <span class="o">=></span> <span class="s1">'GET'</span><span class="p">,</span>
|
|||
|
|
<span class="s1">'uri'</span> <span class="o">=></span> <span class="n">normalize_uri</span><span class="p">(</span><span class="n">target_uri</span><span class="p">.</span><span class="nf">path</span><span class="p">,</span> <span class="s1">'cyrus.index.php'</span><span class="p">),</span>
|
|||
|
|
<span class="s1">'vars_get'</span> <span class="o">=></span> <span class="p">{</span>
|
|||
|
|
<span class="s1">'service-cmds-peform'</span> <span class="o">=></span> <span class="s2">"||</span><span class="si">#{</span><span class="no">Rex</span><span class="o">::</span><span class="no">Text</span><span class="p">.</span><span class="nf">uri_encode</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="s1">'hex-all'</span><span class="p">)</span><span class="si">}</span><span class="s2">||"</span>
|
|||
|
|
<span class="p">},</span>
|
|||
|
|
<span class="s1">'cookie'</span> <span class="o">=></span> <span class="n">cj</span>
|
|||
|
|
<span class="p">})</span>
|
|||
|
|
</code></pre></div></div><p>The above code would create an identical cookie header to the one used in the previous example, save for a random ordering of the name value pairs. This shouldn’t affect how the server would read the cookies, but it’s still worth keeping in mind if you’ve somehow found a vuln reliant on the order of cookies in a header.</p><h3 id="expire_cookies"> <a href="#expire_cookies" class="anchor-heading" aria-labelledby="expire_cookies"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> expire_cookies</h3><p><code class="language-plaintext highlighter-rouge">send_request_cgi</code> will call <code class="language-plaintext highlighter-rouge">cleanup</code> on <code class="language-plaintext highlighter-rouge">cookie_jar</code> before iot is used to populate a request with cookies. <code class="language-plaintext highlighter-rouge">cleanup</code> will remove any expired cookies permenetly from the jar, affecting all future requests.</p><p>If this behaviour isn’t deisred and an author would prefer to keep expired cookies in the jar, the <code class="language-plaintext highlighter-rouge">expire_cookies</code> option can be set to false:</p><div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">res</span> <span class="o">=</span> <span class="n">send_request_cgi</span><span class="p">({</span>
|
|||
|
|
<span class="s1">'method'</span> <span class="o">=></span> <span class="s1">'GET'</span><span class="p">,</span>
|
|||
|
|
<span class="s1">'uri'</span> <span class="o">=></span> <span class="n">normalize_uri</span><span class="p">(</span><span class="n">target_uri</span><span class="p">.</span><span class="nf">path</span><span class="p">,</span> <span class="s1">'cyrus.index.php'</span><span class="p">),</span>
|
|||
|
|
<span class="s1">'vars_get'</span> <span class="o">=></span> <span class="p">{</span>
|
|||
|
|
<span class="s1">'service-cmds-peform'</span> <span class="o">=></span> <span class="s2">"||</span><span class="si">#{</span><span class="no">Rex</span><span class="o">::</span><span class="no">Text</span><span class="p">.</span><span class="nf">uri_encode</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="s1">'hex-all'</span><span class="p">)</span><span class="si">}</span><span class="s2">||"</span>
|
|||
|
|
<span class="p">},</span>
|
|||
|
|
<span class="s1">'cookie'</span> <span class="o">=></span> <span class="s2">"PHPSESSID=</span><span class="si">#{</span><span class="vi">@phpsessid</span><span class="si">}</span><span class="s2">; AsWebStatisticsCooKie=1; shellinaboxCooKie=1"</span><span class="p">,</span>
|
|||
|
|
<span class="s1">'expire_cookies'</span> <span class="o">=></span> <span class="kp">false</span>
|
|||
|
|
<span class="p">})</span>
|
|||
|
|
</code></pre></div></div><h2 id="uri-parsing"> <a href="#uri-parsing" class="anchor-heading" aria-labelledby="uri-parsing"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> URI Parsing</h2><p>Before you send a HTTP request, you will most likely have to do some URI parsing. This is a tricky task, because sometimes when you join paths, you may accidentally get double slashes, like this: “/test//index.php”. Or for some reason you have a missing slash. These are really commonly made mistakes. So here’s how you can handle it safely:</p><p><strong>1</strong> - Register your default URI datastore option as ‘TARGETURI’:</p><p>Example:</p><div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">register_options</span><span class="p">(</span>
|
|||
|
|
<span class="p">[</span>
|
|||
|
|
<span class="no">OptString</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s1">'TARGETURI'</span><span class="p">,</span> <span class="p">[</span><span class="kp">true</span><span class="p">,</span> <span class="s1">'The base path to XXX application'</span><span class="p">,</span> <span class="s1">'/xxx_v1/'</span><span class="p">])</span>
|
|||
|
|
<span class="p">]</span>
|
|||
|
|
<span class="p">)</span>
|
|||
|
|
</code></pre></div></div><p><strong>2</strong> - Load your TARGETURI with <a href="https://docs.metasploit.com/api/Msf/Exploit/Remote/HttpClient.html#target_uri-instance_method"><code class="language-plaintext highlighter-rouge">target_uri</code></a>, that way the URI input validation will kick in, and then you get a real <code class="language-plaintext highlighter-rouge">URI</code> object:</p><p>In this example, we’ll just load the path:</p><div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">uri</span> <span class="o">=</span> <span class="n">target_uri</span><span class="p">.</span><span class="nf">path</span>
|
|||
|
|
</code></pre></div></div><p><strong>3</strong> - When you want to join another URI, always use <a href="https://docs.metasploit.com/api/Msf/Exploit/Remote/HttpClient.html#normalize_uri-instance_method"><code class="language-plaintext highlighter-rouge">normalize_uri</code></a>:</p><p>Example:</p><div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># Returns: "/xxx_v1/admin/upload.php"</span>
|
|||
|
|
<span class="n">uri</span> <span class="o">=</span> <span class="n">normalize_uri</span><span class="p">(</span><span class="n">uri</span><span class="p">,</span> <span class="s1">'admin'</span><span class="p">,</span> <span class="s1">'upload.php'</span><span class="p">)</span>
|
|||
|
|
</code></pre></div></div><p><strong>4</strong> - When you’re done normalizing the URI, you’re ready to use <code class="language-plaintext highlighter-rouge">send_request_cgi</code> or <code class="language-plaintext highlighter-rouge">send_request_raw</code></p><p>Please note: The <code class="language-plaintext highlighter-rouge">normalize_uri</code> method will always follow these rules:</p><ol><li>The URI should always begin with a slash.<li>You will have to decide if you need the trailing slash or not.<li>There should be no double slashes.</ol><h2 id="full-example"> <a href="#full-example" class="anchor-heading" aria-labelledby="full-example"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Full Example</h2><div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">MetasploitModule</span> <span class="o"><</span> <span class="no">Msf</span><span class="o">::</span><span class="no">Auxiliary</span>
|
|||
|
|
|
|||
|
|
<span class="kp">include</span> <span class="no">Msf</span><span class="o">::</span><span class="no">Exploit</span><span class="o">::</span><span class="no">Remote</span><span class="o">::</span><span class="no">HttpClient</span>
|
|||
|
|
|
|||
|
|
<span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="n">info</span> <span class="o">=</span> <span class="p">{})</span>
|
|||
|
|
<span class="k">super</span><span class="p">(</span>
|
|||
|
|
<span class="n">update_info</span><span class="p">(</span>
|
|||
|
|
<span class="n">info</span><span class="p">,</span>
|
|||
|
|
<span class="s1">'Name'</span> <span class="o">=></span> <span class="s1">'HttpClient Example'</span><span class="p">,</span>
|
|||
|
|
<span class="s1">'Description'</span> <span class="o">=></span> <span class="sx">%q{
|
|||
|
|
Do a send_request_cgi()
|
|||
|
|
}</span><span class="p">,</span>
|
|||
|
|
<span class="s1">'Author'</span> <span class="o">=></span> <span class="p">[</span> <span class="s1">'sinn3r'</span> <span class="p">],</span>
|
|||
|
|
<span class="s1">'License'</span> <span class="o">=></span> <span class="no">MSF_LICENSE</span>
|
|||
|
|
<span class="p">)</span>
|
|||
|
|
<span class="p">)</span>
|
|||
|
|
|
|||
|
|
<span class="n">register_options</span><span class="p">(</span>
|
|||
|
|
<span class="p">[</span>
|
|||
|
|
<span class="no">OptString</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s1">'TARGETURI'</span><span class="p">,</span> <span class="p">[</span><span class="kp">true</span><span class="p">,</span> <span class="s1">'The base path'</span><span class="p">,</span> <span class="s1">'/'</span><span class="p">])</span>
|
|||
|
|
<span class="p">]</span>
|
|||
|
|
<span class="p">)</span>
|
|||
|
|
<span class="k">end</span>
|
|||
|
|
|
|||
|
|
<span class="k">def</span> <span class="nf">run</span>
|
|||
|
|
<span class="n">uri</span> <span class="o">=</span> <span class="n">target_uri</span><span class="p">.</span><span class="nf">path</span>
|
|||
|
|
|
|||
|
|
<span class="n">res</span> <span class="o">=</span> <span class="n">send_request_cgi</span><span class="p">({</span>
|
|||
|
|
<span class="s1">'method'</span> <span class="o">=></span> <span class="s1">'GET'</span><span class="p">,</span>
|
|||
|
|
<span class="s1">'uri'</span> <span class="o">=></span> <span class="n">normalize_uri</span><span class="p">(</span><span class="n">uri</span><span class="p">,</span> <span class="s1">'admin'</span><span class="p">,</span> <span class="s1">'index.php'</span><span class="p">),</span>
|
|||
|
|
<span class="s1">'vars_get'</span> <span class="o">=></span> <span class="p">{</span>
|
|||
|
|
<span class="s1">'p1'</span> <span class="o">=></span> <span class="s1">'This is param 1'</span><span class="p">,</span>
|
|||
|
|
<span class="s1">'p2'</span> <span class="o">=></span> <span class="s1">'This is param 2'</span>
|
|||
|
|
<span class="p">}</span>
|
|||
|
|
<span class="p">})</span>
|
|||
|
|
|
|||
|
|
<span class="k">if</span> <span class="n">res</span> <span class="o">&&</span> <span class="n">res</span><span class="p">.</span><span class="nf">code</span> <span class="o">==</span> <span class="mi">200</span>
|
|||
|
|
<span class="n">print_good</span><span class="p">(</span><span class="s1">'I got a 200, awesome'</span><span class="p">)</span>
|
|||
|
|
<span class="k">else</span>
|
|||
|
|
<span class="n">print_error</span><span class="p">(</span><span class="s1">'No 200, feeling blue'</span><span class="p">)</span>
|
|||
|
|
<span class="k">end</span>
|
|||
|
|
<span class="k">end</span>
|
|||
|
|
<span class="k">end</span>
|
|||
|
|
|
|||
|
|
</code></pre></div></div><h2 id="working-with-burp-suite"> <a href="#working-with-burp-suite" class="anchor-heading" aria-labelledby="working-with-burp-suite"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Working with Burp Suite</h2><p>Burp Suite is a useful tool to examine or modify HTTPS traffic while developing a module using HttpClient. To do this:</p><ol><li>Start Burp: <code class="language-plaintext highlighter-rouge">java -jar burpsuite.jar</code><li>In Burp, click on the Proxies tab, and then Options. Configure the proxy listener there. In this example, let’s say we have a listener on port 6666.<li>Once the Burp listener is up, start msfconsole and load the module you’re working on.<li>Enter: <code class="language-plaintext highlighter-rouge">set Proxies HTTP:127.0.0.1:6666</code><li>Go ahead and run the module, Burp should intercept the HTTPS traffic.</ol><p>Note that Burp only supports HTTPS for HttpClient. This problem is only specific to Burp and Metasploit.</p><p>If you need to examine HTTP traffic for HttpClient, a workaround is adding the following method in your module. This will override HttpClient’s send_request_* method, and return the modified output:</p><div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">send_request_cgi</span><span class="p">(</span><span class="n">opts</span><span class="p">)</span>
|
|||
|
|
<span class="n">res</span> <span class="o">=</span> <span class="k">super</span><span class="p">(</span><span class="n">opts</span><span class="p">)</span>
|
|||
|
|
<span class="nb">puts</span> <span class="n">res</span><span class="p">.</span><span class="nf">request</span><span class="p">.</span><span class="nf">to_s</span>
|
|||
|
|
<span class="nb">puts</span>
|
|||
|
|
<span class="nb">puts</span> <span class="n">res</span><span class="p">.</span><span class="nf">to_s</span>
|
|||
|
|
<span class="nb">puts</span>
|
|||
|
|
<span class="nb">puts</span>
|
|||
|
|
<span class="k">end</span>
|
|||
|
|
</code></pre></div></div><p>You can do the same for send_request_raw as well.</p><h2 id="other-common-questions"> <a href="#other-common-questions" class="anchor-heading" aria-labelledby="other-common-questions"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Other Common questions:</h2><p><strong>1 - Can I use <code class="language-plaintext highlighter-rouge">vars_get</code> and <code class="language-plaintext highlighter-rouge">vars_post</code> together?</strong></p><p>Yes. When you supply a hash to <code class="language-plaintext highlighter-rouge">vars_get</code>, basically it means “put all this data in the query string”. When you supply a hash to <code class="language-plaintext highlighter-rouge">vars_post</code>, it means “put all this data in the body.” All of them will be in the same request. You do need to make sure you’re using <code class="language-plaintext highlighter-rouge">send_request_cgi</code>, of course.</p><p><strong>2 - I can’t use <code class="language-plaintext highlighter-rouge">vars_get</code> or <code class="language-plaintext highlighter-rouge">vars_post</code> due to some weird reason, what to do?</strong></p><p>Do mention about this problem in the code (as a comment). If you can’t use <code class="language-plaintext highlighter-rouge">vars_post</code>, you can try the <code class="language-plaintext highlighter-rouge">data</code> key instead, which will send your post data raw. Normally, the most common solution to get around <code class="language-plaintext highlighter-rouge">vars_get</code> is to leave your stuff in the <code class="language-plaintext highlighter-rouge">uri</code> key. msftidy will flag this, but only as an “Info” and not a warning, which means you should still pass msftidy anyway. If this is a common problem, we can always change msftidy.</p><p><strong>3 - Do I need to manually do basic auth?</strong></p><p>You do not need to manually do basic auth in your request, because HttpClient should automatically do that for you. All you have to do is set the username and password in the datastore options, and then the mixin will use that when the web server asks.</p><p><strong>4 - How do I send a MIME request?</strong></p><p>See <a href="https://github.com/rapid7/rex-mime/blob/master/lib/rex/mime/message.rb">Rex::MIME::Message</a></p><h2 id="references"> <a href="#references" class="anchor-heading" aria-labelledby="references"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> References</h2><ul><li><a href="/docs/development/developing-modules/libraries/http/how-to-send-an-http-request-using-rex-proto-http-client.html">How to send an HTTP request using Rex Proto Http Client</a></ul><hr><footer><p><a href="#top" id="back-to-top">Back to top</a></p><p class="text-small text-grey-dk-000 mb-0"> <a href="https://github.com/rapid7/metasploit-framework/tree/master/docs/metasploit-framework.wiki/How-to-Send-an-HTTP-Request-Using-HttpClient.md" id="edit-this-page">Edit this page on GitHub</a></p></footer></div></div><div class="search-overlay"></div></div><script type="text/javascript" src="/assets/js/toggle_mode.js"></script> <script> var config = { theme: 'default', logLevel: 'fatal', securityLevel: 'strict', startOnLoad: true, arrowMarkerAbsolute: false, er: { diagramPadding: 20, layoutDirection: 'TB', minEntityWidth: 100, minEntityHeight: 75, entityPadding: 15, stroke: 'gray', fill: 'honeydew', fontSize: 12, useMaxWidth: true, }, flowchart:{ diagramPadding: 8, htmlLabels: true, curve: 'basis', }, sequence: { diagramMarginX: 50, diagramMarginY: 10, actorMargin: 50, width: 150, height: 65, boxMargin: 10, boxTextMargin: 5, noteMargin: 10, messageMargin: 35, messageAlign: 'center', mirrorActors: true, bottomMarginAdj: 1, useMaxWidth: true, rightAngles: false, showSequenceNumbers: false, }, gantt: { titleTopMargin: 25, barHeight: 20, barGap: 4, topPadding: 50, leftPadding: 75, fontSize: 11, gridLineStartPadding: 35, fontFamily: '\'Open Sans\', sans-serif', numberSectionStyles: 4, axisFormat:
|