Misc JS Tricks & Relevant Info

Μάθετε το χάκινγκ του AWS από το μηδέν μέχρι τον ήρωα με το htARTE (HackTricks AWS Red Team Expert)!

Αναζήτηση Σφαλμάτων στον Κώδικα Javascript

Έγκυροι Χαρακτήρες Σχολίων JS

//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]

Έγκυροι χαρακτήρες νέων γραμμών στην JS

Οι έγκυροι χαρακτήρες νέων γραμμών στην JavaScript (JS) είναι οι εξής:

  • : Αυτός ο χαρακτήρας αντιπροσωπεύει μια νέα γραμμή.

  • : Αυτός ο χαρακτήρας αντιπροσωπεύει έναν χαρακτήρα επιστροφής καρέτου.

  • \u2028: Αυτός ο χαρακτήρας αντιπροσωπεύει έναν χαρακτήρα νέας γραμμής Unicode.

  • \u2029: Αυτός ο χαρακτήρας αντιπροσωπεύει έναν χαρακτήρα παράγραφου Unicode.

Μπορείτε να χρησιμοποιήσετε αυτούς τους χαρακτήρες για να δημιουργήσετε νέες γραμμές ή να προσθέσετε κενά στον κώδικά σας στην JS.

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

Έγκυροι χώροι JS σε κλήση συνάρτησης

Ορισμένες φορές, κατά την εκτέλεση ενός XSS επιθέσεων, μπορεί να χρειαστεί να χρησιμοποιήσουμε χώρους για να αποφύγουμε την ανίχνευση του κώδικα. Ένας τρόπος για να το κάνουμε αυτό είναι να χρησιμοποιήσουμε έγκυρους χώρους σε μια κλήση συνάρτησης. Οι έγκυροι χώροι μπορούν να εισαχθούν μεταξύ των ονομάτων των παραμέτρων και των τιμών τους. Αυτό μπορεί να δημιουργήσει σύγχυση στον αναλυτή του κώδικα και να του επιτρέψει να παραβλέψει τον κακόβουλο κώδικα που εισάγεται.

Παράδειγμα:

<script>
  function myFunction(param1, param2) {
    // Κανονικός κώδικας εδώ
  }
  
  myFunction('value1', 'value2');
</script>

Σε αυτό το παράδειγμα, μπορούμε να εισάγουμε έγκυρους χώρους μεταξύ των παραμέτρων και των τιμών τους, όπως παρακάτω:

<script>
  function myFunction(param1, param2) {
    // Κακόβουλος κώδικας εδώ
  }
  
  myFunction('value1', 'value2');
</script>

Αυτό μπορεί να καταστήσει δυσκολότερη την ανίχνευση του κακόβουλου κώδικα από τους αναλυτές του κώδικα.

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

Έγκυροι χαρακτήρες για τη δημιουργία συμβολοσειρών

The following characters can be used to generate strings:

Οι παρακάτω χαρακτήρες μπορούν να χρησιμοποιηθούν για τη δημιουργία συμβολοσειρών:

abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ
0123456789
!@#$%^&*()_+-=[]{}|;':",./<>?

These characters are considered valid and can be used in various scenarios during hacking activities.

Αυτοί οι χαρακτήρες θεωρούνται έγκυροι και μπορούν να χρησιμοποιηθούν σε διάφορα σενάρια κατά τη διάρκεια δραστηριοτήτων χάκερ.

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

Αυτή η τεχνική δεν θα είναι πολύ χρήσιμη για XSS, αλλά μπορεί να χρησιμοποιηθεί για να παρακάμψει προστασίες WAF. Αυτός ο κώδικας Python λαμβάνει ως είσοδο 2 bytes και αναζητά surrogate pairs που έχουν το πρώτο byte ως τα τελευταία bytes του High surrogate pair και το τελευταίο byte ως το τελευταίο byte του low surrogate pair.

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{}:

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

URL Fuzzing

