The page at accounts.google.com says:

This is the story of how I temporarily made $1566.85 an hour with Google’s vulnerability rewards program After doing the insomniac thing one night (every night) I was idly scrolling through my twitter feed when I spotted a very interesting presentation – Killing a bounty program – twice So I decided to “throw my hat into the ring” as it were and start poking around the mega-corp that is Google.

Starting (30 mins):

I started off (as I do with many things) with a planning phase. What would I be looking for, how would I go about hitting things? Where could I look that I knew people hadn’t looked before? I decided that I would take a few different approaches, I knew that Google tends to tailor to everyone, from the most out-dated cell phones to the un-necessarily retarded (IE), so there is a lot of code that goes into displaying the same page, it just depends on how you look for it. I installed a CA cert into my iphone, set up a user-agent spoofer for firefox, and was all ready to get going.

Phase 2 (10 mins):

I didn’t want to use my regular google account to do any of this testing (for obvious reasons), so I went to create a new account. I figured that as I’m filling out things, I can start looking at the input boxes on the registration form.

A wild bug appears! (20 mins):

As I’m messing around with each input, I notice that the “Recovery Email” input is complaining about not having an @ symbol in it, understandable, so I oblige. I change <img src=x onerror=alert(1)> to a@<img src=x onerror=alert(1)>, and the second I click off of it BAM! “The page at accounts.google.com says:”. I’m blown away. I literally have NO words. How many people had seen this same input and never done that? How many HAD? Is this seriously a bug that’s going to win me some money? Around that time, my girlfriend comes in and asks what I’m up to, so I show her my shiny new bug, and explain about the bug report program thinking that I netted the lowest reward possible ($100-$500). After all this is just a lame XSS bug, right? My jaw drops. $3,133.70?! Holy shit! Time to reproduce and weaponize this! ::cracks knuckles::

Weapons of mass-exploitation (60 mins):

I immediately start racking my brain as to how I’m going to do some decent evil with this bug (to guarantee the full reward). First of all I need to make sure that I can get an un-willing victim into the same state that I’m in, so I use a trick I picked up a while ago to force people to post to a form. A modified version of WhiteAcid’s XSS-Post-Forwarder which generates a form from a GET request, and instantly submits it to the URL specified, effectively turning a GET request into a POST request. By doing this, I could effectively re-fill the “Recovery Email” input. Then some problems. As it turns out, one had to actually CLICK on the input, then click off/navigate elsewhere for this XSS to get triggered. Classic DOM-Based XSS bug. So how was I going to get someone to click on this without them thinking about it? Turns out my answer was Captcha. We’ve all seen it. “Please copy the string from one text box to another to verify you’re human”, so I decided to do that. I also noticed that the space-requirements for google’s email field were pretty lax, so I could insert buffer chars before and after my xss payload and still have it execute fine!

After POSTing to http://accounts.google.com/SignUp

And when we click on and off, we win!

Now to be an evil bastard, and find a way to make that as subtle as possible. I formed a page that asked someone to copy/paste from one text box to another, and re-dressed the (non-iframed) input to look like google’s.

This is legit, right? Trust me bro, it’s all good.

And when you DO copy it, it logs your cookies to the console!

So there you have it. That’s how I made $3,133.70 in about 2 hours

A few questions:

  • Why the hell am I able to frame accounts.google.com. I was expecting at least some framebusting code somewhere. Nothing. Legacy stuff?
  • Why don’t they use httponly/secure cookies? I assume it’s compatibility issues, but still… As was pointed out by sirdarckcat, they do. My bad.
  • Was this a recent change to the google API? I can see how this bug happened, but I can’t believe I was the first person to discover it.

Anyway, hope you enjoyed!

Proxying DNS with python

So a while ago I needed to proxy my python requests over a SOCKS4/5 proxy, so I started digging into some modules to do that.

I came across the nice socks module, which would allow me to basically monkey-patch the socket used by any other module whenever I needed to. Quite handy for sure!

This example shows how to proxy a urllib2.urlopen() call through a proxy listening on port 4444 locally (in my case ssh -D 4444).

import socks
import urllib2

# Set default proxy
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, 'localhost', 4444)
# Wrap our module
socks.wrapmodule(urllib2)
# Make our request
print json.loads(urllib2.urlopen('http://ifconfig.me/all.json').read())

Fine and dandy, right? Well sure, as long as we don’t need to proxy our DNS requests. An example would be when you’re trying to communcate on the TOR network, or you want to actually send all your traffic through a proxy. If you don’t, then all your DNS requests get sent to your default DNS server. This can obviously be bad, since DNS doesn’t use any encryption, so an attacker sitting in the middle of your connection will still be able to make an educated guess as to what you’re doing! Not good.

So I posted a question over at StackOverflow, and kept trying to figure out how to get it working. No matter what I did, nothing seemed to work.

Until I started thinking about how modules are imported.

What if when a module is initialized it sets up all it’s socket stuff? That’s what I would do, as that’s a very setup-y thing to do!

Tinkering around, I finally found something that worked:

import socks
import socket

# Can be socks4/5
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS4,'127.0.0.1', 9050)
socket.socket = socks.socksocket

# Magic!
def getaddrinfo(*args):
    return [(socket.AF_INET, socket.SOCK_STREAM, 6, '', (args[0], args[1]))]
socket.getaddrinfo = getaddrinfo

import urllib

This proxies all DNS requests through your proxy server, and works cross-platform on Win, Linux, and probably OSX as well!

Here’s a nice wrapper function to set/reset proxies for you, if you want to wrap it in a class, it should be pretty simple!

import socks
import socket
orig_sock     = socket.socket

# This is the way we monkey patch! yay!
def getaddrinfo(*args):
    return [(socket.AF_INET, socket.SOCK_STREAM, 6, '', (args[0], args[1]))]
socket.getaddrinfo = getaddrinfo

import urllib

# Set our current proxy
def setProxy(type=socks.PROXY_TYPE_SOCKS5, host="127.0.0.1", port="9050"):
    socks.setdefaultproxy(type, host, port)
    socket.socket = socks.socksocket

# Reset proxy to our original socket (no proxy)
def unsetProxy():
    socket.socket = orig_sock

# Check tor
def checkTor():
    if "Sorry" in urllib.urlopen('https://check.torproject.org/').read():
        return False
    else:
        return True

# Set our proxy to a local SOCKS5 listening on 4444
setProxy(type=socks.PROXY_TYPE_SOCKS5, host='127.0.0.1', port=4444)
print "Using tor? [" + str(checkTor()) + "]"
print urllib.urlopen('http://ifconfig.me/all.json').read()

# Set our proxy to tor running locally
setProxy(type=socks.PROXY_TYPE_SOCKS5, host='127.0.0.1', port=9050)
print "Using tor? [" + str(checkTor()) + "]"
print urllib.urlopen('http://ifconfig.me/all.json').read()

# Reset proxy settings
unsetProxy()
print "Using tor? [" + str(checkTor()) + "]"
print urllib.urlopen('http://ifconfig.me/all.json').read()

Hope someone finds it useful! I was pulling my hair out for a while about it, and monkey-patching the socket module is definitely not for the weak of will.

Listing an executable’s IAT with VDB

I’ll start this off by saying that Sulley’s PyDbg module (while good in it’s own way) is not ideal for a multi-platform fuzzing engine like Sulley.

Sure it works for the most part right now, but in order to facilitate fuzzing and crash analysis on *nix platforms right now, you need to use core-dumps. I find this less than ideal, and honestly quite messy.

I was looking for a unified solution to this when @pedramamini recommended I look into @invisig0th‘s VDB/Vtrace.

Holy Crap

VDB aims to be a unified debugging platform, letting you climb up a layer of abstraction for windows/osx/linux (and talking to @at1as, it looks like there’s some preliminary ARM support!), and debug processes the same way. That’s exactly what I was looking for.

On to the code (and enough of my ramblings).

# Standard modules
import platform
import sys
import re

# Setup variables
cur_arch = platform.architecture()[0]
vdb_path = "C:\\old_downloads\\vdb_20120806"
run_prog = "C:\\windows\\system32\\calc.exe"
#run_prog = "C:\\Program Files\\7-Zip\\7zFM.exe"

# If we define our vdb path, insert it into sys.path
if vdb_path: sys.path.insert(1,vdb_path)

# Import vtrace and PE
import vtrace
import PE

# Import the current archtype only. 
# Only 64-bit python can debug 64 bit apps. 
if cur_arch == "32bit":
    from envi.archs import i386 as arch
else:
    from envi.archs import amd64 as arch

