Guides

Failure to Install GD with CPAN: LDS/GD-2.35.tar.gz

I decided to install the GD image library for Perl on my working station, and as usual, using CPAN. However, after running install GD, I was faced with an error.

make: *** [GD.o] Error 1
  LDS/GD-2.35.tar.gz
  /usr/bin/make -- NOT OK
Running make test
  Can't test without successful make
Running make install
  Make had returned bad status, install seems impossible
Failed during this command:
 LDS/GD-2.35.tar.gz                           : make NO

Unable to find the cause, I turned to apt-get, which installed GD without any problems.

$ sudo apt-cache search libgd perl 
libgd-gd2-perl - Perl module wrapper for libgd - gd2 variant
libgd-graph-perl - Graph Plotting Module for Perl 5
libgd-text-perl - Text utilities for use with GD
ruby1.8 - Interpreter of object-oriented scripting language Ruby 1.8
calamaris - log analyzer for Squid or Oops proxy log files
libgd-barcode-perl - Library to create barcode images (GD::Barcode)
libgd-gd1-noxpm-perl - Perl module wrapper for libgd (old version against GD 1.8.x)
libgd-gd1-perl - Perl module wrapper for libgd (old version against GD 1.8.x)
libgd-gd2-noxpm-perl - Perl module wrapper for libgd - gd2 variant without XPM support
libgd-graph3d-perl - Create 3D Graphs with GD and GD::Graph
libgd-perl - Perl module wrapper for libgd
libgd-securityimage-perl - Security image (captcha) generator.
libgdk-pixbuf-perl - Perl module for the gdkpixbuf library
$ sudo apt-get install libgd-perl

HTS Realistic 5: Find the Hidden Hash

Damn Telemarketers!: Telemarketers are invading peoples privacy and peace and quiet. Get the password for the administrative section of the site to delete their database and return the privacy of their victims!

Realistic mission 5 of Hack This Site is quite fun, since it involves several vulnerabilities. You are supposed to clear a spammer’s database.

From: spiffomatic64

Message: Yo! This is Spiffomatic64 from Hackthissite.org! I’m a bit of a hacker myself as you can see, but I recently came upon a problem I couldn’t resolve…..
Lately I’ve been getting calls day and night from the telemarketing place. I’ve gone to their website and hacked it once deleting all of their phone numbers so they wouldn’t call me anymore. That was a temporary fix but they put their database back up, this time with an encrypted password. When I hacked them I noticed everything they used was 10 years out of date and the new password seems to be a ‘message digest’. I have done some research and I think it could be something like a co called hash value. I think you could somehow reverse engineer it or brute force it. I also think it would be a good idea to look around the server for anything that may help you.

Don’t just skim that through; read everything that Spiffomatic has to say. It’s quite helpful. Now, for their site. As you’ve probably seen, it consists of four visible sections: Home, News, Database and Contact.

The Home page contains nothing but an image and few email addresses, and the Contact page is equally useless. Don’t forget to check the source anyway, though, just to be sure. The Database page has nothing but a password input field. Inputting anything just gives you a “invalid password” message. Since entering “\”, “‘” and “”” characters still gives you the same message, we can assume that this field is not vulnerable to SQL injections.

We can’t find any vulnerability from the News page, either. However, the news items contain valuable information. We find that the administrator’s girlfriend’s name is Haley, which invites us to try that name as a password. Unfortunately, it didn’t work. We are also told something about “zapp”, which I have no idea of what it is. Next, we are told that they had some problems with Google:

Google was grabbing links it shouldn’t be so I have taken extra precautions.

Now, how do you take extra precautions when search engines are grabbing links that they shouldn’t? Well, you edit robots.txt to disallow it. Let’s take a look at the robots.txt of Compu-Global-Hyper-Mega-Net: http://www.hackthissite.org/missions/realistic/5/robots.txt.

Disallow: /lib/
Disallow: /secret/

Nice to know. Check those folders out, and you will find that directory listing is not disabled. Begin with secret/, since it seems most interesting. There are two files: admin.php and admin.bak.php. The prior is the script that validates passwords, and the latter seems to be a backup of the prior. However, when we access it, we get:

error matching hash 3184342944a094dd5dbe6fccaeb8dc96

Note that the specific hash might be different for you. As Spiffomatic64 said, this is a message digest (MD). Probably, it’s the message digest of the password that you are going to enter. But how are we supposed to know the algorithm of the hashing function? Remember the other directory disallowed from robots.txt? Let’s check lib/.

There is only one file here–”hash”. The hashing algorithm, perhaps? Download the file and open it in your favourite text-editor. Uh-oh. A lot of bogus characters, followed by:

Error: MDupdate MD already done.
Error: MDupdate called with illegal count value %d.
3.4.4 [FreeBSD] 20050518
MIC

In most cases when you encounter such a file, using a hex editor lets you read parts of it. There are many, for example XVI32 for Windows and hexedit for Linux. Now, look for something that you recognize. You will probably find this part in the file:

do_global_ctors_aux
/usr/src/lib/csu/i386-elf/crtn.S
md4.c
MDblock
md4driver.c

Which reveals that the encryption algorithm used is MD4. Use any MD4 collision finder to crack the hash. I’ve written a simple MD4 collision finder in perl, which you can use. If you don’t happen to like Perl, there is a lot of free tools available out there, including online reverse-lookup databases.

Going back to the “Database” page and entering the password completes the challenge.

HTS Realistic 4: UNION ALL the Products

Fischer’s Animal Products: A company slaughtering animals and turning their skin into overpriced products sold to rich bastards! Help animal rights activists increase political awareness by hacking their mailing list.

So I finally got around to write a walkthrough/guide for Hack This Site realistic mission 4. Your objective is to get the email addresses of the subscribers to the news letter of Fischer’s Animal Products.

From: SaveTheWhales

Message: Hello, I was referred to you by a friend who says you know how to hack into computers and web sites – well I was wondering if you could help me out here. There’s this local store who is killing hundreds of animals a day exclusively for the purpose of selling jackets and purses etc out of their skin! I have been to their website and they have an email list for their customers. I was wondering if you could somehow hack in and send me every email address on that list? I want to send them a message letting them know of the murder they are wearing. Just reply to this message with a list of the email addresses. Please? Their website is at http://www.hackthissite.org/missions/realistic/4/. Thanks so much!!

Start by investigating every part of Fischer’s the site. There are essentially two parts which might be vulnerable. The most visible one is the email form. A clearly visible input-field, where you just add your email address and are given a “Email added successfully” message. As you’ve seen through other missions containing SQL injections, the first step is attempting to get out of the string. Try registering an email address containing apostrophes, both single and double.

Error inserting into table “email”! Email not valid! Please contact an administrator of Fischer’s.

Unsuccessful. However, we got an important piece of information: the table name is “email”.

Now for the other part of the website; the product lists. There are two product lists, “fur coats” and “alligator accessories” (how this would have anything with whales to do is beyond me). If you’ve been as observant as you should be, you’ve noticed that both are the same file–products.php–with the category ID as an argument.

What do we want to accomplish? If we wanted to select something else from that table, we could attempt to change the WHERE part of the SELECT statement by changing the category argument to something like “1 OR categpory = 2″ (which happens to give you both categories of products on one page). However, we want to add information from another table: the “email” table. This is were the MySQL command UNION comes in very handy. Using UNION, we can merge the results of two SELECT statements into one. For example, we could:

SELECT * FROM table1 UNION ALL SELECT * FROM table2;

The result would be getting all rows from table1 and all rows from table2. Note that this assumes that the number of columns in table1 and table2 are equal. If they are not, the command will not work. UNION ALL is used instead of simply UNION in order to preserve duplicate rows. It is good practice to use UNION ALL in order to avoid unexpected errors. Let’s assume that the initial query could be something like this:

SELECT * FROM products WHERE category = 1;

We also want the rows from the email table. Therefore, we’ll try looking for another category: 1 UNION ALL SELECT * FROM email, resulting in the following final query:

SELECT * FROM products WHERE category = 1 UNION ALL SELECT * FROM email;

Which is exactly what we want. However, this results in nothing of value. Remember the assumption made earlier when we UNIONed table1 and table2? They must be of the same number of columns. We can assume that “email” has fewer columns than “products” does, since the products table should be more advanced. Therefore, we add columns to the email table:

SELECT * FROM products WHERE category = 1 UNION ALL SELECT *, NULL FROM email;

NULL means nothing–it is just an empty column. This doesn’t work either, so we’ll have to keep adding NULLs until we get some results. It will finally work at three NULLs:

SELECT * FROM products WHERE category = 1 UNION ALL SELECT *, NULL, NULL, NULL FROM email;

Below the category 1 products, you can see ten broken images. Viewing the source-code, you will find that the sources of these are email addresses! Rearranging the column order will give you a more eligible format.

SELECT * FROM products WHERE category = 1 UNION ALL SELECT NULL, *, NULL, NULL FROM email;

Just copy the list and email it to SaveTheWhales!

HackQuest: JavaScript: Ok, finally it’s secure. Or?

Name: Ok, finally it’s secure. Or?
Place: London, UK
Target: MicroWorld building

This time its them. We want access to their fire alarm system.

Search for the form:

73
74
75
76
77
78
79
80
            <form name="LayoutBereich1FORM" action="" method=
            "post">
              <input id="Eingabefeld1" type="TEXT" name=
              "inputbox1" value="" size="30" maxlength="30">
              <input type="BUTTON" name="Schaltfl&auml;chen1"
              value="Enter Password" id="Schaltflaechen1"
              onclick="testEncode(this.form)">
            </form>

Eingabefeld1/inputbox1 is the only field. testEncode() is called onclick.

39
40
41
42
43
44
45
function testEncode(form) {
	var dater = new Date();
	Day = dater.getDate();
	dater = null;
	var Ret = encode (form.inputbox1.value, Day)
	location = Ret + ".html"
}

Now, the date seems to matter. Day is set using getDate(), which returns the current day of the month, from 1 to 31. In my current case, it is 17, since the date is the 17th of July.

Next, the variable Ret is set to encode( form.inputbox1.value, Day ). The first argument sent to encode() is the password, and the second argument has already been described. encode() is a function defined on the page.

47
48
49
50
51
52
53
54
55
56
57
58
59
function encode (OrigString, CipherVal) {
	Ref="0123456789abcdefghijklmnopqrstuvwxyz._~ABCDEFGHIJKLMNOPQRSTUVWXYZ"
	CipherVal = parseInt(CipherVal)
	var Temp=""
	for (Count=0; Count < OrigString.length; Count++) {
		var TempChar = OrigString.substring (Count, Count+1)
		var Conv = cton(TempChar)
		var Cipher=Conv^CipherVal
		Cipher=ntoc(Cipher)
		Temp += Cipher
	}
	return (Temp)
}

The first line defines Ref as a long string. Next, CipherVal–the second argument, i.e. the day of the month–is changed from a string to an integer. A for loop runs one time for every character in OrigString, which is the password that you entered, incrementing Count each time.

In the loop, TempChar is set to the character at position Count of OrigString, similar to the substring() usage in the previous Jedi Mindtricks challenge. Next, Conv is set to cton(TempChar). The cton() function is set below encode():

61
62
63
function cton (Char) {
	return (Ref.indexOf(Char));
}

The indexOf() function returns the position of the first occurence of a string in another string. Here, the position of Char in Ref is returned. For example, if Char was “j”, 19 would be returned.

Line 54 contains ^, the bitwise XOR operator. To conduct a bitwise XOR, you compare each bit of two numbers. When the two are not eqal, that bit of the new number is 1. When they are not, it is set to 0. For example, 19^6=21:


10011=19
00110=6
10101=21

Cipher is set to Conv^CipherVal, and ntoc() is called with the result as an argument.

65
66
67
function ntoc (Val) {
	return (Ref.substring(Val, Val+1))
}

Just like the previous occurence of substring(), this returns the character from Ref at position Val, which is position Cipher. The result is appended to Temp, and after the return, Temp is returned, and testEncode sets the location to the returned string with the “.html” suffix.


Now, you should be coming to a sad realisation: the password cannot be figured out through only the source code. In fact, this has nothing to do with JavaScript at all. It’s just an incredibly stupid category for this challenge.

Instead, start looking at what is different from other challenges. You’ve probably noticed that the location does not follow the standard; the URL is http://www.hackquest.de/modules/HackQuest/hacking/274/octodron/274.php. What an Octodron is, I have no idea, and neither does Google. One of those racing tracks that is formed like an 8, making you return to where you started? A misspelt octodon? Anyway, this should catch your eye.

The next part is just about testing as you would for any vulnerability. After a while, you might find that there is a nice directory-listing at /modules/HackQuest/hacking/274/octodron. ClickThisHiddenFile.php? Yes, please.

HackQuest: JavaScript: Jedi Mindtricks

Name: Jedi mindtricks.
Place: Mexico City, Mexico
Target: Twilight Security Company

At least five major MSA agents came from here. Take them off the internet for good.

The source code is obfuscated, through URL-encoding it and then fixing it with JavaScript. Generalizing the code, we have:

1
2
3
m = '%3C%21...html%3E';
d = unescape(m);
document.write(d);

If we could only get hold of d, this challenge would be a lot easier. The formerly mentioned JavaScript injection comes in handy. However, trying to inject the intuitive javascript:alert(d) would end up with nothing but a hard-to-manage alert-box. Instead, we will put it on the page. Just using document.write(d) will result in the tags being interpreted by your browser. Therefore, we put it all inside a textarea.

javascript:document.write('<textarea>'+d+'</textarea>')

This will give you the whole source code inside a nice textarea field. Put your cursor in it, select everything with ctrl+A and then paste it into a text editor for an easy overview. As always, start by finding the form.

67
68
69
70
71
72
      <form name="LayoutBereich1FORM" action="" method="post">
        <input id="Eingabefeld1" type="TEXT" name="Eingabefeld1"
        value="" size="30" maxlength="30"> <input type="BUTTON"
        name="Schaltflächen1" value="Enter Password" id=
        "Schaltflaechen1" onclick="return PassConfirm()">
      </form>

Only one field this time, “Eingabefeld1″. Submitting calls PassConfirm().

25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
function PassConfirm() {
 
  var y="alphabravocharliedeltax";
  var x="lidocaineadrenalineekel";
  var z="sidewinderamraamphoenix";
 
  var s = "";
  for (Count=0; Count < y.length; Count++) {
 
		var t1 = y.substring (Count, Count+1);
		var t2 = z.substring (Count, Count+1);
		var t3 = x.substring (Count, Count+1);
 
		if (t1 * t2 * t3 >= 5 || t3^t1 >= 3)
  	  s=s+t1;
		else {
	  	if (t3 == t2)
				 s=s+t3;
	  	if (t2 == t1)
				 s=s+t2;
	  	if (t1 == t3)
				 s=s+t3;
		}
  }
 
  var x=document.LayoutBereich1FORM.Eingabefeld1.value
  if (x==s) {
    y = s + ".php"
    window.open(y,"_self")
  } else {
    alert("Dooh, try again!")
  }
}

First, x, y and z are set to some strings. A for-loop then starts. It increments Count and is run from 0 until Count < y.length. y.length is the amount of characters in “alphabravocharliedeltax”, which is 23.

In the for loop, the three variables t1, t2 and t3 are first initialised using the substring() function. substring() is a built-in JavaScript function that extracts a part of a string. In this case, it only takes one character, the one at position Count (remember that the first character is character 0).

The following condition check is just bogus. The product of strings (t1*t2*t3 or t3^t1) will never be of a numerical value, and thus only the else-block will be executed. What the else-block effectively does is that it appends the character to s if two of the three strings have the same character at that position With this information, we can go through x, y and z and find the password. The first one is at Count==1, where the x and z substrings are equal and thus “i” is added to s. The next is at Count==2, and the at Count==8. In my case, the final s was ideaeex.

Next s is checked to be equal to the password entered, and if it was right, the challenge is cleared.

HackQuest: JavaScript: What you mean its not THAT easy?

This challenge presents a more modern (and unnecessary) way of entering the code.

Name: What you mean its not THAT easy?
Place: Berlin, Germany
Target: MAD central

This german security agent needs some info uploaded, so they realize the MicroWorld threat.

It’s a little more difficult to find the form now, but that’s still were we should start. Searching the source code for “form” reveals that everything is even printed through the JavaScript:

24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
        <!-- Key-code script by Bart Jellema -->
    var usermulcode=10
 
    var code=0   // the entered code
    var mul=1    // the multiplied digits
    var digit=0  // number of digits entered so far
    var fails=0  // number of tries done
    function Clear_code()
    {
      document.codepad.thecode.value=''
      code=0     
      mul=1
      digit=0
    }
    function Enter_code(number)
    {
      code=code*10+number        
      mul=mul*number          
      document.codepad.thecode.value=code
      digit++   
 
      if (digit==4) 
      {
        if (mul==120)              
        {
          window.open (code+".php", "_self")
        }
        else
        {
          fails++          
          code=0     
          mul=1
          digit=0
          if (fails<3) {
              if(fails==1){
                  document.codepad.thecode.value="Try again"
              }
              if(fails==2){
                  document.codepad.thecode.value="Last time"
              }
          } else {
              document.codepad.thecode.value="Bye!"
          }
        }
      }
    }
 
        function keycodepad(mulcode)
        {
         usermulcode=mulcode
         document.write("<table><tr><td><form name=\"codepad\">");
         document.write("<input type=\"button\" value=\" 1 \" onClick=\"Enter_code(1)\">");
         document.write("<input type=\"button\" value=\" 2 \" onClick=\"Enter_code(2)\">");
         document.write("<input type=\"button\" value=\" 3 \" onClick=\"Enter_code(3)\">");
         document.write("<input type=\"button\" value=\" 4 \" onClick=\"Enter_code(4)\"><br>");
         document.write("<input type=\"button\" value=\" 5 \" onClick=\"Enter_code(5)\">");
         document.write("<input type=\"button\" value=\" 6 \" onClick=\"Enter_code(6)\">");
         document.write("<input type=\"button\" value=\" 7 \" onClick=\"Enter_code(7)\">");
         document.write("<input type=\"button\" value=\" 8 \" onClick=\"Enter_code(8)\"><br>");
         document.write("<input type=\"button\" value=\" 9 \" onClick=\"Enter_code(9)\">");
         document.write("<input type=\"button\" value=\" 0 \" onClick=\"Enter_code(0)\">");
         document.write("<input type=\"button\" value=\" C \" onClick=\"Clear_code()\"><br>");
         document.write("<input type=\"text\" name=\"thecode\" size=9 value=\"\"><br>");
         document.write("<\/form><\/table>");
        }
 
        <!-- Key-codescriptbyBartJellema-->

It is initialised at line 95 by the call keycodepad(24). Apparently, the variable “mulcode” is thus set to “24″, and after that “usermulcode”. Every click on a number calls Enter_code() with the number clicked as an argument. We will therefore dissect Enter_code(number), line by line.

First, code is multiplied by 10 and then the number is added to it. The effect of this is that number is appended to the right of the existing code. From the start, code equals 0 (line 27), and it is reset to that if C is pressed (from the Clear_code() function).

Next, mul is multiplied by the number pressed. mul starts off as 1 and is reset to 1 by Clear_code(). The line after that just updates the “display” to show the full code. After that, digit is incremented. As can be seen from line 29, digit is the number of digits that have been pressed (although this is reset by Clear_code() to 0).

Unless the following condition is true, Enter_code() ends here. The if statement checks whether digit==4, i.e. if four digits have been pressed. If mul==120, we have succeeded and are referred to another page. If not, the wrong-code handling sets in. It seems as if it is so easy as to find four digits between 1 and 9 where the product equals 120. However, it is not (what you mean it’s not THAT easy?). It seems that we have to find the correct combination, and through only the JavaScript, this is not possible. The usermulcode variable is of no use since it is not use in this script. We can find al combinations using a simple Perl script, though:

