CodeWar – or How I Learned Python in 24 Hours

So the other day my friend, Stacksth, decided to have a geekout. A geekout is this fun little thing where we set aside the weekend and decide to just do geeky stuff, like screw around with an outdated IDS appliance box, or analyze every piece of wireless traffic that just happens to float our way, simply because we can.

For this geekout we decided to learn the Python programming/scripting language. Now, we both studied Computer Science together, and come from a developer background with Java as our primary language, so this wasn’t really about learning how to program, but simply about learning how it’s done in Python. The problem we both usually face when trying to learn a new language is that we get demotivated really quick because we don’t really need it for anything, it’s just a “nice-to-have” kinda thing, but for this one we came up with a really great idea, that I have then chosen to call ‘CodeWar’. We both work with information security, I mainly do offensive testing, where he mainly deals with the defensive side, so for this we decided on the following game-rules:

  • Player 1 is to create a simple server-application that listens on a ports, and upon connection asks for your name
  • Player 2 is to create a small application (or “attack-code”) that connects to this server, and upon being asked, provides a name

Now this probably sounds really boring and lame, but really, this simple exercise taught us how to create a basic program, work with sockets and perform actions, basic building blocks that you’ll need regardless of what language you use. Now for the fun part:

  • Player 2 is to alter his code so that it sends unexpected data to Player 1’s application, in an attempt to make it crash
  • Player 1, after the application crashes, is to implement fixes until Player 2 is no longer able to crash the application

This is where things get really interesting. Essentially, this requires Player 2 to write his own little fuzzer, and use it to locate errors in Player 1’s code, and it forces Player 1 to learn how to do secure development. This is essentially what vulnerability research, secure coding and exploit development is all about, find an error, and see if you can exploit it. Unfortunately, Stacksth (he was Player 1) have a pretty good grasp on secure programming, so he’d already implemented checks to make sure I wasn’t sending him numbers or other junk-data, and he even implemented a mechanism to make sure that I couldn’t send excessive amounts of data to overflow anything, so I was unable to crash it. So after this, we decided to add a little more functionality:

  • Player 1 is to add functionality to have the server ask for name and year of birth, and then return the name and age of Player 2
  • Player 2 is to try and screw with it

So now we had more variables and more input to work with, but alas, Stacksth IS good at this, so inputvalidation was in place. However, I discovered that if I had my code connect to his server with multiple connections at the same time, and then disconnected one of them, his service would crash. It needed multithreading. Victory for Player 2!!

Now that I’d managed to crash his server, we decided to exchange code. I was given the code for the service, and Stacksth received my attack-code. On for round two:

  • Player 2 is to make the service multithreaded so it can handle multiple requests and doesn’t crash
  • Player 1 is to try and screw with it

Now this was a bit tricky, and we did spend two movies (that’s how we measure time at these things, as we constantly have nerdy films playing on the big screen) figuring out how to make it work, but in the end, we actually learned how to do multithread programing for Python. YEAY US! Now, the input was still the same, so I was benefiting from Stacksth previous efforts, and he was unable to crash the service now that it was multithreaded, so we decided to add more functionality, and start interacting with the underlying filesystem:

  • Player 2 is the make the service record Player 1’s input, and store it in a file with the users name, on the computer
  • Player 1 is to try and make something off it

So this taught us how to write to files, and it also taught us (or ME!) the importance of filtering out dangerous filenames. I realized this when Stacksth wanted me to look for his files in my /var/www/ folder, and found them. So this also taught us how to filter out certain characters. Fresh off Stacksth success, we decided to exchange code again, and add more functionality:

  • Player 1 is to make the service retrieve the content of the file, if the name provided is already in the files, and read the birth-year from the file, then calculate Player 2’s age and return it to the screen. If the name is not in the files, it needs to ask for the users birth-year, save it in a file and return the age of Player 2
  • Player 2 is to try and make something off it

Now this is starting to look an awful lot like some form of login mechanism, right? So this taught us how to read from files, do splits and all sorts of fun handling. Now, the fact that there is a difference in output depending on whether the user-file exists or not, means that an enumerator can be made. So, I did. The attack-code was changed to perform account-enumeration, and naturally this was done in a method of it’s own, so we’d now learned how to split functionality up into methods as well.

