4 perc
Security In The Front
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}"