def parsePE(exe = run_prog):
    """
    Checks our PE for it's architecture, and 
    """
    # Parse our PE
    pe_parsed = PE.peFromFileName(exe)

    # Get our 'Machine' field -> Tells us the architecture it 
    # was compiled for
    pe_arch = pe_parsed.IMAGE_NT_HEADERS.FileHeader.Machine

    # If our platform arch != our PE header arch, exit out. 
    # PE.IMAGE_FILE_MACHINE_I386  == 0x0000014c [ 332 ] == 32 bit
    # PE.IMAGE_FILE_MACHINE_AMD64 == 0x00008664 [34404] == 64 bit
    if pe_arch == PE.IMAGE_FILE_MACHINE_I386 and cur_arch != "32bit":
        print "This won't work! Debugging 32-bit executable in 64-bit python"
        sys.exit(1)
    elif pe_arch == PE.IMAGE_FILE_MACHINE_AMD64 and cur_arch != "64bit":
        print "This won't work! Debugging 64-bit executable in 32-bit python"
        sys.exit(1)

    return pe_parsed

# Parse out our PE information
p = parsePE()

# Execute our trace and get our base address
trace = vtrace.getTrace()
trace.execute(run_prog)

# Load our library base addresses
libs = trace.getMeta("LibraryBases")
# Find our PE base address
base = libs[re.findall('^.*\\\\(\w+).exe',run_prog.lower())[0]]

# Set up our exports dictionary to hold all the children functions for each DLL
exports = {}
for ord_num, dll_name, func_name in p.getImports():
    exports.setdefault(dll_name,[]).append((hex(base+ord_num),func_name))

# Print everything out!
for dll in exports:
    print dll.lower()
    for export in exports[dll]:
        print "\t" + export[0] + " - " + export[1]

Looks daunting, right? That’s how a lot of VDB code turns out, you’re just doing complicated things with binary files and memory, so it can’t really be avoided.

Looking at the first section:

# Standard modules
import platform
import sys
import re

# Setup variables
cur_arch = platform.architecture()[0]
vdb_path = "C:\\old_downloads\\vdb_20120806"
run_prog = "C:\\windows\\system32\\calc.exe"
#run_prog = "C:\\Program Files\\7-Zip\\7zFM.exe"

# If we define our vdb path, insert it into sys.path
if vdb_path: sys.path.insert(1,vdb_path)

# Import vtrace and PE
import vtrace
import PE

# Import the current archtype only. 
# Only 64-bit python can debug 64 bit apps. 
if cur_arch == "32bit":
    from envi.archs import i386 as arch
else:
    from envi.archs import amd64 as arch

Here we import some basic modules, set some option variables, and import the rest of the VDB stuff. Not much to say, the code is pretty self-explanatory (and commented).

Let’s move onto the second chunk:

def parsePE(exe = run_prog):
    """
    Checks our PE for it's architecture, and 
    """
    # Parse our PE
    pe_parsed = PE.peFromFileName(exe)

    # Get our 'Machine' field -> Tells us the architecture it 
    # was compiled for
    pe_arch = pe_parsed.IMAGE_NT_HEADERS.FileHeader.Machine

    # If our platform arch != our PE header arch, exit out. 
    # PE.IMAGE_FILE_MACHINE_I386  == 0x0000014c [ 332 ] == 32 bit
    # PE.IMAGE_FILE_MACHINE_AMD64 == 0x00008664 [34404] == 64 bit
    if pe_arch == PE.IMAGE_FILE_MACHINE_I386 and cur_arch != "32bit":
        print "This won't work! Debugging 32-bit executable in 64-bit python"
        sys.exit(1)
    elif pe_arch == PE.IMAGE_FILE_MACHINE_AMD64 and cur_arch != "64bit":
        print "This won't work! Debugging 64-bit executable in 32-bit python"
        sys.exit(1)

    return pe_parsed

First thing we do is load our executable into a PE class, which parses our a whole bunch of good, juicy information for us.

Remember kids → iPython is always your friend when exploring new pieces of code.

