//This is a 1 line comment/* This is a multiline comment*/#!This is a 1 line comment, but "#!" must to be at the beggining of the line-->This is a 1 line comment, but "-->" must to be at the beggining of the linefor (let j =0; j <128; j++) {for (let k =0; k <128; k++) {for (let l =0; l <128; l++) {if (j ==34|| k ==34|| l ==34)continue;if (j ==0x0a|| k ==0x0a|| l ==0x0a)continue;if (j ==0x0d|| k ==0x0d|| l ==0x0d)continue;if (j ==0x3c|| k ==0x3c|| l ==0x3c)continue;if ((j ==47&& k ==47)||(k ==47&& l ==47))continue;try {var cmd =String.fromCharCode(j) +String.fromCharCode(k) +String.fromCharCode(l) +'a.orange.ctf"';eval(cmd);} catch(e) {var err =e.toString().split('\n')[0].split(':')[0];if (err ==='SyntaxError'|| err ==="ReferenceError")continueerr =e.toString().split('\n')[0]}console.log(err,cmd);}}}//From: https://balsn.tw/ctf_writeup/20191012-hitconctfquals/#bounty-pl33z// From: Heyes, Gareth. JavaScript for hackers: Learn to think like a hacker (p. 43). Kindle Edition.log=[];for(let i=0;i<=0xff;i++){for(let j=0;j<=0xfff;j++){try {eval(`${String.fromCodePoint(i,j)}%$£234$`)log.push([i,j])}catch(e){}}}console.log(log)//[35,33],[47,47]
Gültige JS-Zeilenumbruchzeichen
//Javascript interpret as new line these chars:String.fromCharCode(10) //0x0aString.fromCharCode(13) //0x0dString.fromCharCode(8232) //0xe2 0x80 0xa8String.fromCharCode(8233) //0xe2 0x80 0xa8for (let j =0; j <65536; j++) {try {var cmd ='"aaaaa";'+String.fromCharCode(j) +'-->a.orange.ctf"';eval(cmd);} catch(e) {var err =e.toString().split('\n')[0].split(':')[0];if (err ==='SyntaxError'|| err ==="ReferenceError")continue;err =e.toString().split('\n')[0]}console.log(`[${err}]`,j,cmd);}//From: https://balsn.tw/ctf_writeup/20191012-hitconctfquals/#bounty-pl33z
Gültige JS-Leerzeichen im Funktionsaufruf
// Heyes, Gareth. JavaScript for hackers: Learn to think like a hacker (pp. 40-41). Kindle Edition.// Check chars that can be put in between in func name and the ()functionx(){}log=[];for(let i=0;i<=0x10ffff;i++){try {eval(`x${String.fromCodePoint(i)}()`)log.push(i)}catch(e){}}console.log(log)v//9,10,11,12,13,32,160,5760,8192,8193,8194,8195,8196,8197,8198,8199,8200,8201,8202,813 232,8233,8239,8287,12288,65279
Gültige Zeichen zur Generierung von Zeichenfolgen
// Heyes, Gareth. JavaScript for hackers: Learn to think like a hacker (pp. 41-42). Kindle Edition.// Check which pairs of chars can make something be a valid stringlog=[];for(let i=0;i<=0x10ffff;i++){try {eval(`${String.fromCodePoint(i)}%$£234${String.fromCodePoint(i)}`)log.push(i)}catch(e){}}console.log(log) //34,39,47,96//single quote, quotes, backticks & // (regex)
Surrogate Pairs BF
Diese Technik wird für XSS nicht sehr nützlich sein, könnte jedoch hilfreich sein, um WAF-Schutzmaßnahmen zu umgehen. Dieser Python-Code erhält als Eingabe 2 Bytes und sucht nach einem Surrogatpaar, bei dem das erste Byte das letzte Byte des High-Surrogatpaars und das letzte Byte das letzte Byte des Low-Surrogatpaars ist.
def unicode(findHex):for i inrange(0,0xFFFFF):H =hex(int(((i -0x10000) /0x400) +0xD800))h =chr(int(H[-2:],16))L =hex(int(((i -0x10000) %0x400+0xDC00)))l =chr(int(L[-2:],16))if(h == findHex[0]) and (l == findHex[1]):print(H.replace("0x","\\u")+L.replace("0x","\\u"))
javascript{}: Protokoll-Fuzzing
// Heyes, Gareth. JavaScript for hackers: Learn to think like a hacker (p. 34). Kindle Edition.log=[];let anchor =document.createElement('a');for(let i=0;i<=0x10ffff;i++){anchor.href =`javascript${String.fromCodePoint(i)}:`;if(anchor.protocol ==='javascript:') {log.push(i);}}console.log(log)//9,10,13,58// Note that you could BF also other possitions of the use of multiple chars// Test one optionlet anchor =document.createElement('a');anchor.href =`javascript${String.fromCodePoint(58)}:alert(1337)`;anchor.append('Click me')document.body.append(anchor)// Another way to test<ahref="javascript:alert(1337)">Test</a>
URL Fuzzing
// Heyes, Gareth. JavaScript for hackers: Learn to think like a hacker (pp. 36-37). Kindle Edition.// Before the protocola=document.createElement('a');log=[];for(let i=0;i<=0x10ffff;i++){a.href =`${String.fromCodePoint(i)}https://hacktricks.xyz`;if(a.hostname ==='hacktricks.xyz'){log.push(i);}}console.log(log) //0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32// Between the slashesa=document.createElement('a');log=[];for(let i=0;i<=0x10ffff;i++){a.href =`/${String.fromCodePoint(i)}/hacktricks.xyz`;if(a.hostname ==='hacktricks.xyz'){log.push(i);}}console.log(log) //9,10,13,47,92
HTML Fuzzing
// Heyes, Gareth. JavaScript for hackers: Learn to think like a hacker (p. 38). Kindle Edition.// Fuzzing chars that can close an HTML commentlet log=[];let div =document.createElement('div');for(let i=0;i<=0x10ffff;i++){div.innerHTML=`<!----${String.fromCodePoint(i)}><span></span>-->`;if(div.querySelector('span')){log.push(i);}}console.log(log)//33,45,62
Der Dekrement-Operator -- ist ebenfalls eine Zuweisung. Dieser Operator nimmt einen Wert und dekrementiert ihn dann um eins. Wenn dieser Wert keine Zahl ist, wird er auf NaN gesetzt. Dies kann verwendet werden, um den Inhalt von Variablen aus der Umgebung zu entfernen.
Funktionen Tricks
.call und .apply
Die .call-Methode einer Funktion wird verwendet, um die Funktion auszuführen.
Das erste Argument, das sie standardmäßig erwartet, ist der Wert von this und wenn nichts bereitgestellt wird, wird window dieser Wert sein (es sei denn, strict mode wird verwendet).
functiontest_call(){console.log(this.value); //baz}new_this={value:"hey!"}test_call.call(new_this);// To pass more arguments, just pass then inside .call()functiontest_call() {console.log(arguments[0]); //"arg1"console.log(arguments[1]); //"arg2"console.log(this); //[object Window]}test_call.call(null,"arg1","arg2")// If you use the "use strict" directive "this" will be null instead of window:functiontest_call() {"use strict";console.log(this); //null}test_call.call(null)//The apply function is pretty much exactly the same as the call function with one important difference, you can supply an array of arguments in the second argument:functiontest_apply() {console.log(arguments[0]); //"arg1"console.log(arguments[1]); //"arg2"console.log(this); //[object Window]}test_apply.apply(null, ["arg1","arg2"])
Arrow-Funktionen
Arrow-Funktionen ermöglichen es Ihnen, Funktionen einfacher in einer einzigen Zeile zu erstellen (wenn Sie sie verstehen).
// Traditionalfunction (a){ return a +1; }// Arrow formsa => a +100;a => {a +100};// Traditionalfunction (a, b){ return a + b +1; }// Arrow(a, b) => a + b +100;// Tradictional no argslet a =4;let b =2;function (){ return a + b +1; }// Arrowlet a =4;let b =2;() => a + b +1;
So, die meisten der vorherigen Funktionen sind tatsächlich nutzlos, da wir sie nirgendwo speichern, um sie zu speichern und aufzurufen. Beispiel: Erstellen der plusone-Funktion:
// Traductionalfunctionplusone (a){ return a +1; }//Arrowplusone= a => a +100;
Bind-Funktion
Die Bind-Funktion ermöglicht es, eine Kopie einer Funktion zu erstellen, die das this-Objekt und die gegebenen Parameter ändert.
//This will use the this object and print "Hello World"varfn=function ( param1, param2 ) {console.info( this, param1, param2 );}fn('Hello','World')//This will still use the this object and print "Hello World"var copyFn =fn.bind();copyFn('Hello','World')//This will use the "console" object as "this" object inside the function and print "fixingparam1 Hello"var bindFn_change =fn.bind(console,"fixingparam1");bindFn_change('Hello','World')//This will still use the this object and print "fixingparam1 Hello"var bindFn_thisnull =fn.bind(null,"fixingparam1");bindFn_change('Hello','World')//This will still use the this object and print "fixingparam1 Hello"var bindFn_this =fn.bind(this,"fixingparam1");bindFn_change('Hello','World')
Beachten Sie, dass Sie mit bind das this-Objekt manipulieren können, das beim Aufrufen der Funktion verwendet wird.
Funktionscode-Leck
Wenn Sie das Objekt einer Funktion zugreifen können, können Sie den Code dieser Funktion erhalten.
functionafunc(){return1+1;}console.log(afunc.toString()); //This will print the code of the functionconsole.log(String(afunc)); //This will print the code of the functionconsole.log(this.afunc.toString()); //This will print the code of the functionconsole.log(global.afunc.toString()); //This will print the code of the function
In Fällen, in denen die Funktion keinen Namen hat, können Sie dennoch den Funktionscode von innen ausgeben:
Sandbox Escape - Wiederherstellung des Window-Objekts
Das Window-Objekt ermöglicht den Zugriff auf global definierte Funktionen wie alert oder eval.
// Some ways to access windowwindow.eval("alert(1)")framesglobalThisparentselftop //If inside a frame, this is top most window// Access window from documentdocument.defaultView.alert(1)// Access document from a node objectnode =document.createElement('div')node.ownerDocument.defaultView.alert(1)// There is a path property on each error event whose last element is the window<imgsrconerror=event.path.pop().alert(1337)>// In other browsers the method is<img srconerror=event.composedPath().pop().alert(1337)>// In case of svg, the "event" object is called "evt"<svg><image href=1 onerror=evt.composedPath().pop().alert(1337)>// Abusing Error.prepareStackTrace to get Window backError.prepareStackTrace=function(error, callSites){2 callSites.shift().getThis().alert(1337);3 };4 new Error().stack// From an HTML event// Events from HTML are executed in this contextwith(document) {with(element) {//executed event}}// Because of that with(document) it's possible to access properties of document like:<img srconerror=defaultView.alert(1337)><img srconerror=s=createElement('script');s.append('alert(1337)');appendChild(s)>
Haltepunkt beim Zugriff auf den Wert
// Stop when a property in sessionStorage or localStorage is set/get// via getItem or setItem functionssessionStorage.getItem =localStorage.getItem=function(prop) {debugger;return sessionStorage[prop];}localStorage.setItem=function(prop, val) {debugger;localStorage[prop] = val;}
// Stop when anyone sets or gets the property "ppmap" in any object// For example sessionStorage.ppmap// "123".ppmap// Useful to find where weird properties are being set or accessed// or to find where prototype pollutions are occurringfunctiondebugAccess(obj, prop, debugGet=true){var origValue = obj[prop];Object.defineProperty(obj, prop, {get:function () {if ( debugGet )debugger;return origValue;},set:function(val) {debugger;origValue = val;}});};debugAccess(Object.prototype,'ppmap')
Automatischer Browserzugriff zum Testen von Payloads
//Taken from https://github.com/svennergr/writeups/blob/master/inti/0621/README.mdconstpuppeteer=require("puppeteer");constrealPasswordLength=3000;asyncfunctionsleep(ms) {returnnewPromise((resolve) =>setTimeout(resolve, ms));}(async () => {constbrowser=awaitpuppeteer.launch();constpage=awaitbrowser.newPage();//Loop to iterate through different valuesfor (let i =0; i <10000; i +=100) {console.log(`Run number ${i}`);constinput=`${"0".repeat(i)}${realPasswordLength}`;console.log(` https://challenge-0621.intigriti.io/passgen.php?passwordLength=${input}&allowNumbers=true&allowSymbols=true×tamp=1624556811000`);//Go to the pageawaitpage.goto(`https://challenge-0621.intigriti.io/passgen.php?passwordLength=${input}&allowNumbers=true&allowSymbols=true×tamp=1624556811000`);//Call function "generate()" inside the pageawaitpage.evaluate("generate()");//Get node inner text from an HTML elementconstpasswordContent=awaitpage.$$eval(".alert .page-content",(node) => node[0].innerText);//Transform the content and print it in consoleconstplainPassword=passwordContent.replace("Your password is: ","");if (plainPassword.length!= realPasswordLength) {console.log(i,plainPassword.length, plainPassword);}awaitsleep(1000);}awaitbrowser.close();})();