Trucos JS Varios e Informaci贸n Relevante

tip

Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks

Fuzzing de Javascript

Caracteres de Comentario JS V谩lidos

javascript
//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 line


for (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")
continue
err = 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]

Caracteres de Nueva L铆nea JS V谩lidos

javascript
//Javascript interpret as new line these chars:
String.fromCharCode(10) //0x0a
String.fromCharCode(13) //0x0d
String.fromCharCode(8232) //0xe2 0x80 0xa8
String.fromCharCode(8233) //0xe2 0x80 0xa8

for (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

Espacios JS V谩lidos en la llamada a funci贸n

javascript
// 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 ()
function x(){}

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

Caracteres v谩lidos para generar cadenas

javascript
// 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 string
log = []
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

Esta t茅cnica no ser谩 muy 煤til para XSS, pero podr铆a ser 煤til para eludir las protecciones de WAF. Este c贸digo de python recibe como entrada 2 bytes y busca pares de sustitutos que tengan el primer byte como el 煤ltimo byte del par de sustitutos alto y el 煤ltimo byte como el 煤ltimo byte del par de sustitutos bajo.

python
def unicode(findHex):
for i in range(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{}: Fuzzing de Protocolo

javascript
// 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 option
let anchor = document.createElement('a');
anchor.href = `javascript${String.fromCodePoint(58)}:alert(1337)`;
anchor.append('Click me')
document.body.append(anchor)

// Another way to test
<a href="&#12;javascript:alert(1337)">Test</a>

Fuzzing de URL

javascript
// Heyes, Gareth. JavaScript for hackers: Learn to think like a hacker (pp. 36-37). Kindle Edition.

// Before the protocol
a = 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 slashes
a = 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

javascript
// Heyes, Gareth. JavaScript for hackers: Learn to think like a hacker (p. 38). Kindle Edition.

// Fuzzing chars that can close an HTML comment

let 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

Analizando atributos

La herramienta Hackability inspector de Portswigger ayuda a analizar los atributos de un objeto javascript. Ver: https://portswigger-labs.net/hackability/inspector/?input=x.contentWindow&html=%3Ciframe%20src=//subdomain1.portswigger-labs.net%20id=x%3E

.map archivos js

"--" Asignaci贸n

El operador de decremento -- tambi茅n es una asignaci贸n. Este operador toma un valor y luego lo decrementa en uno. Si ese valor no es un n煤mero, se establecer谩 en NaN. Esto se puede usar para eliminar el contenido de las variables del entorno.

Trucos de Funciones

.call y .apply

El m茅todo .call de una funci贸n se utiliza para ejecutar la funci贸n.
El primer argumento que espera por defecto es el valor de this y si nada se proporciona, window ser谩 ese valor (a menos que se use modo estricto).

javascript
function test_call() {
console.log(this.value) //baz
}
new_this = { value: "hey!" }
test_call.call(new_this)

// To pass more arguments, just pass then inside .call()
function test_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:
function test_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:
function test_apply() {
console.log(arguments[0]) //"arg1"
console.log(arguments[1]) //"arg2"
console.log(this) //[object Window]
}
test_apply.apply(null, ["arg1", "arg2"])

Funciones de flecha

Las funciones de flecha te permiten generar funciones en una sola l铆nea m谩s f谩cilmente (si las entiendes)

javascript
// Traditional
function (a){ return a + 1; }
// Arrow forms
a => a + 100;
a => {a + 100};

// Traditional
function (a, b){ return a + b + 1; }
// Arrow
(a, b) => a + b + 100;

// Tradictional no args
let a = 4;
let b = 2;
function (){ return a + b + 1; }

// Arrow
let a = 4;
let b = 2;
() => a + b + 1;

Entonces, la mayor铆a de las funciones anteriores son en realidad in煤tiles porque no las estamos guardando en ning煤n lugar para guardarlas y llamarlas. Ejemplo creando la funci贸n plusone:

javascript
// Traductional
function plusone(a) {
return a + 1
}

//Arrow
plusone = (a) => a + 100

Funci贸n bind

La funci贸n bind permite crear una copia de una funci贸n modificando el objeto this y los par谩metros dados.

javascript
//This will use the this object and print "Hello World"
var fn = 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")

note

Tenga en cuenta que al usar bind puede manipular el objeto this que se va a utilizar al llamar a la funci贸n.

Fuga de c贸digo de funci贸n

Si puede acceder al objeto de una funci贸n, puede obtener el c贸digo de esa funci贸n.

javascript
function afunc() {
return 1 + 1
}
console.log(afunc.toString()) //This will print the code of the function
console.log(String(afunc)) //This will print the code of the function
console.log(this.afunc.toString()) //This will print the code of the function
console.log(global.afunc.toString()) //This will print the code of the function

En los casos donde la funci贸n no tiene ning煤n nombre, a煤n puedes imprimir el c贸digo de la funci贸n desde dentro:

javascript
;(function () {
return arguments.callee.toString()
})()(function () {
return arguments[0]
})("arg0")

Algunas maneras aleatorias de extraer el c贸digo de una funci贸n (incluso comentarios) de otra funci贸n:

javascript
;(function () {
return (retFunc) => String(arguments[0])
})((a) => {
/* Hidden commment */
})()(function () {
return (retFunc) => Array(arguments[0].toString())
})((a) => {
/* Hidden commment */
})()(function () {
return String(this)
}).bind(() => {
/* Hidden commment */
})()((u) => String(u))((_) => {
/* Hidden commment */
})((u) => (_) => String(u))((_) => {
/* Hidden commment */
})()

Escape de Sandbox - Recuperando el objeto window

El objeto Window permite acceder a funciones definidas globalmente como alert o eval.

javascript
// Some ways to access window
window.eval("alert(1)")
frames
globalThis
parent
self
top //If inside a frame, this is top most window

// Access window from document
document.defaultView.alert(1)
// Access document from a node object
node = document.createElement('div')
node.ownerDocument.defaultView.alert(1)

// There is a path property on each error event whose last element is the window
<img src onerror=event.path.pop().alert(1337)>
// In other browsers the method is
<img src onerror=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 back
Error.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 context
with(document) {
with(element) {
//executed event
}
}
// Because of that with(document) it's possible to access properties of document like:
<img src onerror=defaultView.alert(1337)>
<img src onerror=s=createElement('script');s.append('alert(1337)');appendChild(s)>

Punto de interrupci贸n en el acceso al valor

javascript
// Stop when a property in sessionStorage or localStorage is set/get
// via getItem or setItem functions
sessionStorage.getItem = localStorage.getItem = function (prop) {
debugger
return sessionStorage[prop]
}

localStorage.setItem = function (prop, val) {
debugger
localStorage[prop] = val
}
javascript
// 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 occurring

function debugAccess(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")

Acceso autom谩tico al navegador para probar cargas 煤tiles

javascript
//Taken from https://github.com/svennergr/writeups/blob/master/inti/0621/README.md
const puppeteer = require("puppeteer")

const realPasswordLength = 3000
async function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms))
}

;(async () => {
const browser = await puppeteer.launch()
const page = await browser.newPage()
//Loop to iterate through different values
for (let i = 0; i < 10000; i += 100) {
console.log(`Run number ${i}`)
const input = `${"0".repeat(i)}${realPasswordLength}`
console.log(
`  https://challenge-0621.intigriti.io/passgen.php?passwordLength=${input}&allowNumbers=true&allowSymbols=true&timestamp=1624556811000`
)
//Go to the page
await page.goto(
`https://challenge-0621.intigriti.io/passgen.php?passwordLength=${input}&allowNumbers=true&allowSymbols=true&timestamp=1624556811000`
)
//Call function "generate()" inside the page
await page.evaluate("generate()")
//Get node inner text from an HTML element
const passwordContent = await page.$$eval(
".alert .page-content",
(node) => node[0].innerText
)
//Transform the content and print it in console
const plainPassword = passwordContent.replace("Your password is: ", "")
if (plainPassword.length != realPasswordLength) {
console.log(i, plainPassword.length, plainPassword)
}

await sleep(1000)
}
await browser.close()
})()

tip

Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks