Forrás

A feladathoz egy zip fájl, azon belül mindössze egy index.html fájl tartozik. Ebből a lényegi rész csupán ez az egy hosszú sor:

async function checkCredentials(){var t=document.getElementById("access-user").value, r=document.getElementById("access-code").value;c1="NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm",c2="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",n1=[5,6,7,8,9,0,1,2,3,4],n2="0123456789";var n=(e,t,r)=>e.reduce(((e,r,n)=>r.apply(e,t[n])),r),c=[""],i=String.prototype.split,a=Array.prototype.join,o=Array.prototype.filter,p=Array.prototype.map,l=String.prototype.slice,y=String.prototype.repeat,u=Array.prototype.indexOf,s=Array.prototype.reduce,d=Array.prototype.reverse,h=function(e){return this==e},f=function(e){return indexedDB.cmp(this,e)},A=String.prototype.charAt;if([[[i,p,f,h],[c,[e=>-1==u.call(c2,e)?e:c1[u.call(c2,e)]],[["n","q","z","v","a"]],[0]],t],[[l,y,i,p,o,f,h],[[0,4],[3],c,[e=>-1==u.call(c2,e)?e:c1[u.call(c2,e)]],[(e,t)=>t%3==1],[["G","U","{","O"]],[0]],r],[[l,function(){return encodeURI(this)},l,function(e){return parseInt(this,e)},function(e){return this^e},h],[[-1],[],[-2],[16],[96],[29]],r],[[i,s,h],[c,[e=>e+e,1],[16777216]],r],[[y,i,p,s,h],[[21],c,[e=>n1[u.call(n2,e)]],[(e,t)=>e+h.apply(t,[8]),0],[63]],r],[[i,o,p,d,a,h],[c,[(e,t)=>~u.call([4,11,13,14,16,17,20,22],t)],[e=>c1[u.call(c2,e)]],[],["-"],["E-X-U-P-J-C-Q-S"]],r],[[function(){return Array.from(this)},f,h],[[],[["_"]],[0]],new Set(n([l,i,d,o],[[12,16],c,[],[(e,t)=>~u.apply([0,3],[t])]],r))],[[i,d,o,function(){return this.slice(2,this.length).concat(this.slice(0,2))},d,a,h],[c,[],[(e,t)=>~u.apply([18,13,4,16,15],[t])],[],[],[""],["ncrnt"]],r],[[A,h],[[6],["0"]],r]].reduce(((e,t)=>e&&n.apply(void 0,t)),!0)){var v=new Uint8Array((new TextEncoder).encode(r)),g=new Uint8Array(await crypto.subtle.digest("SHA-256",v)),m=new Uint8Array([9,87,39,96,151,202,140,186,120,235,167,229,47,231,6,212,77,205,58,14,248,104,169,79,116,140,236,98,126,26,100,120]);0==indexedDB.cmp(g,m)?activate():alert("User is not authorized. This incident will be reported.")}else alert("User is not authorized.")}

Magyarázat

Meglehetősen obfuszkálva van, de egy kis tördelés és refaktorálás után érthetőbb:

async function checkCredentials() {
    var username = document.getElementById("access-user").value;
    var code = document.getElementById("access-code").value;
    var alphabet2 = "NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm";
    var alphabet  = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    var numbers_array = [5, 6, 7, 8, 9, 0, 1, 2, 3, 4];
    var numbers_str = "0123456789";
    function n (operations, operands, first_argument) {
        operations.reduce(
            (prev, curr, index) => curr.apply(prev, operands[index]), 
            first_argument
        );
    }
    var is_equals_to_this = function (e) {
            return this == e;
        };
    var cmp_to_this = function (e) {
            return indexedDB.cmp(this, e);
        };
    if (
        [
            [
                [String.prototype.split, Array.prototype.map, cmp_to_this, is_equals_to_this], 
                [[""], [(e) => (-1 == Array.prototype.indexOf.call(alphabet, e) ? e : alphabet2[Array.prototype.indexOf.call(alphabet, e)])], [["n", "q", "z", "v", "a"]], [0]], 
                username
            ],
            [
                [String.prototype.slice, String.prototype.repeat, String.prototype.split, Array.prototype.map, Array.prototype.filter, cmp_to_this, is_equals_to_this], 
                [[0, 4], [3], [""], [(e) => (-1 == Array.prototype.indexOf.call(alphabet, e) ? e : alphabet2[Array.prototype.indexOf.call(alphabet, e)])], [(e, t) => t % 3 == 1], [["G", "U", "{", "O"]], [0]], 
                code
            ],
            [
                [String.prototype.slice, function () { return encodeURI(this); }, String.prototype.slice, function (e) { return parseInt(this, e); }, function (e) { return this ^ e; }, is_equals_to_this],
                [[-1], [], [-2], [16], [96], [29]],
                code,
            ],
            [
                [String.prototype.split, Array.prototype.reduce, is_equals_to_this], 
                [[""], [(e) => e + e, 1], [16777216]], 
                code
            ],
            [
                [String.prototype.repeat, String.prototype.split, Array.prototype.map, Array.prototype.reduce, is_equals_to_this], 
                [[21], [""], [(e) => numbers_array[Array.prototype.indexOf.call(numbers_str, e)]], [(e, t) => e + is_equals_to_this.apply(t, [8]), 0], [63]], 
                code
            ],
            [
                [String.prototype.split, Array.prototype.filter, Array.prototype.map, Array.prototype.reverse, Array.prototype.join, is_equals_to_this], 
                [[""], [(e, t) => ~Array.prototype.indexOf.call([4, 11, 13, 14, 16, 17, 20, 22], t)], [(e) => alphabet2[Array.prototype.indexOf.call(alphabet, e)]], [], ["-"], ["E-X-U-P-J-C-Q-S"]], 
                code
            ],
            [
                [function () { return Array.from(this); }, cmp_to_this, is_equals_to_this],
                [[], [["_"]], [0]],
                new Set(n([String.prototype.slice, String.prototype.split, Array.prototype.reverse, Array.prototype.filter], [[12, 16], [""], [], [(e, t) => ~Array.prototype.indexOf.apply([0, 3], [t])]], code)),
            ],
            [
                [String.prototype.split, Array.prototype.reverse, Array.prototype.filter, function () { return this.slice(2, this.length).concat(this.slice(0, 2)); }, Array.prototype.reverse, Array.prototype.join, is_equals_to_this],
                [[""], [], [(e, t) => ~Array.prototype.indexOf.apply([18, 13, 4, 16, 15], [t])], [], [], [""], ["ncrnt"]],
                code,
            ],
            [
                [String.prototype.charAt, is_equals_to_this], 
                [[6], ["0"]], 
                code
            ],
        ].reduce((prev, curr) => prev && n.apply(void 0, curr), true)
    ) {
        var code_bytes = new Uint8Array(new TextEncoder().encode(code));
        var code_hash = new Uint8Array(await crypto.subtle.digest("SHA-256", code_bytes));
        var correct_hash = new Uint8Array([9, 87, 39, 96, 151, 202, 140, 186, 120, 235, 167, 229, 47, 231, 6, 212, 77, 205, 58, 14, 248, 104, 169, 79, 116, 140, 236, 98, 126, 26, 100, 120]);
        0 == indexedDB.cmp(code_hash, correct_hash) ? activate() : alert("User is not authorized. This incident will be reported.");
    } else alert("User is not authorized.");
}

Cél

A függvényben lévő feltételben találhatóak nyomok a jelszó, azaz a flag egyes karaktereire. Ezeket felhasználva kell kitalálni mi is a flag.

Megoldás

Vegyük sorra a feltételeket és azt, hogy mi derül ki belőlük.

indexedDB.cmp(username.split("").map((e) => (-1 == alphabet.indexOf(e) ? e : alphabet2[alphabet.indexOf(e)])), ["n", "q", "z", "v", "a"]) == 0

username == "admin" Ez igazából nem releváns a megoldáshoz.

indexedDB.cmp(code.slice(0, 4).repeat(3).split("").map((e) => (-1 == alphabet.indexOf(e) ? e : alphabet2[alphabet.indexOf(e)])).filter((e, t) => t % 3 == 1), ["G", "U", "{", "O"]) == 0

code[0:4] == "HTB{"

parseInt(encodeURI(code.slice(-1)).slice(-2), 16) ^ 96 == 29 

code[-1] == "}"

code.split("").reduce((e) => e + e, 1) == 16777216 

len(code) == 24

code.repeat(21).split("").map((e) => numbers_array[numbers_str.indexOf(e)]).reduce((e, t) => e + t == 8, 0) == 63 

code.count('3') == 3

code.split("").filter((e, t) => ~[4, 11, 13, 14, 16, 17, 20, 22].indexOf(t)).map((e) => alphabet2[alphabet.indexOf(e)]).reverse().join("-") == "E-X-U-P-J-C-Q-S" 

code[4] == "F" and code[11] == "D" and code[13] == "P" and code[14] == "W" and code[16] == "C" and code[17] == "H" and code[20] == "K" code[22] == "R"

indexedDB.cmp(Array.from(new Set(code.slice(12, 16).split("").reverse().filter((e, t) => ~[0, 3].indexOf(t)))), ["_"]) == 0 

code[12] == "_" and code[15] == "_"

code.split("").reverse().filter((e, t) => ~[18, 13, 4, 16, 15].indexOf(t)).slice(2).concat(this.slice(0, 2)).reverse().join("") == "ncrnt" 

code[19] == "c" and code[10] == "n" and code[8] == "t" and code[7] == "n" and code[5] == "r"

code.charAt(6) == "0" 

code[6] == "0"

Végül mindet megfejtve fény derül a teljes flagre: code == "HTB{Fr0nt3nD_PW_CH3cK3R}"