> ipython -i vtrace_ex.py
-- SNIP -- 
In [1]: p.<TAB>
p.IMAGE_DOS_HEADER    p.getMaxRva           p.inmem               p.readAtRva
p.IMAGE_NT_HEADERS    p.getPdataEntries     p.parseExports        p.readPointerAtOffset
p.checkRva            p.getRelocations      p.parseImports        p.readPointerAtRva
p.fd                  p.getResourceDef      p.parseLoadConfig     p.readResource
p.getDataDirectory    p.getResources        p.parseRelocations    p.readRvaFormat
p.getDllName          p.getSectionByName    p.parseResources      p.readStringAtRva
p.getExportName       p.getSections         p.parseSections       p.readStructAtOffset
p.getExports          p.getVS_VERSIONINFO   p.pe32p               p.readStructAtRva
p.getForwarders       p.high_bit_mask       p.psize               p.rvaToOffset
p.getImports          p.imports             p.readAtOffset        p.sections

There are a lot of interesting things here, but what we’re focused on here is the IMAGE_NT_HEADERS, which has a few fields, namely Signature, FileHeader, and OptionalHeader. By calling p.IMAGE_NT_HEADERS.tree() we can get a good overview of the information stored there.

Signature section (should always be “PE\x00\x00”)

In [3]: print p.IMAGE_NT_HEADERS.tree()<ENTER>
00000000 (248) IMAGE_NT_HEADERS: IMAGE_NT_HEADERS
00000000 (04)   Signature: 50450000

FileHeader section

00000004 (20)   FileHeader: IMAGE_FILE_HEADER
00000004 (02)     Machine: 0x0000014c (332)
00000006 (02)     NumberOfSections: 0x00000004 (4)
00000008 (04)     TimeDateStamp: 0x4a5bc622 (1247528482)
0000000c (04)     PointerToSymbolTable: 0x00000000 (0)
00000010 (04)     NumberOfSymbols: 0x00000000 (0)
00000014 (02)     SizeOfOptionalHeader: 0x000000e0 (224)
00000016 (02)     Ccharacteristics: 0x00000102 (258)

OptionalHeader section

00000018 (224)   OptionalHeader: IMAGE_OPTIONAL_HEADER
00000018 (02)     Magic: 0b01
0000001a (01)     MajorLinkerVersion: 0x00000009 (9)
0000001b (01)     MinorLinkerVersion: 0x00000000 (0)
0000001c (04)     SizeOfCode: 0x00052e00 (339456)
00000020 (04)     SizeOfInitializedData: 0x0006a600 (435712)
00000024 (04)     SizeOfUninitializedData: 0x00000000 (0)
00000028 (04)     AddressOfEntryPoint: 0x00009768 (38760)
0000002c (04)     BaseOfCode: 0x00001000 (4096)
00000030 (04)     BaseOfData: 0x00052000 (335872)
00000034 (04)     ImageBase: 0x01000000 (16777216)
00000038 (04)     SectionAlignment: 0x00001000 (4096)
0000003c (04)     FileAlignment: 0x00000200 (512)
00000040 (02)     MajorOperatingSystemVersion: 0x00000006 (6)
00000042 (02)     MinorOperatingSystemVersion: 0x00000001 (1)
00000044 (02)     MajorImageVersion: 0x00000006 (6)
00000046 (02)     MinorImageVersion: 0x00000001 (1)
00000048 (02)     MajorSubsystemVersion: 0x00000006 (6)
0000004a (02)     MinorSubsystemVersion: 0x00000001 (1)
0000004c (04)     Win32VersionValue: 0x00000000 (0)
00000050 (04)     SizeOfImage: 0x000c0000 (786432)
00000054 (04)     SizeOfHeaders: 0x00000400 (1024)
00000058 (04)     CheckSum: 0x000cd612 (841234)
0000005c (02)     Subsystem: 0x00000002 (2)
0000005e (02)     DllCharacteristics: 0x00008140 (33088)
00000060 (04)     SizeOfStackReserve: 0x00040000 (262144)
00000064 (04)     SizeOfStackCommit: 0x00002000 (8192)
00000068 (04)     SizeOfHeapReserve: 0x00100000 (1048576)
0000006c (04)     SizeOfHeapCommit: 0x00001000 (4096)
00000070 (04)     LoaderFlags: 0x00000000 (0)
00000074 (04)     NumberOfRvaAndSizes: 0x00000010 (16)
00000078 (128)     DataDirectory: VArray
00000078 (08)       0: IMAGE_DATA_DIRECTORY
00000078 (04)         VirtualAddress: 0x00000000 (0)
0000007c (04)         Size: 0x00000000 (0)
--SNIP--

So the field we’re interested in is the FileHeaderMachine field. This will give us the architecture our executable was compiled to run on, and with pretty much anything in the wonderful world of Windows, it’s in a binary format.