1
2
3
4
5
6
7
8
9
10
11
12
@n = 2..9;
foreach my $a (@n) {
  foreach my $b (@n) {
    foreach my $c (@n) {
      foreach my $d (@n) {
        if ( $a*$b*$c*$d == 120 ) {
          print $a, $b, $c, $d, "\n";
        }
      }
    }
  }
}

Since the URL is only dependant on the code (line 49), we can actually generate a nice list of possible solution URLs. Just replace line 7 in the perl script above with:

7
print 'http://www.hackquest.de/modules/HackQuest/hacking/824/', $a, $b, $c, $d, '.php', "\n";
http://www.hackquest.de/modules/HackQuest/hacking/824/2256.php
http://www.hackquest.de/modules/HackQuest/hacking/824/2265.php
http://www.hackquest.de/modules/HackQuest/hacking/824/2345.php
http://www.hackquest.de/modules/HackQuest/hacking/824/2354.php
http://www.hackquest.de/modules/HackQuest/hacking/824/2435.php
http://www.hackquest.de/modules/HackQuest/hacking/824/2453.php
http://www.hackquest.de/modules/HackQuest/hacking/824/2526.php
http://www.hackquest.de/modules/HackQuest/hacking/824/2534.php
http://www.hackquest.de/modules/HackQuest/hacking/824/2543.php
http://www.hackquest.de/modules/HackQuest/hacking/824/2562.php
http://www.hackquest.de/modules/HackQuest/hacking/824/2625.php
http://www.hackquest.de/modules/HackQuest/hacking/824/2652.php
http://www.hackquest.de/modules/HackQuest/hacking/824/3245.php
http://www.hackquest.de/modules/HackQuest/hacking/824/3254.php
http://www.hackquest.de/modules/HackQuest/hacking/824/3425.php
http://www.hackquest.de/modules/HackQuest/hacking/824/3452.php
http://www.hackquest.de/modules/HackQuest/hacking/824/3524.php
http://www.hackquest.de/modules/HackQuest/hacking/824/3542.php
http://www.hackquest.de/modules/HackQuest/hacking/824/4235.php
http://www.hackquest.de/modules/HackQuest/hacking/824/4253.php
http://www.hackquest.de/modules/HackQuest/hacking/824/4325.php
http://www.hackquest.de/modules/HackQuest/hacking/824/4352.php
http://www.hackquest.de/modules/HackQuest/hacking/824/4523.php
http://www.hackquest.de/modules/HackQuest/hacking/824/4532.php
http://www.hackquest.de/modules/HackQuest/hacking/824/5226.php
http://www.hackquest.de/modules/HackQuest/hacking/824/5234.php
http://www.hackquest.de/modules/HackQuest/hacking/824/5243.php
http://www.hackquest.de/modules/HackQuest/hacking/824/5262.php
http://www.hackquest.de/modules/HackQuest/hacking/824/5324.php
http://www.hackquest.de/modules/HackQuest/hacking/824/5342.php
http://www.hackquest.de/modules/HackQuest/hacking/824/5423.php
http://www.hackquest.de/modules/HackQuest/hacking/824/5432.php
http://www.hackquest.de/modules/HackQuest/hacking/824/5622.php
http://www.hackquest.de/modules/HackQuest/hacking/824/6225.php
http://www.hackquest.de/modules/HackQuest/hacking/824/6252.php
http://www.hackquest.de/modules/HackQuest/hacking/824/6522.php

Just start testing.

HackQuest: JavaScript: Now, what is that really?

Name: Now, what is that really?
Place: Melbourne, Australia
Target: Garage of James Fern

This guy developed software that MicroWorld stole. Now we steal it first, much safer.

Pressing “Enter Site” gives a JavaScript alert, “Sorry all wrong”. As usual, we look up the source code of the form.

32
33
34
35
36
37
38
39
40
41
42
43
      <form name="form" action="" method="post">
        Username<br>
        <input id="Eingabefeld2" type="TEXT" name="Name" value=""
        size="30" maxlength="30"><br>
        Password<br>
 
         <input id="Eingabefeld1" type="TEXT" name="Password"
        value="" size="30" maxlength="30"><br><br>
         <input type="BUTTON" name="Schaltfl&auml;chen1" value=
        "Enter Site" id="Schaltflaechen1" onclick=
        "pw(this.form)">
      </form>

