Monday, October 15, 2012

hackyou CTF: Web 100

Web 100 was a classic javascript password that was just a complicated formula. The entered password was used to generate the key so you had to actually break the password. Here is the relevant part of the script.
var PasswordIsCorrect = false;
var PasswordPrompt = "Enter the password";
var TodaysSecretPassphrase = "Climbing is dangerous";
var QuoteOfTheDay = "the beige hue on the waters of the loch impressed all, including the zapped french queen, before she heard that symphony again, as kind young arthur wanted. keen oxygen vendor.";
do {
  var SuppliedPassword = prompt(PasswordPrompt);
  if (SuppliedPassword === null) {
 break;
  }

  if (SuppliedPassword.length == 12) {
 PasswordIsCorrect = true;
  }
  if (! IsNumber(SuppliedPassword.charAt(0))) {
 PasswordIsCorrect = false;
  }
  if (! IsNumber(SuppliedPassword.charAt(10)) || ! IsNumber(SuppliedPassword.charAt(1))) {
 PasswordIsCorrect = false;
  }
  if (! IsNumber(SuppliedPassword.charAt(6)) || ! IsNumber(SuppliedPassword.charAt(2))) {
 PasswordIsCorrect = false;
  }
  if (Number(SuppliedPassword.charAt(0)) + Number(SuppliedPassword.charAt(1)) + Number(SuppliedPassword.charAt(2)) + Number(SuppliedPassword.charAt(6)) + Number(SuppliedPassword.charAt(10)) != SuppliedPassword.length) {
 PasswordIsCorrect = false;
  }
  if (SuppliedPassword.charAt(7) != PasswordPrompt.charAt(PasswordPrompt.length - 1)) {
 PasswordIsCorrect = false;
  }
  if (SuppliedPassword.charCodeAt(7) != SuppliedPassword.charCodeAt(8) - Number(SuppliedPassword.charAt(0)) / Number(SuppliedPassword.charAt(0))) {
 PasswordIsCorrect = false;
  }
  if (Number(SuppliedPassword.charAt(2)) != Number(SuppliedPassword.charAt(6)) || Number(SuppliedPassword.charAt(6)) != Number(SuppliedPassword.charAt(1))) {
 PasswordIsCorrect = false;
  }
  if (Number(SuppliedPassword.charAt(1)) * Number(SuppliedPassword.charAt(10)) != 0) {
 PasswordIsCorrect = false;
  }
  if (Number(SuppliedPassword.charAt(1)) - Number(SuppliedPassword.charAt(10)) != SuppliedPassword.charAt(3).length) {
 PasswordIsCorrect = false;
  }
  if (Number(SuppliedPassword.charAt(1)) - Number(SuppliedPassword.charAt(10)) != SuppliedPassword.charAt(3).length) {
 PasswordIsCorrect = false;
  }
  if (SuppliedPassword.charAt(11) + SuppliedPassword.charAt(3) + SuppliedPassword.charAt(4) != TodaysSecretPassphrase.substr(Number(SuppliedPassword.charAt(0)) / 2, 3)) {
 PasswordIsCorrect = false;
  }
  if (! IsLowercase(SuppliedPassword.charAt(9))) {
 PasswordIsCorrect = false;
  }
  if (QuoteOfTheDay.indexOf(SuppliedPassword.charAt(9)) != -1) {
 PasswordIsCorrect = false;
  }

  if (! PasswordIsCorrect) {
 PasswordPrompt = "Password incorrect. Repeat the password";
  }
} while (! PasswordIsCorrect);
I solved this by going through the if statements one at a time and constructing my password as I went. All of the if statements result in the PasswordIsCorrect being set to false (except the first one). So let's do it!

1. SuppliedPassword.length == 12
   Obviously the length of the password has to be twelve, so we start with
xxxxxxxxxxxx
2. ! IsNumber(SuppliedPassword.charAt(0))
   The first char must be a number.
0xxxxxxxxxxx
3. ! IsNumber(SuppliedPassword.charAt(10)) || ! IsNumber(SuppliedPassword.charAt(1))
   The 11th and 2nd char must be a number.
00xxxxxxxx0x
4. ! IsNumber(SuppliedPassword.charAt(6)) || ! IsNumber(SuppliedPassword.charAt(2))
   The 3rd and 7th char must be a number.
000xxx0xxx0x
5. Number(SuppliedPassword.charAt(0)) + Number(SuppliedPassword.charAt(1)) + Number(SuppliedPassword.charAt(2)) + Number(SuppliedPassword.charAt(6)) + Number(SuppliedPassword.charAt(10)) ! = SuppliedPassword.length
   All of the numbers must add up to twelve.
422xxx2xxx2x
6. SuppliedPassword.charAt(7) ! = PasswordPrompt.charAt(PasswordPrompt.length - 1)
   The 8th char must be the last char of the string PasswordPrompt, which is the letter 'd'.
422xxx2dxx2x
7. SuppliedPassword.charCodeAt(7) ! = SuppliedPassword.charCodeAt(8) - Number(SuppliedPassword.charAt(0)) / Number(SuppliedPassword.charAt(0))
   The char at spot 8 must be 1 letter less than the one at 8 (charAt(0)/charAt(0) always equals 1).
422xxx2dex2x
8. Number(SuppliedPassword.charAt(2)) ! = Number(SuppliedPassword.charAt(6)) || Number(SuppliedPassword.charAt(6)) ! = Number(SuppliedPassword.charAt(1))
   The number at spot 3 must equal the 7th and the 7th must equal the second. No change.

9. Number(SuppliedPassword.charAt(1)) * Number(SuppliedPassword.charAt(10)) ! = 0
   Either the second char or the 11th must be a 0. Since the second, third, and seventh must be the same, I chose the 10th. The first number must be adjusted to keep the sum of the numbers at 12.
622xxx2dex0x
10. Number(SuppliedPassword.charAt(1)) - Number(SuppliedPassword.charAt(10)) != SuppliedPassword.charAt(3).length
   The difference between spot 2 and spot 11 must equal 1. We must then make spots 2, 3, and 7 equal to satisfy an earlier condition. We must then adjust spot 0 so that all the numbers add to 12. There is only one possible solution here so we know we are getting close to the real solution.
911xxx1dex0x
11. SuppliedPassword.charAt(11) + SuppliedPassword.charAt(3) + SuppliedPassword.charAt(4) != TodaysSecretPassphrase.substr(Number(SuppliedPassword.charAt(0)) / 2, 3)
   This says that the concatenation of the chars at spots 12, 4, and 5 must equal the substring starting at spot 0 divided by 2. Spot 0 is 9 which is divided by 2 and rounded down to 4 because it is int division. The substring of the passphrase is 'bin' to which we set the chars 12, 4, and 5.
911inx1dex0b
12. ! IsLowercase(SuppliedPassword.charAt(9))
   The 10th char must be lowercase. No change.

13. QuoteOfTheDay.indexOf(SuppliedPassword.charAt(9)) != -1
   The 10th char in our string must not be in the quote of the day (see the script above). I chose the letter 'j'.
911inx1dej0b

We now have the password and we enter it only to find out there as an annoying countdown/self-destruct sequence that destroys the key before we can copy and paste it. I used burpsuite to change the script before it got to my browser so that it took longer to time out which gave me sufficient time to copy and paste the key: n0-evidence-0n1y-this-8030.

-- suntzu_II

No comments:

Post a Comment