URL Fuzzing είναι μια τεχνική που χρησιμοποιείται για να εντοπίσει ευπάθειες σε μια εφαρμογή ιστού. Σε αυτήν την τεχνική, ο χάκερ δοκιμάζει διάφορες παραλλαγές των URLs για να ελέγξει αν υπάρχουν ευπάθειες ασφαλείας. Αυτό μπορεί να γίνει με την προσθήκη ειδικών χαρακτήρων, παραμέτρων ή διαδρομών στο URL.

Ο χάκερ μπορεί να χρησιμοποιήσει εργαλεία αυτοματοποίησης για να δοκιμάσει χιλιάδες διαφορετικές παραλλαγές των URLs σε σύντομο χρονικό διάστημα. Αυτό του επιτρέπει να εντοπίσει ευπάθειες όπως Cross-Site Scripting (XSS), SQL Injection και πολλές άλλες.

Η URL Fuzzing είναι μια ισχυρή τεχνική που μπορεί να αποκαλύψει ευπάθειες σε μια εφαρμογή ιστού και να βοηθήσει τον χάκερ να εκμεταλλευτεί αυτές τις ευπάθειες για κακόβουλους σκοπούς.

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

Το HTML Fuzzing είναι μια τεχνική που χρησιμοποιείται για να εντοπίσει ευπάθειες στον κώδικα HTML μιας ιστοσελίδας. Κατά τη διάρκεια του HTML Fuzzing, εισάγονται διάφορες μορφές εισόδου στα πεδία εισαγωγής της ιστοσελίδας, με σκοπό να ελεγχθεί η αντίδραση της εφαρμογής σε αυτές τις εισόδους.

Ο στόχος του HTML Fuzzing είναι να ανακαλυφθούν ευπάθειες όπως Cross-Site Scripting (XSS) επιθέσεις, ανεπαρκής επικύρωση εισόδου και άλλες ασφαλείας σχετικές ευπάθειες. Με τη χρήση διαφορετικών μορφών εισόδου, όπως ειδικοί χαρακτήρες, μεγάλα μεγέθη δεδομένων και ανεπιθύμητα σύμβολα, μπορούν να ανακαλυφθούν ευπάθειες που δεν θα είχαν ανακαλυφθεί με την κανονική χρήση της εφαρμογής.

Η διαδικασία του HTML Fuzzing μπορεί να γίνει χειροκίνητα ή αυτοματοποιημένα, χρησιμοποιώντας εργαλεία όπως το Burp Suite ή το OWASP ZAP. Με την ανίχνευση ευπαθειών μέσω του HTML Fuzzing, οι επιτιθέμενοι μπορούν να εκμεταλλευτούν τις ευπάθειες αυτές για να προκαλέσουν ζημιά στην εφαρμογή ή να αποκτήσουν πρόσβαση σε ευαίσθητες πληροφορίες.

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

Ανάλυση των χαρακτηριστικών

Το εργαλείο Hackability inspector από την Portswigger βοηθά στην ανάλυση των χαρακτηριστικών ενός αντικειμένου JavaScript. Ελέγξτε: https://portswigger-labs.net/hackability/inspector/?input=x.contentWindow&html=%3Ciframe%20src=//subdomain1.portswigger-labs.net%20id=x%3E

.map αρχεία js

"--" Ανάθεση

Ο τελεστής μείωσης -- είναι επίσης μια ανάθεση. Αυτός ο τελεστής παίρνει μια τιμή και μειώνει την κατά ένα. Εάν αυτή η τιμή δεν είναι ένας αριθμός, θα οριστεί σε NaN. Αυτό μπορεί να χρησιμοποιηθεί για να αφαιρέσετε το περιεχόμενο των μεταβλητών από το περιβάλλον.

Κόλπα Συναρτήσεων

.call και .apply

Η μέθοδος .call μιας συνάρτησης χρησιμοποιείται για να εκτελέσει τη συνάρτηση. Το πρώτο όρισμα που αναμένει από προεπιλογή είναι η τιμή του this και εάν δεν δοθεί τίποτα, η τιμή αυτή θα είναι window (εκτός αν χρησιμοποιείται strict mode).

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"])

Συναρτήσεις βέλους

Οι συναρτήσεις βέλους σας επιτρέπουν να δημιουργήσετε συναρτήσεις σε μία γραμμή πιο εύκολα (αν τις κατανοείτε)

// 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;

Έτσι, οι περισσότερες από τις προηγούμενες συναρτήσεις είναι πραγματικά άχρηστες επειδή δεν τις αποθηκεύουμε πουθενά για να τις καλέσουμε. Παράδειγμα δημιουργίας της συνάρτησης plusone:

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

//Arrow
plusone = a => a + 100;

Συνάρτηση bind

Η συνάρτηση bind επιτρέπει τη δημιουργία ενός αντιγράφου μιας συνάρτησης με τροποποιημένο το this αντικείμενο και τις παραμέτρους που δίνονται.

//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')

Σημείωση ότι χρησιμοποιώντας το bind μπορείτε να παραμορφώσετε το αντικείμενο this που θα χρησιμοποιηθεί κατά την κλήση της συνάρτησης.

Διαρροή κώδικα συνάρτησης

Εάν μπορείτε να έχετε πρόσβαση στο αντικείμενο μιας συνάρτησης, μπορείτε να πάρετε τον κώδικα αυτής της συνάρτησης.

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

Σε περιπτώσεις όπου η συνάρτηση δεν έχει κανένα όνομα, μπορείτε ακόμα να εκτυπώσετε τον κώδικα της συνάρτησης από μέσα:

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

Ορισμένοι τυχαίοι τρόποι για να εξαγάγετε τον κώδικα μιας συνάρτησης (ακόμα και σχόλια) από μια άλλη συνάρτηση:

(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 */ })()

Απόδραση από το Sandbox - Ανάκτηση του αντικειμένου παραθύρου

Το αντικείμενο παραθύρου επιτρέπει την πρόσβαση σε παγκοσμίως καθορισμένες συναρτήσεις όπως η alert ή η eval.

// 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)>

Διακοπή στην πρόσβαση στην τιμή

// 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;
}
// 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')

Αυτόματη πρόσβαση στον περιηγητή για να ελέγξετε τα δεδομένα εισροής

Μπορείτε να χρησιμοποιήσετε τον περιηγητή για να ελέγξετε αυτόματα τα δεδομένα εισροής που εισάγονται σε μια ιστοσελίδα. Αυτό μπορεί να γίνει με τη χρήση JavaScript και την εκτέλεση κώδικα αυτόματα στον περιηγητή.

Για να το κάνετε αυτό, μπορείτε να χρησιμοποιήσετε τη μέθοδο eval() της JavaScript για να εκτελέσετε κώδικα από μια συγκεκριμένη είσοδο. Για παράδειγμα, μπορείτε να δημιουργήσετε ένα αόρατο iframe στη σελίδα και να χρησιμοποιήσετε τη μέθοδο eval() για να εκτελέσετε κώδικα JavaScript μέσα σε αυτό το iframe.

Με αυτόν τον τρόπο, μπορείτε να εκτελέσετε οποιονδήποτε κώδικα JavaScript θέλετε στον περιηγητή, ελέγχοντας έτσι την αντίδραση της ιστοσελίδας σε διάφορες εισόδους.

Πρέπει να λάβετε υπόψη ότι η χρήση της μεθόδου eval() μπορεί να είναι επικίνδυνη, καθώς μπορεί να εκτελέσει οποιονδήποτε κώδικα παρέχετε, συμπεριλαμβανομένου κακόβουλου κώδικα. Πρέπει να είστε προσεκτικοί και να χρησιμοποιείτε αυτήν τη μέθοδο με προσοχή.

//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();
})();
Μάθετε το χάκινγκ του AWS από το μηδέν μέχρι τον ήρωα με το htARTE (HackTricks AWS Red Team Expert)!

Last updated