RSS

Leetmore CTF 2012: Web 100 (Pentagon Authentication)

This entry was posted on Oct 18 2012

This webchallenge asks for a password. The validation is done in javascript. If the correct password is passed, the flag is displayed. The HTML of the page was:









If no password is supplied, the loop is broken and the page doesn’t prompt for password anymore.

if (SuppliedPassword === null) {
break;
}

Password is exactly 12 characters long.

if (SuppliedPassword.length == 12) {
PasswordIsCorrect = true;
}

N = Number, C = Character

 0  1  2  3 4  5  6  7 8  9  10 11
 N N  N       N        N  

 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;
}

C(0) + C(1) + C(2) + C(6) + C(10) = 12

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;
}

 0  1  2  3 4  5  6  7 8  9  10 11
 N N  N       N  d      N  

var PasswordPrompt = "Enter the password";
.
.
.
if (SuppliedPassword.charAt(7) != PasswordPrompt.charAt(PasswordPrompt.length - 1)) {
PasswordIsCorrect = false;
}

C(8) = C(7) + 1

 0  1  2  3 4  5  6  7 8  9  10 11
 9 1  1  i  n   1  d e  j  0 b

if (SuppliedPassword.charCodeAt(7) != SuppliedPassword.charCodeAt(8) - Number(SuppliedPassword.charAt(0)) / Number(SuppliedPassword.charAt(0))) {
PasswordIsCorrect = false;
}

N(1) = N(2) = N(6)

if (Number(SuppliedPassword.charAt(2)) != Number(SuppliedPassword.charAt(6)) || Number(SuppliedPassword.charAt(6)) != Number(SuppliedPassword.charAt(1))) {
PasswordIsCorrect = false;
}

Either (N(1) = 0 OR N(10) = 0 OR BOTH = 0

if (Number(SuppliedPassword.charAt(1)) * Number(SuppliedPassword.charAt(10)) != 0) {
PasswordIsCorrect = false;
}

N(0) – N(10) = 1

if (Number(SuppliedPassword.charAt(1)) - Number(SuppliedPassword.charAt(10)) != SuppliedPassword.charAt(3).length) {
PasswordIsCorrect = false;
}

Combining the above two, N(1) = 1, N(10) = 0

 0  1  2  3 4  5  6  7 8  9  10 11
 N 1  1       1  d  e    0  

Also, C(0) + C(1) + C(2) + C(6) + C(10) = 12, hence C(0) = 12 – (1 + 1+ 1) = 9

 0  1  2  3 4  5  6  7 8  9  10 11
 9 1  1       1  d  e    0  

var TodaysSecretPassphrase = "Climbing is dangerous";
.
.
.
if (SuppliedPassword.charAt(11) + SuppliedPassword.charAt(3) + SuppliedPassword.charAt(4) != TodaysSecretPassphrase.substr(Number(SuppliedPassword.charAt(0)) / 2, 3)) {
PasswordIsCorrect = false;
}

 0  1  2  3 4  5  6  7
 C l  i  m  b i n  g

It concatenates C(11), C(3), C(4) and compares with the substring “bin”

 0  1  2  3 4  5  6  7 8  9  10 11
 9 1  1  i  n   1  d  e    0 b

C(9) is in lowercase

if (! IsLowercase(SuppliedPassword.charAt(9))) {
PasswordIsCorrect = false;
}

C(9) is not in the list of the characters found in QuoteOfTheDay

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.";

if (QuoteOfTheDay.indexOf(SuppliedPassword.charAt(9)) != -1) {
PasswordIsCorrect = false;
}

So, here’s a nice Python script to find the character.

>>> 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.";
>>> qotd_set = set()
>>> for c in QuoteOfTheDay:
... qotd_set(c)
...
>>> for c in QuoteOfTheDay:
... qotd_set.add(c)
...
>>> qotd_set
set([' ', ',', '.', 'a', 'c', 'b', 'e', 'd', 'g', 'f', 'i', 'h', 'k',
'm', 'l', 'o', 'n', 'q', 'p', 's', 'r', 'u', 't', 'w', 'v', 'y', 'x',
'z'])
>>> qotd_list = list()
>>> for c in qotd_set:
... qotd_list.append(c)
...
>>> qotd_list.sort()
>>> print qotd_list
[' ', ',', '.', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'k', 'l',
'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']

C(9) = j

 0  1  2  3 4  5  6  7 8  9  10 11
 9 1  1  i  n   1  d  e  j  0 b

Entering the password “911in 1dej0b” displays the flag, but it disappears after a 5 seconds. To fix this, save the HTML and delete this part of the code to disable the timer:

ar count = 4;
var int = setInterval(function () {
if (!count) {
document.getElementsByTagName('div')[0].innerHTML = "****************************";
document.getElementsByTagName('b')[0].innerHTML = "##########################";
document.getElementsByTagName('big')[0].innerHTML = "-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-";
clearInterval(int);
return;
}
document.getElementsByTagName('big')[0].innerHTML +=count--+".. ";
}, 400);

Now the flag is calculated by the remaining portion of the Javascript

if (PasswordIsCorrect) {
var a = 4, b = 8, c, d, e = 3, f = 7, g = 9, h = 4, i = 1, j = 7, k, l, o, l, o, l, o, l, r = 9, s = 5, n = 123;
for (i = 0; i < 1337; i++) {
b = a = d = a = s = s = 1337;
f = e = d = e = r = a = l = Number(SuppliedPassword.charAt(s / 222));
h = e = d = g = e = h = o = g = s = Math.tan(g*e*r*i*n*e) + Math.sin(l−a−s−e−r);
if (i > Number(SuppliedPassword.charAt(1)) * Number(SuppliedPassword.charAt(0))) {
break;
}
}
for (j = 0; j > o; j−−) {
f = SuppliedPassword.substr(4, 1) + (f − f);
s += f.substr(f, f);
f += s[0] + SuppliedPassword[8] + "v" + SuppliedPassword.charAt(3);
g = (TodaysSecretPassphrase.substr(12, 3) + 'c' + f[3]).replace(/\x61/, f.charAt(3));
f = f + g + String.fromCharCode(s.charCodeAt(0)) + f[1];
f += f[8] + (f[f.length − 1] * 1 + 1) + /y/.source + f.charAt(f.length / 2 + 5);
f = f + "th";
f += String.fromCharCode(SuppliedPassword[9].charCodeAt(0) − 1) + String.fromCharCode(SuppliedPassword[11].charCodeAt(0) + 17);
f = f + f[f.length / 3 + 2 * 1 * 2] + s.substr(3, 4)
}

Solution: n0-evidence-0n1y-this-8030

Post a Comment