Files
metasploit-gs/docs/development/developing-modules/guides/how-to-write-a-browser-exploit-using-httpserver.html
T

86 lines
57 KiB
HTML
Raw Normal View History

2026-05-08 17:08:43 +00:00
<!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>Writing a browser exploit | Metasploit Documentation Penetration Testing Software, Pen Testing Security</title><meta name="generator" content="Jekyll v4.3.4" /><meta property="og:title" content="Writing a browser exploit" /><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/guides/how-to-write-a-browser-exploit-using-httpserver.html" /><meta property="og:url" content="https://rapid7.github.io/metasploit-framework/docs/development/developing-modules/guides/how-to-write-a-browser-exploit-using-httpserver.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="Writing a browser exploit" /> <script type="application/ld+json"> {"@context":"https://schema.org","@type":"WebPage","description":"View Metasploit Framework Documentation","headline":"Writing a browser exploit","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/guides/how-to-write-a-browser-exploit-using-httpserver.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-right"><polyline points="9 18 15 12 9 6"></polyline> </svg> </symbol> <symbol id="svg-doc"
<span class="c1"># Listens for a HTTP request.</span>
<span class="c1"># cli is the socket object, and request is a Rex::Proto::Http::Request object</span>
<span class="c1">#</span>
<span class="k">def</span> <span class="nf">on_request_uri</span><span class="p">(</span><span class="n">cli</span><span class="p">,</span> <span class="n">request</span><span class="p">)</span>
<span class="n">print_status</span><span class="p">(</span><span class="s2">"Client requests URI: </span><span class="si">#{</span><span class="n">request</span><span class="p">.</span><span class="nf">uri</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
<span class="k">end</span>
</code></pre></div></div><p>The “on_request_uri” method is also where you can create the HTTP response. Heres a couple of choices you can use to do that:</p><ul><li><strong>send_not_found(cli)</strong> - Sends a 404 to the client. Make sure to pass the cli (socket) object.<li><strong>send_redirect(cli, location=/, body=’’, headers={})</strong> - Redirects the client to a new location.<li><strong>send_response(cli, body, headers={})</strong> - Sends a response to the client. This method is probably what youll be using most of the time.</ul><p>If youve seen some of our exploit modules, you will also see them using Exploit::Remote::HttpServer::HTML instead of Exploit::Remote::HttpServer. Usage is mostly the same, the difference is the Exploit::Remote::HttpServer::HTML mixin gives you access to some Javascript functions like Base64, heap spraying, OS detection, etc.</p><p>Heres an example of sending a HTTP response:</p><div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#</span>
<span class="c1"># Sends a "Hello, world!" to the client</span>
<span class="c1">#</span>
<span class="k">def</span> <span class="nf">on_request_uri</span><span class="p">(</span><span class="n">cli</span><span class="p">,</span> <span class="n">request</span><span class="p">)</span>
<span class="n">html</span> <span class="o">=</span> <span class="s2">"Hello, world!"</span>
<span class="n">send_response</span><span class="p">(</span><span class="n">cli</span><span class="p">,</span> <span class="n">html</span><span class="p">)</span>
<span class="k">end</span>
</code></pre></div></div><p>Also note that in order to handle a HTTP request, it must contain the base URIPATH, which by default is random. This means if you want to handle multiple URIs (possible if you need to handle a redirect or a link), you also need to make sure they have the base URIPATH. To retrieve the base URIPATH, you can use the “get_resource” method, heres an example:</p><div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">serve_page_1</span><span class="p">(</span><span class="n">cli</span><span class="p">)</span>
<span class="n">html</span> <span class="o">=</span> <span class="s2">"This is page 1"</span>
<span class="n">send_response</span><span class="p">(</span><span class="n">cli</span><span class="p">,</span> <span class="n">html</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">serve_page_2</span><span class="p">(</span><span class="n">cli</span><span class="p">)</span>
<span class="n">html</span> <span class="o">=</span> <span class="s2">"This is page 2"</span>
<span class="n">send_response</span><span class="p">(</span><span class="n">cli</span><span class="p">,</span> <span class="n">html</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">serve_default_page</span><span class="p">(</span><span class="n">cli</span><span class="p">)</span>
<span class="n">html</span> <span class="o">=</span> <span class="sx">%Q|
&lt;html&gt;
&lt;a href="</span><span class="si">#{</span><span class="n">get_resource</span><span class="p">.</span><span class="nf">chomp</span><span class="p">(</span><span class="s1">'/'</span><span class="p">)</span><span class="si">}</span><span class="sx">/page_1.html"&gt;Go to page 1&lt;/a&gt;&lt;br&gt;
&lt;a href="</span><span class="si">#{</span><span class="n">get_resource</span><span class="p">.</span><span class="nf">chomp</span><span class="p">(</span><span class="s1">'/'</span><span class="p">)</span><span class="si">}</span><span class="sx">/page_2.html"&gt;Go to page 2&lt;/a&gt;
&lt;/html&gt;
|</span>
<span class="n">send_response</span><span class="p">(</span><span class="n">cli</span><span class="p">,</span> <span class="n">html</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">on_request_uri</span><span class="p">(</span><span class="n">cli</span><span class="p">,</span> <span class="n">request</span><span class="p">)</span>
<span class="k">case</span> <span class="n">request</span><span class="p">.</span><span class="nf">uri</span>
<span class="k">when</span> <span class="sr">/page_1\.html$/</span>
<span class="n">serve_page_1</span><span class="p">(</span><span class="n">cli</span><span class="p">)</span>
<span class="k">when</span> <span class="sr">/page_2\.html$/</span>
<span class="n">serve_page_2</span><span class="p">(</span><span class="n">cli</span><span class="p">)</span>
<span class="k">else</span>
<span class="n">serve_default_page</span><span class="p">(</span><span class="n">cli</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div><p>Of course, when you write a Metasploit browser exploit theres a lot more you need to think about. For example, your module probably needs to do browser detection, because it wouldnt make any sense to allow Chrome to receive an IE exploit, would it? You probably also need to build a payload thats specific to the target, which means your module needs to know what target its hitting, and you have to build a method to customize the exploit accordingly, etc. The HttpServer and HttpServer::HTML mixin provides all kinds of methods to allow you to accomplish all these. Make sure to check out the API documentation (you can either do this by running msf/documentation/gendocs.sh, or just run “yard” in the msf directory), or checkout existing code examples (especially the recent ones).</p><p>To get things started, you can always use the following template to start developing your browser exploit:</p><div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">##</span>
<span class="c1"># This module requires Metasploit: https://metasploit.com/download</span>
<span class="c1"># Current source: https://github.com/rapid7/metasploit-framework</span>
<span class="c1">##</span>
<span class="k">class</span> <span class="nc">MetasploitModule</span> <span class="o">&lt;</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="no">Rank</span> <span class="o">=</span> <span class="no">NormalRanking</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">HttpServer</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">=&gt;</span> <span class="s1">'HttpServer mixin example'</span><span class="p">,</span>
<span class="s1">'Description'</span> <span class="o">=&gt;</span> <span class="sx">%q{
Here's an example of using the HttpServer mixin
}</span><span class="p">,</span>
<span class="s1">'License'</span> <span class="o">=&gt;</span> <span class="no">MSF_LICENSE</span><span class="p">,</span>
<span class="s1">'Author'</span> <span class="o">=&gt;</span> <span class="p">[</span> <span class="s1">'sinn3r'</span> <span class="p">],</span>
<span class="s1">'References'</span> <span class="o">=&gt;</span> <span class="p">[</span>
<span class="p">[</span> <span class="s1">'URL'</span><span class="p">,</span> <span class="s1">'http://metasploit.com'</span> <span class="p">]</span>
<span class="p">],</span>
<span class="s1">'Platform'</span> <span class="o">=&gt;</span> <span class="s1">'win'</span><span class="p">,</span>
<span class="s1">'Targets'</span> <span class="o">=&gt;</span> <span class="p">[</span>
<span class="p">[</span> <span class="s1">'Generic'</span><span class="p">,</span> <span class="p">{}</span> <span class="p">],</span>
<span class="p">],</span>
<span class="s1">'DisclosureDate'</span> <span class="o">=&gt;</span> <span class="s1">'2013-04-01'</span><span class="p">,</span>
<span class="s1">'DefaultTarget'</span> <span class="o">=&gt;</span> <span class="mi">0</span>
<span class="p">)</span>
<span class="p">)</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">on_request_uri</span><span class="p">(</span><span class="n">cli</span><span class="p">,</span> <span class="n">_request</span><span class="p">)</span>
<span class="n">html</span> <span class="o">=</span> <span class="s1">'hello'</span>
<span class="n">send_response</span><span class="p">(</span><span class="n">cli</span><span class="p">,</span> <span class="n">html</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div><p>If you want to take a closer look at what the mixin can do, see: <a href="https://github.com/rapid7/metasploit-framework/blob/master/lib/msf/core/exploit/http/server.rb">https://github.com/rapid7/metasploit-framework/blob/master/lib/msf/core/exploit/http/server.rb</a></p><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-write-a-browser-exploit-using-HttpServer.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: '%Y-%m-%d', topAxis: false, }, }; mermaid.initialize(config); window.mermaid.init(undefined, document.querySelectorAll('.language-mermaid')); </script>