From Badge Names to Broken Logic: Exploiting Web Application Flaws for Fun and Profit + Video

Listen to this Post

Featured Image

Introduction:

Web application security is a cat-and-mouse game where attackers leverage both technical misconfigurations and logical flaws to bypass controls. Two critical vulnerability classes—special character injection leading to state confusion, and race conditions enabling limit bypasses—continue to plague modern applications. This article dissects two real-world findings from a private bug bounty program, providing technical deep dives into their exploitation and mitigation.

Learning Objectives:

  • Understand how special characters can disrupt backend CORS and request handling to cause persistent UI injections.
  • Learn to identify and exploit race conditions for bypassing rate limits and business logic constraints.
  • Master the use of Burp Suite tools (Repeater, Intruder) for parallel request testing.
  • Implement server-side mitigations against state confusion and concurrency issues.

You Should Know:

1. Persistent Undismissable Notification Injection via Special Characters

The core issue arises when user-controllable input (e.g., a badge name) is not properly sanitized before being processed by the backend. In this case, injecting characters like `<` or `?` caused the backend to misinterpret the request. Specifically, before sending the required `PATCH` request to accept the badge, the application pre-flighted the request with an `OPTIONS` method. The malformed input likely caused the `OPTIONS` request to fail due to improper input validation or routing, leaving the application in a state where the notification could not be dismissed. Step‑by‑step guide explaining what this does and how to use it.

Step 1: Identify Input Points

Locate any field where user input is reflected in a notification or UI element (e.g., profile names, badge titles, group names).

Step 2: Inject Test Payloads

Using Burp Suite or a similar proxy, intercept the request that submits this data. Modify the parameter to include special characters: `%3C` (<), `%3E` (>), `%3F` (?), or `%22` ("). URL-encode them if necessary.

Example Request:

POST /api/update-badge HTTP/1.1
Host: target.com
...
{"badge_name": "Hackers<"}

Step 3: Observe Backend Behavior

After submission, monitor the subsequent requests. Look for an unexpected `OPTIONS` preflight request before the intended `PATCH` or POST. Check if this `OPTIONS` request returns an error (4xx or 5xx).

Step 4: Verify Persistence

If the notification becomes undismissable, attempt to interact with it. Check the browser’s developer console (F12) for JavaScript errors or failed API calls. The application may be stuck because it expects the `PATCH` to succeed, but the failed `OPTIONS` prevents it from proceeding.

2. Mitigating Notification Injection Attacks

To prevent such injection, developers must implement robust input validation and output encoding, and ensure CORS preflight is handled correctly regardless of input.

Step‑by‑step guide explaining what this does and how to use it.

Server-Side Mitigation (Linux/Backend Focus)

Step 1: Implement Strict Input Validation

Use allow-lists for input. For example, in a Node.js/Express app, validate badge names:

const validateBadgeName = (req, res, next) => {
const badgeName = req.body.badge_name;
// Allow only alphanumeric and spaces
const regex = /^[a-zA-Z0-9 ]+$/;
if (!regex.test(badgeName)) {
return res.status(400).json({ error: 'Invalid characters in badge name' });
}
next();
};
app.post('/api/update-badge', validateBadgeName, (req, res) => { ... });

Step 2: Proper Output Encoding

When displaying the badge name in HTML or JavaScript, ensure context-aware encoding. Use templating engines that auto-escape, or manually encode using libraries like `he` in JavaScript.

Step 3: Secure CORS Configuration

Ensure the server handles `OPTIONS` requests generically and does not rely on user input to determine CORS policy. A basic, secure CORS handler:

app.options('/api/', (req, res) => {
res.header('Access-Control-Allow-Origin', 'https://trusted-frontend.com');
res.header('Access-Control-Allow-Methods', 'GET, POST, PATCH, OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type');
res.sendStatus(204);
});

3. Understanding Race Conditions for Limit Bypass

A race condition occurs when a system’s behavior depends on the sequence or timing of uncontrollable events. In web apps, this often involves sending multiple requests concurrently to exploit a window of inconsistency before a limit or state is updated. For example, if a coupon can only be used once, sending 10 parallel requests might allow it to be applied 10 times if the check-and-update operation is not atomic.

Step‑by‑step guide explaining what this does and how to use it.

Step 1: Identify a Limit

Find a function with a clear limit: coupon usage, vote casting, wallet withdrawal, or like/unlike actions. The target in the post was likely a limit on accepting or interacting with badges.

Step 2: Prepare the Request Group

In Burp Suite Repeater, create multiple tabs, each containing the exact request that performs the limited action (e.g., `POST /api/use-coupon` with the same coupon code). Ensure all requests are identical.

Step 3: Send Requests in Parallel (Turbo Intruder)

Burp’s standard Intruder sends requests sequentially. For true parallelism, use the Turbo Intruder extension (Python-based).

Example Turbo Intruder Script:

def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=10,
requestsPerConnection=100,
pipeline=False
)
for i in range(20):  Send 20 requests
engine.queue(target.req)
def handleResponse(req, interesting):
table.add(req)

