HackTricks
Searchโ€ฆ
๐Ÿ‘ฝ
Network Services Pentesting
๐Ÿ•ธ
Pentesting Web
Other JS Tricks
Support HackTricks and get benefits!

Javascript Characters Brute-Force

JavaScript Comments BF

1
//This is a 1 line comment
2
/* This is a multiline comment*/
3
#!This is a 1 line comment, but "#!" must to be at the beggining of the line
4
-->This is a 1 line comment, but "-->" must to be at the beggining of the line
5
โ€‹
6
โ€‹
7
for (let j = 0; j < 128; j++) {
8
for (let k = 0; k < 128; k++) {
9
for (let l = 0; l < 128; l++) {
10
if (j == 34 || k ==34 || l ==34)
11
continue;
12
if (j == 0x0a || k ==0x0a || l ==0x0a)
13
continue;
14
if (j == 0x0d || k ==0x0d || l ==0x0d)
15
continue;
16
if (j == 0x3c || k ==0x3c || l ==0x3c)
17
continue;
18
if (
19
(j == 47 && k == 47)
20
||(k == 47 && l == 47)
21
)
22
continue;
23
try {
24
var cmd = String.fromCharCode(j) + String.fromCharCode(k) + String.fromCharCode(l) + 'a.orange.ctf"';
25
eval(cmd);
26
} catch(e) {
27
var err = e.toString().split('\n')[0].split(':')[0];
28
if (err === 'SyntaxError' || err === "ReferenceError")
29
continue
30
err = e.toString().split('\n')[0]
31
}
32
console.log(err,cmd);
33
}
34
}
35
}
36
//From: https://balsn.tw/ctf_writeup/20191012-hitconctfquals/#bounty-pl33z
Copied!

Javascript New Lines BF

1
//Javascript interpret as new line these chars:
2
String.fromCharCode(10) //0x0a
3
String.fromCharCode(13) //0x0d
4
String.fromCharCode(8232) //0xe2 0x80 0xa8
5
String.fromCharCode(8233) //0xe2 0x80 0xa8
6
โ€‹
7
for (let j = 0; j < 65536; j++) {
8
try {
9
var cmd = '"aaaaa";'+String.fromCharCode(j) + '-->a.orange.ctf"';
10
eval(cmd);
11
} catch(e) {
12
var err = e.toString().split('\n')[0].split(':')[0];
13
if (err === 'SyntaxError' || err === "ReferenceError")
14
continue;
15
err = e.toString().split('\n')[0]
16
}
17
console.log(`[${err}]`,j,cmd);
18
}
19
//From: https://balsn.tw/ctf_writeup/20191012-hitconctfquals/#bounty-pl33z
Copied!

Surrogate Pairs BF

This technique won't be very useful for XSS but it could be useful to bypass WAF protections. This python code receive as input 2bytes and it search a surrogate pairs that have the first byte as the the last bytes of the High surrogate pair and the the last byte as the last byte of the low surrogate pair.
1
def unicode(findHex):
2
for i in range(0,0xFFFFF):
3
H = hex(int(((i - 0x10000) / 0x400) + 0xD800))
4
h = chr(int(H[-2:],16))
5
L = hex(int(((i - 0x10000) % 0x400 + 0xDC00)))
6
l = chr(int(L[-2:],16))
7
if(h == findHex[0]) and (l == findHex[1]):
8
print(H.replace("0x","\\u")+L.replace("0x","\\u"))
Copied!
More info:

.map js files

"--" Assignment

The decrement operator -- is also an asignment. This operator takes a value and then decrements it by one. If that value is not a number, it will be set to NaN. This can be used to remove the content of variables from the environment.

Functions Tricks

Arrow functions

Arrow functions allow you to generate functions in a single line more easily (if you understand them)
1
// Traditional
2
function (a){ return a + 1; }
3
// Arrow forms
4
a => a + 100;
5
a => {a + 100};
6
โ€‹
7
// Traditional
8
function (a, b){ return a + b + 1; }
9
// Arrow
10
(a, b) => a + b + 100;
11
โ€‹
12
// Tradictional no args
13
let a = 4;
14
let b = 2;
15
function (){ return a + b + 1; }
16
โ€‹
17
// Arrow
18
let a = 4;
19
let b = 2;
20
() => a + b + 1;
Copied!
So, most of the previous functions are actually useless because we aren't saving them anywhere to save and call them. Example creating the plusone function:
1
// Traductional
2
function plusone (a){ return a + 1; }
3
โ€‹
4
//Arrow
5
plusone = a => a + 100;
Copied!

Bind function

