24 KiB
Verskillende JS-truuks & relevante inligting
Leer AWS-hacking van nul tot held met htARTE (HackTricks AWS Red Team Expert)!
- Werk jy in 'n cybersecurity-maatskappy? Wil jy jou maatskappy adverteer in HackTricks? Of wil jy toegang hê tot die nuutste weergawe van die PEASS of HackTricks aflaai in PDF-formaat? Kyk na die SUBSCRIPTION PLANS!
- Ontdek The PEASS Family, ons versameling eksklusiewe NFTs
- Kry die amptelike PEASS & HackTricks swag
- Sluit aan by die 💬 Discord-groep of die telegram-groep of volg my op Twitter 🐦@carlospolopm.
- Deel jou hacking-truuks deur PR's in te dien by die hacktricks-repo en hacktricks-cloud-repo.
Javascript Fuzzing
Geldige JS Kommentaar Karakters
//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]
Geldige JS Nuwe Lyn Karakters
In JavaScript kan jy verskillende karakters gebruik om 'n nuwe lyn te skep binne 'n string. Hier is 'n lys van geldige karakters wat jy kan gebruik:
\n
: Skep 'n nuwe lyn.\r
: Skep 'n karretjie-terugkeer.\u2028
: Skep 'n lynafbreking.\u2029
: Skep 'n paragraafafbreking.
Hier is 'n voorbeeld van hoe jy hierdie karakters kan gebruik:
var string = "Hierdie is 'n voorbeeld\nvan 'n nuwe lyn";
Dit sal 'n nuwe lyn skep na die woord "voorbeeld".
//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
Geldige JS-spasies in funksie-oproep
In sommige situasies kan die gebruik van geldige JS-spasies in 'n funksie-oproep nuttig wees om XSS-aanvalle te omseil. Hier is 'n paar voorbeelde van hoe dit gedoen kan word:
- Gebruik van new line karakter: Jy kan die new line karakter (
\n
) gebruik om 'n funksie-oproep oor meerdere lyne te verdeel. Byvoorbeeld:
aler\nt('XSS');
- Gebruik van tab karakter: Die tab karakter (
\t
) kan ook gebruik word om 'n funksie-oproep oor meerdere spasies te verdeel. Byvoorbeeld:
aler\t('XSS');
- Gebruik van backslash karakter: Die backslash karakter (
\
) kan gebruik word om 'n funksie-oproep oor meerdere spasies te verdeel. Byvoorbeeld:
aler\ t('XSS');
Dit is belangrik om te onthou dat hierdie tegnieke slegs werk in spesifieke omstandighede en nie altyd betroubaar is nie. Dit is dus belangrik om ander XSS-verdedigingsmaatreëls te implementeer om jou webtoepassing te beskerm.
// 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
Geldige karakters om Strings te genereer
// 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
Hierdie tegniek sal nie baie nuttig wees vir XSS nie, maar dit kan nuttig wees om WAF-beskerming te omseil. Hierdie Python-kode ontvang as inset 2 byte en soek 'n surrogate-paar wat die eerste byte as die laaste bytes van die Hoë surrogate-paar het en die laaste byte as die laaste byte van die lae surrogate-paar.
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"))
Meer inligting:
- https://github.com/dreadlocked/ctf-writeups/blob/master/nn8ed/README.md
- https://mathiasbynens.be/notes/javascript-unicode https://mathiasbynens.be/notes/javascript-encoding
javascript{}:
Protokol 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 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="javascript:alert(1337)">Test</a>
URL Fuzzing
URL Fuzzing is 'n tegniek wat gebruik word om potensiële kwesbaarhede in 'n webtoepassing te identifiseer deur verskillende variante van 'n URL te probeer. Dit behels die invoeging van verskillende waardes en parameters in die URL om te sien of dit lei tot enige onverwagte gedrag of fouttoestande. Hierdie tegniek kan gebruik word om potensiële XSS-kwesbaarhede te ontdek deur te kyk of die webtoepassing korrek omgaan met ongeldige of skadelike invoer in die URL.
// 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 is a technique used to discover vulnerabilities in web applications by injecting malicious or unexpected input into HTML elements. This technique involves sending a large number of test cases to the target application, with the goal of triggering unexpected behavior or uncovering security flaws.
During HTML Fuzzing, various types of input can be injected into HTML elements, such as:
- Script tags: Injecting script tags can help identify Cross-Site Scripting (XSS) vulnerabilities. By injecting malicious scripts, an attacker can execute arbitrary code in the victim's browser.
- HTML tags: Injecting HTML tags can help identify HTML injection vulnerabilities. This can lead to the manipulation of the website's structure and content.
- Event attributes: Injecting event attributes can help identify DOM-based XSS vulnerabilities. By injecting malicious event handlers, an attacker can execute code within the context of the victim's browser.
- URL parameters: Injecting malicious input into URL parameters can help identify vulnerabilities such as Server-Side Request Forgery (SSRF) or Remote File Inclusion (RFI).
To perform HTML Fuzzing, you can use automated tools or write custom scripts to generate and send a large number of test cases to the target application. The goal is to observe how the application handles different types of input and identify any unexpected behavior or vulnerabilities.
It is important to note that HTML Fuzzing should only be performed on applications that you have permission to test. Unauthorized testing can lead to legal consequences. Always ensure you have proper authorization before conducting any security testing.
// 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
Ontleding van eienskappe
Die instrument Hackability-inspekteur van Portswigger help om die eienskappe van 'n JavaScript-objek te ontleed. Kyk: https://portswigger-labs.net/hackability/inspector/?input=x.contentWindow&html=%3Ciframe%20src=//subdomain1.portswigger-labs.net%20id=x%3E
.map js-lêers
- Truuk om .map js-lêers af te laai: https://medium.com/@bitthebyte/javascript-for-bug-bounty-hunters-part-2-f82164917e7
- Jy kan hierdie instrument gebruik om hierdie lêers te ontleed https://github.com/paazmaya/shuji
"--" Toekenning
Die dekrement-operator --
is ook 'n toekenning. Hierdie operator neem 'n waarde en verminder dit dan met een. As daardie waarde nie 'n nommer is nie, sal dit op NaN
gestel word. Dit kan gebruik word om die inhoud van veranderlikes uit die omgewing te verwyder.
Funksie Truuks
.call en .apply
Die .call
-metode van 'n funksie word gebruik om die funksie uit te voer.
Die eerste argument wat dit standaard verwag, is die waarde van this
en as niks voorsien word nie, sal window
daardie waarde wees (tensy strict mode
gebruik word).
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"])
Pylpuntfunksies
Pylpuntfunksies maak dit makliker om funksies in 'n enkele lyn te genereer (as jy hulle verstaan)
// 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;
So, die meeste van die vorige funksies is eintlik nutteloos omdat ons hulle nie enige plek stoor om hulle te bewaar en aan te roep nie. Byvoorbeeld, die skep van die plusone
funksie:
// Traductional
function plusone (a){ return a + 1; }
//Arrow
plusone = a => a + 100;
Bind-funksie
Die bind-funksie maak dit moontlik om 'n kopie van 'n funksie te skep wat die this
objek en die parameters wat gegee word, wysig.
//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')
{% hint style="info" %}
Let daarop dat jy met behulp van bind
die this
objek kan manipuleer wat gebruik sal word wanneer die funksie geroep word.
{% endhint %}
Funksie kode lek
As jy toegang het tot die objek van 'n funksie, kan jy die kode van daardie funksie kry.
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
In gevalle waar die funksie geen naam het nie, kan jy steeds die funksie kode binne die funksie druk:
(function (){ return arguments.callee.toString(); })()
(function (){ return arguments[0]; })("arg0")
Sommige willekeurige maniere om die kode van 'n funksie (selfs kommentaar) uit 'n ander funksie te onttrek:
(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 */ })()
Sandbakkie-ontsnapping - Herstel van vensterobjek
Die vensterobjek maak dit moontlik om globaal gedefinieerde funksies soos alert of eval te bereik.
{% code overflow="wrap" %}
// 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)>
{% endcode %}
Breekpunt op toegang tot waarde
Object.defineProperty(window, 'value', {
get: function() {
debugger;
return this._value;
},
set: function(val) {
this._value = val;
}
});
Met deze code kun je een breekpunt instellen wanneer er toegang is tot een bepaalde waarde in de browser. Het Object.defineProperty
-functie wordt gebruikt om een nieuw eigenschap te definiëren op het window
-object genaamd 'value'. Deze eigenschap heeft een getter en een setter functie.
De getter functie wordt uitgevoerd wanneer er toegang is tot de waarde van 'value'. In dit geval wordt er een debugger
statement toegevoegd, wat ervoor zorgt dat de browser stopt bij dit punt en je de mogelijkheid geeft om de code te inspecteren en te debuggen.
De setter functie wordt uitgevoerd wanneer er een nieuwe waarde wordt toegewezen aan 'value'. In dit geval wordt de nieuwe waarde opgeslagen in een interne variabele genaamd _value
.
Dit kan handig zijn bij het opsporen van XSS-kwetsbaarheden, omdat het je in staat stelt om te zien wanneer een bepaalde waarde wordt gebruikt in de code en om te controleren of er mogelijk onveilige invoer wordt gebruikt.
// 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')
Outomatiese Blaaiertoegang om toetslading te toets
Sometimes, when testing for Cross-Site Scripting (XSS) vulnerabilities, it can be useful to have automatic browser access to test payloads. This allows you to quickly and efficiently test your payloads without manually interacting with the browser.
Soms kan dit nuttig wees om outomatiese blaaiertoegang te hê om toetslading te toets wanneer jy op soek is na Cross-Site Scripting (XSS) kwesbaarhede. Dit stel jou in staat om vinnig en doeltreffend jou lading te toets sonder om handmatig met die blaaiertoepassing te werk.
There are several tools and techniques that can help you achieve automatic browser access. Here are a few examples:
Daar is verskeie hulpmiddels en tegnieke wat jou kan help om outomatiese blaaiertoegang te verkry. Hier is 'n paar voorbeelde:
Browser Extensions
Blaaiertoepassing-uitbreidings
Browser extensions like XSStrike and XSS Hunter can automate the process of testing XSS payloads. These extensions allow you to easily inject and test payloads directly from your browser.
Blaaiertoepassing-uitbreidings soos XSStrike en XSS Hunter kan die proses van toetsing van XSS-lading outomatiseer. Hierdie uitbreidings maak dit maklik om lading direk vanuit jou blaaiertoepassing in te spuit en te toets.
Headless Browsers
Koplose Blaaiers
Headless browsers like Puppeteer and Selenium can be used to automate browser interactions. These tools allow you to programmatically control a browser and execute XSS payloads without any user intervention.
Koplose blaaiers soos Puppeteer en Selenium kan gebruik word om blaaiertoepassing-interaksies te outomatiseer. Hierdie hulpmiddels stel jou in staat om 'n blaaiertoepassing outomaties te beheer en XSS-lading uit te voer sonder enige gebruikersintervensie.
Remote Browser Services
Afgeleë Blaaiertoepassing Dienste
Remote browser services like BrowserStack and Sauce Labs provide access to a wide range of browsers and devices for testing purposes. These services allow you to run your XSS payloads on different browsers and platforms without the need for local installations.
Afgeleë blaaiertoepassing dienste soos BrowserStack en Sauce Labs bied toegang tot 'n wye verskeidenheid blaaiertoepassings en toestelle vir toetsdoeleindes. Hierdie dienste stel jou in staat om jou XSS-lading op verskillende blaaiertoepassings en platforms uit te voer sonder die behoefte aan plaaslike installasies.
By utilizing these tools and services, you can streamline your XSS testing process and save time by automating browser access to test payloads.
Deur van hierdie hulpmiddels en dienste gebruik te maak, kan jy jou XSS-toetsproses stroomlyn en tyd bespaar deur blaaiertoegang tot toetslading outomaties te maak.
//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×tamp=1624556811000`);
//Go to the page
await page.goto(
`https://challenge-0621.intigriti.io/passgen.php?passwordLength=${input}&allowNumbers=true&allowSymbols=true×tamp=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();
})();
Leer AWS-hacking van nul tot held met htARTE (HackTricks AWS Red Team Expert)!
- Werk jy in 'n cybersecurity-maatskappy? Wil jy jou maatskappy adverteer in HackTricks? Of wil jy toegang hê tot die nuutste weergawe van die PEASS of laai HackTricks in PDF af? Kyk na die SUBSCRIPTION PLANS!
- Ontdek The PEASS Family, ons versameling eksklusiewe NFTs
- Kry die amptelike PEASS & HackTricks swag
- Sluit aan by die 💬 Discord-groep of die telegram-groep of volg my op Twitter 🐦@carlospolopm.
- Deel jou hacking-truuks deur PR's in te dien by die hacktricks-repo en hacktricks-cloud-repo.