Remember to note what you always should note; the username ID (Eingabefeld2/Name), the password ID (Eingabefeld1/Password) and the onclick event (pw(this.form)). We start by checking what the pw() function does. For a change, it isn’t obfuscated.

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
function pw (form)
{
   var d1, d2, d3;
   d1=window.document.bgColor;
	 d2=form.Name.value;
	 d3=form.Password.value;
 
  if (d2==d1.length) { 
    if (d3==d1) {
      window.open (d1.substr(1, 10)+".php","_self")
    } else { 
      alert("Sorry all wrong.")
    } 
  } else { 
    alert("Sorry all wrong.") 
  } 
}

d2 and d3 are simply set to the username and password, respectively. d1, however, is set to the current background colour, which is a little uncommon. We then have two checks, the first one checks that d2 (username) equals the length of d1 (background colour). To find the exact background colour, we use a very useful technique called JavaScript injection.

With a JavaScript injection, we can execute arbitrary JavaScript commands at any page. Do so by putting the command in the location bar of your web browser (usually ctrl+L), prefixing it with “javascript:”. By making a JavaScript alert with the background colour in, we can easily copy that colour name. Put “javascript:alert(window.document.bgColor)” into the location bar, and you will see a popup with a colour name. In my case, it was #0e0e0e. This is d1.

The username was supposed to be the same as the length of the background colour. The length of #0e0e0e, i.e. the amount of characters in that string, is 7. Thus, the username must be “7″.

The next condition is “d3==d1″, which means that the password should be the same as the background colour, which is “#0e0e0e”.

HackQuest: JavaScript: Sir, could you pop me?

Name: Sir, could you pop me?
Place: Tokyo, Japan
Target: Lant Towers

There was a meeting in these rooms, which we must disrupt. Get us in…

When you start this challenge, you will notice that you are immediately prompted for username and password, and thereafter redirected to an irrelevant page. Disabling JavaScript from the start could give you problems with getting through the Flash screen. Thus, you’ll have to find the URL for the page all by yourself. After pressing the “Accept” button, hit the “Stop” button on your browser before you see the username/password prompts. Now, view the page source and look for the frame containing the challenge. You will find an (incorrectly implemented) iframe:

<iframe width=100% height=650 src="modules/HackQuest/hacking/frameheader.php?uname=Tim&uid=56382&url=253">

Of course, your uname and uid will be different. Follow that URL with JavaScript disabled and view the source code. You will se a relatively elaborate attempt at hiding the JavaScript, pushing the line count of the file to 56536. However, you should have no problems finding the not-so-elaborately hidden username and password declarations.

var username = "Johnny";

and

var password = "Mnemonic";

Enter those values, and you have succeeded.

HackQuest: JavaScript: Don’t look at me like this

The third JavaScript challenge is a bit more complex.

Name: Don’t look at me like this.
Place: Hawaii, USA
Target: DoD Network

You will have to get the passkeys for the system inside the navy base. We need to inject some data.

First, you might notice that right-clicking has been “disabled”. This is never a problem–just disable JavaScript, which was used to stop right-clicking. You can also view the source code by opening the challenge page in a single window instead of in a frame, and from there viewing the source code from the toolbar. Peeking at the form, we find:

45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
            <form name="e" action="" method="post">
              <input id="u" type="TEXT" name="TEXT" value="User"
              size="30" maxlength="30"> <input id="p" type="TEXT"
              name="TEXT" value="Password" size="30" maxlength=
              "30"> 
              <table border="0">
                <tr>
                  <td>
 
                    <input type="BUTTON" name=
                    "Schaltfl&auml;chen1" value="Enter Site" id=
                    "Schaltflaechen1" onclick=
                    "return ValidateEntry()">
                  </td>
                </tr>
              </table>
            </form>

Note the important items here:

  • The form name is “e”.
  • The ID for the username field is “u”.
  • The ID for the password field is “p”.
  • Upon submitting, the function “ValidateEntry()” is called.

Next, we’ll check what ValidateEntry() does.

