SQL Injection Probe by User Agent

The following user-agent should be blacklisted due to SQL injection probing and occasional injection attempts:

Mozilla/5.0+(Windows;+U;+Windows+NT+5.1;+pt-PT;+rv:1.9.1.2)+Gecko/20090729+Firefox/3.5.2+(.NET+CLR+3.5.30729)

 

A common signature is uri queries with the string A=0 or 0=A.

It has been tracked from 448 unique IP addresses over the last 7 days for a total of 5384 requests.

Given that this user string is significantly outdated, there should be little concern with dropping legitimate traffic.

Some example injection strings:

0'(%2f**%2fsElEcT+1+%2f**%2ffRoM(%2f**%2fsElEcT+count(*),%2f**%2fcOnCaT((%2f**%2fsElEcT(%2f**%2fsElEcT+%2f**%2fuNhEx(%2f**%2fhEx(%2f**%2fcOnCaT(char(33,126,33),0x4142433134355a5136324457514146504f4959434644,char(33,126,33)))))+%2f**%2ffRoM+information_schema.%2f**%2ftAbLeS+%2f**%2flImIt+0,1),floor(rand(0)*2))x+%2f**%2ffRoM+information_schema.%2f**%2ftAbLeS+%2f**%2fgRoUp%2f**%2fbY+x)a)+

 

(SeLeCt+1+FrOm(SeLeCt+count(*),CoNcAt((SeLeCt(SeLeCt+UnHeX(HeX(CoNcAt(char(33,126,33),0x4142433134355a5136324457514146504f4959434644,char(33,126,33)))))+FrOm+information_schema.TaBlEs+LiMiT+0,1),floor(rand(0)*2))x+FrOm+information_schema.TaBlEs+GrOuP+By+x)a)+and+1=1

 

Recently seen IP addresses (click read more for list):

Continue reading “SQL Injection Probe by User Agent”

KIWI CTF 2017 – MD5_GAMES – WEB 50 PTS

10 years has passed since MD5 was broken, yet it is still frequently used in web applications, particularly PHP powered applications (maybe because there’s a function after it?). Break it again to prove the point!

We are given access to the source code:

<?php
if (isset($_GET['src']))
    highlight_file(__FILE__) and die();
if (isset($_GET['md5']))
{
    $md5=$_GET['md5'];
    if ($md5==md5($md5))
        echo "Wonderbubulous! Flag is [here goes a flag]"; //.require __DIR__."/flag.php";
    else
        echo "Nah... '",htmlspecialchars($md5),"' not the same as ",md5($md5);
}

 

As we can see we need to generate an MD5 hash that is ‘equal’ to the string it was generated from.

The flaw in the source is the result of a type juggling issue with the comparison using ‘==‘ instead of ‘===‘.

When using ‘==‘ both values being compared that have have ‘0e’ will be converted to a float value such that the string has leading zeroes into an ‘e’ and followed by only integers.

Consider the following:

var_dump('000e1032' == '00e032098103123'); // Returns True
var_dump('000e1032' === '00e032098103123'); // Returns False
var_dump('000e1032' == '00e03209A103123'); // Returns False

A common misconception is that this would be entirely limited to values starting with 0e. However, we can have any number of leading zeroes.

So in order to create a ‘collision’ we need to find a string that matches a regex of ‘^[0]{1,30}e[0-9]{1,30}$’ and that also has an MD5 value matching that regex.

I setup the script with a single argument that I planned to use for a range of 0-32.

I have an empty file setup that each additional process can check to see if another process found the collision.  The aim here is to maximize CPU without being limited to a single core via the process.

Essentially each value from 0-32 represents a block of 15 million attempts.

We setup the counter based on the process integer from 0-32 and multiply by one million:

count = int(thread_num) * MILL

Then we initiate our WHILE LOOP that first checks the output file to see if any other processes found a collision first:

if os.stat(OUTFILE).stsize > 0:
 break

If not, then we enter our leading zero loop for each count value:

for i in range(1,16):
    m = hashlib.md5()
    plain = '0' * int(i) + 'e' + str(count)
    m.update(str(plain))
    collide = m.hexdigest()

Lets break this down. The plain text that we will generate the hash from is going to have a number of zeroes equivalent to ‘i’ generated before ‘e’ followed by the current loop counter.

So, if we are at the very start of process 3, our current plain value would be ‘0e3000000’. As we step through the ‘i’ loop it will increase. So once ‘i’ is 10 for example, the plain value will be ‘0000000000e3000000’.

To illustrate the order that hashes are being generated:

 

We then check it against our regex to see if it matches and will work:

if re.match('^[0]{1,30}e[0-9]{1,30}$',collide):
   f=open(OUTFILE, 'w+')
   f.write('[+]:: Collision Found!\n[+]:: Value '+str(plain)+'\n[+]:: HASH '+collide)
   f.close()
   print '[+]:: Execution Time - ' + str(datetime.now() - starttime)
   print '[+]:: Hashes Generated - ' + str((count - (MILL*int(thread_num))) * 16 - i)
   break

 

There are plenty of ways we can execute our script to open multiple processes (for loops, python, etc). I have too many issues with my workstation not maximizing CPU with threading and mp modules to try to waste time troubleshooting for now. Once we run with command line ‘python md5_games.py x’ where x is 0-32, we can find the hash in just a few seconds.

Turns out process number 9 generates a match the quickest per the md5_out.txt file:

[+]:: Collision Found!
[+]:: Value 0000e9012915
[+]:: HASH 0e799233929553026239472795857843

[+]:: Execution Time – 0:00:05.844000

Square CTF 2017 – FLOPPY – REVERSE 1000 PTS

Our team of corn snakes formed an uneasy alliance with the office mice and slithered into the server room of Evil Robot Corp. They extracted an image of the VPN server before they had to retreat. Turns out sending a team of reptiles into a room whose main purpose is to keep its contents cold wasn’t the best idea. Can you figure out how this bootable floppy works and recover the secret data?

We are presented with a download link for ‘floppy.img’. The file appears to be a DOS/MBR boot sector that is not mountable.

I decided to use Boch’s Emulator to test this image. When configuring Boch’s there are two setting groups that need to be updated – ‘Memory’ and ‘Disk & Boot’

In the ‘Memory’ settings ensure you have the latest Boch’s ROM BIOS and VGA BIOS images and update their paths:

In the ‘Disk and Boot’ configure the following settings and select the ‘floppy.img’ file for First floppy/image device:

Once configured click start and let it load to the Challenge screen:

We enter random input ‘ASDF’ and see a response of ‘Nope’.

So lets take a look under the hood. We are able to load this directly in IDA PRO x86 and review the code.

After loading ‘floppy.img’ in IDA, lets start with the Strings view (SHIFT+F12)

Here we can see the string ‘flag-‘ as well as ‘Nope’.  Double-click on the ‘flag-‘ string to see the IDA view including XREFs:

Click on the aFlag line and hit CTRL+X – this will list the XREFs to this string.

Clicking OK will bring us to the graph view of the function that is calling the string:

We can see a JNZ instruction that decides whether or not we see the ‘Flag-‘ string we want or the ‘Nope’ string.

There are more difficult ways to solve this challenge, but I want the fastest and easiest way. So for that we are simply going to patch the JNZ instruction bytes to a JZ instruction and save our new floppy.img. The result will be outputting the flag, no matter the input.

  • To start click on the line with our JNZ instruction – jnz loc_456
  • Click the ‘Edit’ menu
  • Scroll down to ‘Patch Program’
  • Click ‘Change Byte…’

You will see the following popup

In the values field, change the second byte 85 to 84 and Click OK.

You will notice the instruction change to JZ loc_456

Now to save your patched program click File -> Produce File -> Create EXE. And save the file as patched_floppy.img.

Head back to Boch’s and update your ‘Boot and Disk’ settings to point to your new ‘patched_floppy.img’ and Start it up.

Enter random characters, in this case ‘DSFS’ and the flag will now be output to the screen: