بِسْمِ اللَّهِ الرَّحْمَنِ الرَّحِيمِ

Introduction

Hello guys 👋

I want to share my experience discovering my first serious logic bug, which I consider one of the most impactful vulnerabilities I've found so far.

This discovery actually started from a simple daily habit of mine: I usually open Hacktivity, apply some filters, and read exclusive reports while enjoying my favorite cup of coffee ☕. Lately, I've been focusing more on High to Critical severity reports.

One day, I came across a logic vulnerability report that immediately caught my attention. From the first read, I kept asking myself:

Where exactly is the impact?

I even sent it to ChatGPT for clarification, and found it explaining another scenario to me !!😂 That's when I realized there was something deeper going on.

The report ID was: 3303136

When I checked the company that rejected this report, the controversy around the rejection was very obvious.

None

Without diving too much into why the report was rejected — or how strong it actually was — a scenario suddenly clicked in my head.

I was almost certain that I could reproduce this issue in a large external program that I had worked on before.

Unfortunately, that external program was a bad experience:

  • Toxic environment
  • No real technical discussion
  • No room for learning or growth

Even though the program looked professional on paper and had policies similar to well-known companies, the reality was very different. I honestly wouldn't recommend it to anyone.

For the sake of this write-up, let's call the target:

target.com

Target Overview

The platform specializes in building documentation for websites. It exposes several features that make it a good candidate for testing:

  • IDOR
  • Access Control
  • Business Logic flaws

Available Roles

We'll focus on two main roles:

  1. Owner
  2. Admin

Setup & Initial Observation

  1. I registered on the platform and created a new project named "hwedy"
  2. Owner account: hwedy00
  3. From the invitation feature, I sent an Admin invite to: "hwedy01"

When hwedy01 accepted the invite, the platform redirected directly to the registration page.

First Critical Red Flag 🚩

While accepting the admin invitation, I noticed something alarming:

  • No email verification was required
  • No additional authentication or confirmation step existed

This immediately revealed a serious design flaw in the invitation flow.

At this point, it became clear that the invitation link itself was treated as full authorization, not just a request. Meaning:

Anyone who obtains a valid invitation link can gain access to the project directly — without proving ownership of the email or identity.

This is especially dangerous because:

  • The invitation alone is sufficient to grant project access
  • There is no secondary validation (email verification, auth check, or confirmation)
  • The security of the entire access control model relies solely on the secrecy of the invite link

In other words, the invitation link acts as a permanent access key, not a temporary or conditional authorization mechanism.

Privilege Escalation Flow

After hwedy01 successfully joined as an Admin:

  1. Using hwedy01, I sent another Admin invite to: "hwedy02"
  2. Then, using the Owner account hwedy00, I removed Admin hwedy01 from the project
  3. I confirmed that hwedy01 no longer had access
  4. Finally, I accepted the pending invitation sent to hwedy02

💥 Result: hwedy02 gained full Admin access, even though the inviter (hwedy01) had already been removed.

Vulnerable Scenario (Simplified)

  1. Owner invites Admin A
  2. Admin A accepts and gains access
  3. Admin A sends an Admin invite to B
  4. Owner removes Admin A
  5. Admin B accepts the invite and gains Admin access

Root Cause Analysis

After analyzing the invitation logic deeply, I found a critical flaw in how invitation tokens are handled.

Example invitation token:

ad97e38d0b96e0d69f14a1f5f99f3804a976ded0f3793a89

Token Characteristics

  • Behaves like a random hash with no context
  • No embedded timestamp
  • No expiration data
  • Never invalidated automatically

➡️ The token is valid forever.

API Confirmation

When querying the API endpoint responsible for invitations, the response was:

{
  "data": [
    {
      "id": "6938095d80e70426a4305f8c",
      "email": "hwedy02+7@gmail.com",
      "status": "pending",
      "user_type": "admin",
      "permissions": []
    },
    {
      "id": "6938f1adc5d93252ec18489b",
      "email": "hwedy02+8@gmail.com",
      "status": "pending",
      "user_type": "admin",
      "permissions": []
    },
    {
      "id": "6938f43e6843706b232fb8a7",
      "email": "hwedy02+10@gmail.com",
      "status": "pending",
      "user_type": "admin",
      "permissions": []
    }
  ]
}

This confirmed:

  • No expiration for pending invitations
  • Invitations remain valid indefinitely

Additional Finding — Missing Rate Limiting

The invitation endpoint has no rate limiting. To confirm this, I was able to send over 200 admin invitations to my own email without any restriction or warning.

None

This allows an attacker to generate an unlimited number of valid admin invites in a very short time.

Real Attack Scenario (High-Impact Business Logic Exploit)

  1. Admin(A) joins the project
  2. Before removal, Admin A sends many invites to their own emails (or attacker-controlled emails)
  3. Owner removes Admin A
  4. All malicious invites remain valid
  5. Attacker accepts any invite days/weeks later
  6. Attacker becomes Admin again, without the owner's knowledge
  7. Attacker can now:
  • Modify/delete project documentation
  • Leak internal pages
  • Add new admins
  • Fully take over the project
  • Permanently maintain access (persistence) This completely breaks authorization logic and defeats the owner's ability to remove a malicious admin.

Closing Notes

This vulnerability was not discovered by chance.

It started with a logic bug report that was marked as duplicate, then later reclassified as "not valid" after escalation to the company's support team. The rejection itself wasn't what mattered — what mattered was the idea behind the report.

None
Duplicate
None
After Not-Valid really!!!

Reproducing the same logic flaw in a different environment confirmed an important lesson:

External programs are often one of the biggest traps in bug bounty.

They usually:

  • Look mature and well-documented
  • Claim clear security policies
  • Appear similar to large, trusted platforms

But in practice, many of them:

  • Lack proper security ownership
  • Dismiss valid logic flaws
  • Provide no real technical discussion or feedback
  • Turn learning and reporting into wasted effort

In this case, a rejected report was not a dead end — it was the starting point that led to a real, high-impact vulnerability.

Sometimes, the value of a report is not in its acceptance status, but in the mental model it builds — and how you apply that model elsewhere.

A rejected report taught me more than an accepted one ever did.