The bind function allow to create a copy of a function modifying the this object and the parameters given.
1
//This will use the this object and print "Hello World"
2
var fn = function ( param1, param2 ) {
3
console.info( this, param1, param2 );
4
}
5
fn('Hello', 'World')
6
โ€‹
7
//This will still use the this object and print "Hello World"
8
var copyFn = fn.bind();
9
copyFn('Hello', 'World')
10
โ€‹
11
//This will use the "console" object as "this" object inside the function and print "fixingparam1 Hello"
12
var bindFn_change = fn.bind(console, "fixingparam1");
13
bindFn_change('Hello', 'World')
14
โ€‹
15
//This will still use the this object and print "fixingparam1 Hello"
16
var bindFn_thisnull = fn.bind(null, "fixingparam1");
17
bindFn_change('Hello', 'World')
18
โ€‹
19
//This will still use the this object and print "fixingparam1 Hello"
20
var bindFn_this = fn.bind(this, "fixingparam1");
21
bindFn_change('Hello', 'World')
Copied!
Note that using bind you can manipulate the this object that is going to be used when calling the function.

Function code leak

If you can access the object of a function you can get the code of that function
1
function afunc(){
2
return 1+1;
3
}
4
console.log(afunc.toString()); //This will print the code of the function
5
console.log(String(afunc)); //This will print the code of the function
6
console.log(this.afunc.toString()); //This will print the code of the function
7
console.log(global.afunc.toString()); //This will print the code of the function
Copied!
In cases where the function doesn't have any name, you can still print the function code from within:
1
(function (){ return arguments.callee.toString(); })()
2
(function (){ return arguments[0]; })("arg0")
Copied!
Some random ways to extract the code of a function (even comments) from another function:
1
(function (){ return retFunc => String(arguments[0]) })(a=>{/* Hidden commment */})()
2
(function (){ return retFunc => Array(arguments[0].toString()) })(a=>{/* Hidden commment */})()
3
(function (){ return String(this)}).bind(()=>{ /* Hidden commment */ })()
4
(u=>(String(u)))(_=>{ /* Hidden commment */ })
5
(u=>_=>(String(u)))(_=>{ /* Hidden commment */ })()
Copied!

Breakpoint on access to value

1
// Stop when a property in sessionStorage or localStorage is set/get
2
// via getItem or setItem functions
3
sessionStorage.getItem = localStorage.getItem = function(prop) {
4
debugger;
5
return sessionStorage[prop];
6
}
7
โ€‹
8
localStorage.setItem = function(prop, val) {
9
debugger;
10
localStorage[prop] = val;
11
}
Copied!
1
// Stop when anyone sets or gets the property "ppmap" in any object
2
// For example sessionStorage.ppmap
3
// "123".ppmap
4
// Useful to find where weird properties are being set or accessed
5
// or to find where prototype pollutions are occurring
6
โ€‹
7
function debugAccess(obj, prop, debugGet=true){
8
โ€‹
9
var origValue = obj[prop];
10
โ€‹
11
Object.defineProperty(obj, prop, {
12
get: function () {
13
if ( debugGet )
14
debugger;
15
return origValue;
16
},
17
set: function(val) {
18
debugger;
19
origValue = val;
20
}
21
});
22
};
23
โ€‹
24
debugAccess(Object.prototype, 'ppmap')
Copied!

Automatic Browser Access to test payloads

1
//Taken from https://github.com/svennergr/writeups/blob/master/inti/0621/README.md
2
const puppeteer = require("puppeteer");
3
โ€‹
4
const realPasswordLength = 3000;
5
async function sleep(ms) {
6
return new Promise((resolve) => setTimeout(resolve, ms));
7
}
8
โ€‹
9
(async () => {
10
const browser = await puppeteer.launch();
11
const page = await browser.newPage();
12
//Loop to iterate through different values
13
for (let i = 0; i < 10000; i += 100) {
14
console.log(`Run number ${i}`);
15
const input = `${"0".repeat(i)}${realPasswordLength}`;
16
console.log(` https://challenge-0621.intigriti.io/passgen.php?passwordLength=${input}&allowNumbers=true&allowSymbols=true&timestamp=1624556811000`);
17
//Go to the page
18
await page.goto(
19
`https://challenge-0621.intigriti.io/passgen.php?passwordLength=${input}&allowNumbers=true&allowSymbols=true&timestamp=1624556811000`
20
);
21
//Call function "generate()" inside the page
22
await page.evaluate("generate()");
23
//Get node inner text from an HTML element
24
const passwordContent = await page.$eval(
25
".alert .page-content",
26
(node) => node[0].innerText
27
);
28
//Transform the content and print it in console
29
const plainPassword = passwordContent.replace("Your password is: ", "");
30
if (plainPassword.length != realPasswordLength) {
31
console.log(i, plainPassword.length, plainPassword);
32
}
33
โ€‹
34
await sleep(1000);
35
}
36
await browser.close();
37
})();
Copied!
Support HackTricks and get benefits!