So for our last trick we decided to add in a password as well:

  • Player 1 is to make the service ask for a name. If the name exists in the files, it should ask for a password that is also stored in the file, and the files password and the one submitted by Player 2 is a match, return the calculated age of Player 2
  • Player 2 is to try and get something out of it

So this is really now a regular login-mechanism, so what would be more natural than to try and make dictionary attack script to try and get valid credentials? This, of course, taught us how to do nested loops, which means that we now have pretty much everything we need in order to do just about anything in Python. And best of all, it was a hell of a lot of fun!

I know I started out with calling this a “code war”, and the idea behind that was pretty much just that this was coding done from both sides of the fence, both offensive and defensive, which is really just a great way to learn the ins and outs of both sides. This whole thing could easily be scaled up into a number of predefined steps or assignments, that one side would have to implement, and the other side would then have to break, and points could be awarded depending on whether the system broke or not, turning it into a fun little competition, or “war” between “coders”.

Anyway, this is how I learned Python in 24 Hours, and had fun with it. For inspiration, here’s some of the code that was produced during our geekout, including the solution to the first OverTheWire Vortex challenge. The code might be incomplete, but it’s mainly there for inspiration, and for easy access the next time I need to be reminded of how to do some of this stuff:

##Vortex##

 

#!/bin/python

 

import socket

import struct

 

sock = socket.socket()

host = “vortex.labs.overthewire.org”

port = 5842

 

sock.connect((host,port))        #connect directly

 

total = 0

 

for i in range(4):

data = sock.recv(4)        #reads 4×4 bytes and puts them in an array

sock.send(struct.pack(“<I”,(total & 0xFFFFFFFF)))    #packs the number as binary and sends it

print sock.recv(1024)

 

sock.close

##Attack Code###

 

import struct

import sys

 

host = “192.168.1.103″

#host = “192.168.1.107″

port = 1337

count = 0

 

def enumerateuser():

users = []

file = open(‘users.txt’)

while True:

line = file.readline()

if not line: break

sock = socket.socket()

sock.connect((host,port))

temp = sock.recv(1024)

#print “1 ” + temp

sock.send(“”+line.strip())

two = sock.recv(1024)

if two.find(“Password”) == -1:

print “”

else:

print “users is ok”

users.append(line)

sock.send(“1234″)

reply =  sock.recv(1024)

#print “3 ” + reply

if reply.find(“Data content is”) == -1:

print “”#nothing found”

else:

print “”#line + ” is a valid username”

users.append(line + ” and password is 1234″)

sock.close()

file.close()

print “valid users”

for i in range(len(users)):

print users[i]

 

def brute():

message = “tetetete”*1000000

#for i in range(1000):

while True:

sock = socket.socket()

sock.connect((host,port))

sock.send(“”+message)

print “replye: “+sock.recv(1024)

#print count

sock.close

#count += 1

 

def age():

while True:

name = “ass”*100000

born = “1985″

born2 = “1985″*10000000

#print born2

sock  = socket.socket()

sock.connect((host,port))

#print sock.recv(1024)

sock.send(“”+born2)

#print sock.recv(1024)

#print sock.recv(1024)

sock.send(“”+name)

#sock.send(“”+born2)

#print sock.recv(1024)

sock.close

 

enumerateuser()

##Service##

 

#!/usr/bin/env python

 

import socket

import Queue

from sys import exit

 

host = ”

port = 60011

backlog = 100

size = 1024

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

s.bind((host,port))

s.listen(backlog)

 

def is_number(s):

try:

float(s)

return True

except ValueError:

return False

 

try:

while True:

client, address = s.accept()

 

data = client.recv(size)

if data:

client.send(“Good day piggy!!\n”)

client.send(“When was piggy born?\n”)

born = client.recv(size)

print born

if is_number(born):

born2 = int(born)

date = 2011-born2

client.send(“Piggy is “)

client.send(str(date))

client.send(“\n”)

 

else:

client.send(“thats not a number\n”)

client.close()

except KeyboardInterrupt:

s.close()

print “You cancelled the program!”