Execute this script to fire the requests concurrently.

Step 4: Analyze the Results

Check the server responses. For a successful race condition, you might see multiple `200 OK` responses even though only one should have been allowed. For a vote, you might see the count increase by more than one.

  1. Exploiting Race Conditions in the Wild (Limit Bypass)
    In the provided finding, the attacker searched for “any limits” and created a group of requests to send in parallel. This could apply to anything from liking a post multiple times to redeeming a gift card repeatedly.

Step‑by‑step guide explaining what this does and how to use it.

Example Scenario: Bypassing a Like Limit

Imagine an application allows a user to like a post only once.

Normal Request:

POST /api/like-post HTTP/1.1
Host: target.com
Cookie: session=user123
...
{"post_id": 456}

Exploitation Steps:

1. Intercept the like request.

2. Send it to Turbo Intruder.

3. Configure the engine to send 50 requests with concurrentConnections=20.

4. Run the attack.

5. If successful, the post’s like count may increase by 50, indicating a race condition.

Testing with cURL (Linux Command Line):

You can also simulate concurrency with a bash script:

!/bin/bash
for i in {1..20}; do
curl -X POST https://target.com/api/like-post \
-H "Cookie: session=user123" \
-H "Content-Type: application/json" \
-d '{"post_id": 456}' &
done
wait

This forks 20 background processes nearly simultaneously.

5. Mitigating Race Conditions with Atomic Operations

Preventing race conditions requires ensuring that critical sections of code are executed atomically, meaning they cannot be interrupted by another request.

Step‑by‑step guide explaining what this does and how to use it.

Database-Level Mitigation (Using Transactions)

Step 1: Use Database Locks

In SQL, use `SELECT … FOR UPDATE` to lock the row being checked.

BEGIN;
SELECT  FROM coupons WHERE code = 'DISCOUNT10' AND used = FALSE FOR UPDATE;
-- If row exists and is unused
UPDATE coupons SET used = TRUE WHERE code = 'DISCOUNT10';
COMMIT;

This ensures that the second concurrent request will wait for the first to complete.

Step 2: Implement Optimistic Locking

Add a version column to your table. When updating, check the version.

UPDATE coupons SET used = TRUE, version = version + 1
WHERE code = 'DISCOUNT10' AND version = 1;

If the affected rows count is 0, another process already updated it.

Application-Level Mitigation (Redis)

For high-performance systems, use atomic operations in Redis.

import redis
r = redis.Redis()
 Atomically decrement only if the value is >= 1
result = r.eval("""
local current = redis.call('GET', KEYS[bash])
if current and tonumber(current) >= 1 then
return redis.call('DECR', KEYS[bash])
else
return -1
end
""", 1, "coupon:DISCOUNT10")
if result == -1:
print("Coupon already used or invalid")

What Undercode Say:

  • Key Takeaway 1: Input validation is not just about XSS; it can have critical implications on application logic and request handling, as seen with malformed data breaking CORS preflight.
  • Key Takeaway 2: Race conditions are often overlooked in business logic testing. Attackers can exploit them to multiply assets or bypass limits, and they require a shift from sequential testing to parallel request analysis.

Analysis: These two findings highlight a spectrum of web vulnerabilities. The notification injection, while seemingly a simple input issue, underscores how deeply coupled frontend state management is with backend responses. A failed `OPTIONS` request shouldn’t leave the UI in an inconsistent state; graceful error handling is paramount. The race condition is a classic yet persistently found bug, especially in modern, asynchronous applications. It demonstrates that security testing must evolve beyond simple CRUD operations to include concurrency and timing attacks. Developers must adopt database-level atomic operations or distributed locks to ensure integrity under load.

Prediction:

As web applications become more complex and reliant on microservices and asynchronous APIs, we will see a rise in logic-based race conditions. The lines between client-side state and server-side truth will blur further, making injection-based state corruption a more prevalent attack vector. Automated scanners will struggle to find these, making manual bug bounty hunters invaluable for the foreseeable future.

▶️ Related Video (80% Match):

🎯Let’s Practice For Free:

IT/Security Reporter URL:

Reported By: 0xsila Hack – Hackers Feeds
Extra Hub: Undercode MoN
Basic Verification: Pass ✅

🔐JOIN OUR CYBER WORLD [ CVE News • HackMonitor • UndercodeNews ]

💬 Whatsapp | 💬 Telegram

📢 Follow UndercodeTesting & Stay Tuned:

𝕏 formerly Twitter 🐦 | @ Threads | 🔗 Linkedin | 🦋BlueSky