38
39
      function ValidateEntry (){var y=document.e.u.value;var z=document.e.p.value;var x=0;if (y=='User'){alert('Please complete this form');var x=1;}
      if (z=='Password'){alert('Please complete this form');var x=1;};if (x==1){alert('Entry was not successful');var xxx=0;}else{AreYouWho(y,z);}}

For obfuscation, the DoD Network seems to have compressed the function into two long lines. Neating it up a bit, we have:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function ValidateEntry () {
  var y = document.e.u.value;
  var z = document.e.p.value;
  var x = 0;
  if ( y == 'User' ) {
    alert( 'Please complete this form' );
    var x = 1;
  }
  if ( z == 'Password' ) {
    alert( 'Please complete this form' );
    var x = 1;
  }
  if ( x == 1 ) {
    alert( 'Entry was not successful' );
    var xxx = 0;
  } else {
    AreYouWho( y, z );
  }
}

In lines 2-3, y and z are set to the entered username and password, respectively. The rest of the code runs the function AreYouWho() with the username and password as arguments unless you haven’t changed both “User” and “Password” a bit. The AreYouWho() function is squashed together into the two next lines. The neater version of it would be:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function AreYouWho( z, y ) {
  var x = 0;
  if ( z == 'Password' ) {
    var x = 1;
  }
  if ( y == 'User' ) { 
    var q = x + 1;
  }
  if ( q == 2 ) {
    window.open( "hmmm.php" , "_self" );
  } else {
    alert( 'Incorect Log-In, Password or User Name invalid' );
    var q = 0;
    var x = 0;
  }
}

Now, we know that having q==2 is good for us, since the alternative alerts that the data supplied is incorrect. Thus, we look for how to edit q. It is defined at line 7 in AreYouWho() as x+1. Thus, we want x to equal 1 since 1+1=2 and we want q to be 2. x is defined as 1 at line 4 if z=’Password’, and q is later set to x+1 if y=’User’.

Here comes the tricky part: what are z and y? We can see from the first line that these arguments are accepted such that the first argument passed is z, and the second is y. ValidateEntry() sends the arguments reversed, calling AreYouWho(y,z). This means that the y in ValidateEntry() becomes z, and vice versa. Therefore, the username should be ‘Password’ and the password should be ‘Username’.

HackQuest: JavaScript: It’s simple if you see it

As the name implies, it’s simple if you see it (if you don’t, your intelligence isn’t something to brag about).

Name: It’s simple if you see it.
Place: Reston, USA
Target: CyberTec

CyberTec was a consulting company that helped MicroWorld produce better software in less time.

As with the previous challenge, start by viewing the source and find the form. This time, they put a nice table in it.

48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
            <form name="form" action="" method="post">
              Username <input id="Eingabefeld2" type="TEXT" name=
              "Name" value="" size="30" maxlength="30"><br>
               Password <input id="Eingabefeld1" type="TEXT"
              name="Password" value="" size="30" maxlength="30"> 
              <table border="0">
                <tr>
 
                  <td>
                    <input type="BUTTON" name=
                    "Schaltfl&auml;chen1" value="Enter Site" id=
                    "Schaltflaechen1" onclick=
                    "Spikeman_password(this.form)">
                  </td>
                </tr>
              </table>
            </form>

This time, the onclick action calls the function Spikeman_password, sending the relevant form as an argument. Searching for the spikeman_password function, we find that it is almost as simple as the previous password verification function, only with a username added:

31
32
33
34
35
36
37
38
39
40
41
42
      <!----- Script CopyRight © 1996 - 1997  S.Chris Brown (Spikeman)
      function Spikeman_password(form) { 
        if (form.Name.value=="Gates") { 
          if (form.Password.value=="moneymoneymoney") {
            window.open ("yes.php","_self")
          } else { 
            alert("Sorry " +form.Name.value+ ", wrong password.")
          } 
        } else { 
          alert("Invalid Name") 
        } 
      }

The function checks whether or not the username equals “Gates” and the password equals “moneymoneymoney”. Enter those values, and the mission is accomplished.

A thought: Why wasn’t this password field a real password field, i.e. with the input hidden?