Thankfully visi has provided us with some handy reference attributes for the PE module. They’re pretty self-explanatory, but just to re-iterate.

PE.IMAGE_FILE_MACHINE_I386  == 0x0000014c [ 332 ] == 32 bit
PE.IMAGE_FILE_MACHINE_AMD64 == 0x00008664 [34404] == 64 bit

Cool beans. Let’s move onto the code that actually parses out our executable’s IAT.

# Parse out our PE information
p = parsePE()

# Execute our trace and get our base address
trace = vtrace.getTrace()
trace.execute(run_prog)

# Load our library base addresses
libs = trace.getMeta("LibraryBases")
# Find our PE base address
base = libs[re.findall('^.*\\\\(\w+).exe',run_prog.lower())[0]]

# Set up our exports dictionary to hold all the children functions for each DLL
exports = {}
for ord_num, dll_name, func_name in p.getImports():
    exports.setdefault(dll_name,[]).append((hex(base+ord_num),func_name))

# Print everything out!
for dll in exports:
    print dll.lower()
    for export in exports[dll]:
        print "\t" + export[0] + " - " + export[1]

When using the vtrace module, you pretty much always follow this convention. You can set breakpoints, or parameters to set breakpoints for you, then you call trace.run(), which is equivalent to a continue in $(your debugger of choice).

The getMeta() function is something that basically allows you to query the state of affairs going on with your trace handler (as far as I understand it). In our case we call it with “LibraryBases” which gives us our library names and their offsets. We could have also called “LibraryPaths”, which would’ve given us a similar data structure with the full path to our libraries, but I chose to write a terrible looking regular expression to just chomp out our executable name to find it’s base address.

Now that we have our program’s base address though, we basically just need to get a list of the imports from our PE module. Super simple. The exports dictionary is populated with the dll name as the key, and a value array of tuples in the form (calculated address, name) for each function it imports.

It may be simpler to see the data itself, but just know we calculate the offset relative to our executable’s base address.

In [36]: exports<ENTER>
--SNIP--
'ntdll.dll': [('0xf7112cL', 'WinSqmAddToStreamEx'),
 ('0xf71130L', 'WinSqmIncrementDWORD'),
 ('0xf71134L', 'WinSqmAddToStream'),
 ('0xf71138L', 'NtQueryLicenseValue'),
 ('0xf7113cL', 'RtlInitUnicodeString')],
'ole32.dll': [('0xf710f4L', 'CoInitialize'),
 ('0xf710f8L', 'CoUninitialize'),
 ('0xf710fcL', 'CoCreateInstance')]}

So there you have it. Fairly straight-forward code to dump all the imports for your executable’s IAT! I cranked this out in a single night while drinking beer and relaxing, so needless to say – this tool makes for some extremely fast prototyping of awesome debugger stuff!

Looking into the ridiculously extensive sourcecode for VDB, I can only conclude that @invisig0th and @at1as are simply smart people, and are just swimming in 0-days.

There’s no way to hold THAT many 0-days!

NOTE: VDB’s main site isn’t currently hosting VDB/vtrace right now, but you can find it here

VDB now has docs!

After digging through the source code for VDB, I’ve decided to start contributing in the small ways I can (e.g. doing stuff visi doesn’t want to). I uploaded a copy of VDB onto my github, created a Makefile, created a simple site, and generated some epydocs, so now it’s easy to figure out a lot of what you’re doing without having to grep (or if you use sublime text like me, CTRL+ALT+F’ing)

It’ll also be a good place for me to push my own bug-fixes, then submit patches directly to visi himself!

Of course I’m also a sucker for black/green text, so thanks visi for the CSS!

This blog runs Pelican!

After a year or so I finally decided that I’m done with WordPress. Why? Because I’m a self-respecting security professional. There’s no reason to be running something that is un-necessarily bloated and ridiculously prone to exploits.

Not that I really care about the server it’s running on, because I pay a super-discounted rate for Fatcow’s hosting. Regardless though, I’m done with it all, and will now be hosting a Pelican-powered static blog. No MySQL, no Apache, no PHP. The only part of the LAMP stack is the one I actually like – the L.

This also will make it easier to post, as I do a lot of work in Markdown now a days with all my work on my Github account.

Hope you guys enjoy the new site! I’ll look into implementing comments at some point, but I don’t think they’re absolutely necessary.