Het artikel beschrijft een methode om willekeurige JavaScript-functies aan te roepen zonder gebruik te maken van haakjes. De kern van deze techniek is het overschrijven van de prepareStackTrace-functie van het Error-object, die normaal gesproken stack traces formateert maar hier wordt ingezet om functies te genereren.
Om de payload succesvol te laten werken, moet de output van Array.prototype.toString() worden beheerst. Dit kan door de functie direct te overschrijven of door middel van prototype pollution van de Object.prototype.message-variabele. De uiteindelijke activatie van de functie gebeurt via de valueOf-truc of string-concatenatie, waardoor de functie wordt uitgevoerd als een primitieve waarde.
Het artikel bevat een concrete code-snippet die deze volledige keten van manipulaties demonstreert voor gebruik in een browserconsole.
Nog een manier om functies aan te roepen zonder haakjes
Deze payload werkt door de prepareStackTrace-functie van het Error-object te overschrijven om willekeurige functies te genereren. Deze functie wordt gewoonlijk gebruikt om stack traces te formatteren en wordt aangeroepen wanneer het stack-attribuut van een fout wordt geraadpleegd.
De parameters van deze functie zijn de fout en "een gestructureerde weergave van de stack", wat simpelweg een array van codeposities is. Deze functie heeft dezelfde functiesignatuur als de Function-constructor, die wordt gebruikt om JavaScript-functies te genereren, mits het tweede argument geldige JavaScript-code is.
Als we proberen de functie aan te roepen die met deze methode is gegenereerd, krijgen we een syntaxisatiefout. Dit is te verwachten, aangezien een stack trace geen geldige JavaScript-code is, maar een array van codeposities.
Om de payload te laten werken, moeten we de output van de Array.prototype.toString()-functie zodanig beheersen dat deze onze gewenste JavaScript-payload teruggeeft. Dit kan op twee manieren:
- Ten eerste kunnen we deze simpelweg overschrijven met een constante functie die de payload teruggeeft.
- Of we kunnen prototype pollution gebruiken om onze payload in een andere functie te smokkelen en vervolgens het Array-prototype te overschrijven. Ik ontdekte dat we in het
Error-domein kunnen blijven en de toString-functie daarvan kunnen gebruiken, die gemanipuleerd kan worden door de Object.prototype.message-variabele te vervuilen. Ik ben er zeker van dat er meer manieren zijn om dit te bereiken.
Wanneer we nu alles combineren — de functiegeneratie via de prepareStackTrace-functie en de manier om arrays om te zetten in willekeurige strings — kunnen we willekeurige JavaScript-functies genereren.
Het laatste wat we moeten doen is onze nieuwe functie aanroepen. Gelukkig zijn daar veel manieren voor; ik heb gekozen voor de valueOf-truc. Dit werkt door de standaard valueOf-functie van ons object te overschrijven en deze vervolgens als een primitieve waarde aan te roepen. Als alternatief kunnen we toString gebruiken en het object vervolgens aan een string koppelen (concatenatie).
De uiteindelijke payload is als volgt. Voel je vrij om dit uit te proberen in de browserconsole:
Object.prototype.message='alert\x281337\x29';Array.prototype.toString=Error.prototype.toString;Error.prepareStackTrace = Function;const x = new Error;x.valueOf=x.stack;+x;
Nog een manier om functies aan te roepen zonder haakjes
Deze payload werkt door de prepareStackTrace-functie van het Error-object te overschrijven om willekeurige functies te genereren. Deze functie wordt gewoonlijk gebruikt om stack traces te formatteren en wordt aangeroepen wanneer het stack-attribuut van een fout wordt geraadpleegd.
De parameters van deze functie zijn de fout en "een gestructureerde weergave van de stack", wat simpelweg een array van codeposities is. Deze functie heeft dezelfde functiesignatuur als de Function-constructor, die wordt gebruikt om JavaScript-functies te genereren, mits het tweede argument geldige JavaScript-code is.
Als we proberen de functie aan te roepen die met deze methode is gegenereerd, krijgen we een syntaxisatiefout. Dit is te verwachten, aangezien een stack trace geen geldige JavaScript-code is, maar een array van codeposities.
Om de payload te laten werken, moeten we de output van de Array.prototype.toString()-functie zodanig beheersen dat deze onze gewenste JavaScript-payload teruggeeft. Dit kan op twee manieren:
- Ten eerste kunnen we deze simpelweg overschrijven met een constante functie die de payload teruggeeft.
- Of we kunnen prototype pollution gebruiken om onze payload in een andere functie te smokkelen en vervolgens het Array-prototype te overschrijven. Ik ontdekte dat we in het
Error-domein kunnen blijven en de toString-functie daarvan kunnen gebruiken, die gemanipuleerd kan worden door de Object.prototype.message-variabele te vervuilen. Ik ben er zeker van dat er meer manieren zijn om dit te bereiken.
Wanneer we nu alles combineren — de functiegeneratie via de prepareStackTrace-functie en de manier om arrays om te zetten in willekeurige strings — kunnen we willekeurige JavaScript-functies genereren.
Het laatste wat we moeten doen is onze nieuwe functie aanroepen. Gelukkig zijn daar veel manieren voor; ik heb gekozen voor de valueOf-truc. Dit werkt door de standaard valueOf-functie van ons object te overschrijven en deze vervolgens als een primitieve waarde aan te roepen. Als alternatief kunnen we toString gebruiken en het object vervolgens aan een string koppelen (concatenatie).
De uiteindelijke payload is als volgt. Voel je vrij om dit uit te proberen in de browserconsole:
Object.prototype.message='alert\x281337\x29';Array.prototype.toString=Error.prototype.toString;Error.prepareStackTrace = Function;const x = new Error;x.valueOf=x.stack;+x;