DEV Community

MR storm
MR storm

Posted on

Web Testing Is Boring And That's The Whole Problem

I've been poking at web apps for a while now, and I need to say something that'll probably annoy people who make money off bug bounties.

Most of it is the same five bugs.

Not similar bugs. Not "bugs in the same family." The same bugs. Same logic, same mistakes, same missing checks, copy-pasted across a thousand different products by a thousand different teams who all think their situation is unique.

The reason this matters is that the industry — bug bounties, pentest firms, the whole "become a hacker" content ecosystem — sells web testing as a hunt. A treasure hunt. You against the codebase, finding what nobody else could find. And that framing is a lie. What you're actually doing, most days, is walking the same hallway and trying every door handle in the same order, and every once in a while one of them is unlocked.

Let me back up, because if you're new you probably don't believe me.

The five bugs
There are five bugs. Everything else is a variation.

Broken access control. This is the big one. It's IDOR, it's privilege escalation, it's "the API endpoint returns another user's data because it trusts the ID you sent." It's an admin endpoint that a regular user can hit because nobody checked. It's a GraphQL query that lets you ask for fields you shouldn't see. It's the #1 bug on OWASP's list for a reason — it's everywhere, it's easy to miss, and it's usually devastating when found.

XSS. Reflected, stored, DOM-based. Pick your flavor. Somewhere, a user-controlled string is being dropped into HTML without escaping. Half the time it's a rich text editor that "sanitizes" input with a regex that doesn't work. The other half it's a template that interpolates raw. Same bug, infinite faces.

SSRF. Somewhere, an app fetches a URL that a user supplied. Maybe it's an image preview. Maybe it's a webhook. Maybe it's a PDF generator. And if you can point it at 169.254.169.254 or localhost or an internal service, you're in.

Auth issues. Weak password reset. Token not invalidated on logout. Session not rotated after privilege change. JWT with alg: none accepted. Email verification bypassed by just... not doing it. Password reset token sent in the URL. Password reset token that doesn't expire. Password reset token that's just the user ID base64'd.

Open redirect and its friends. The next= parameter that will happily send you to evil.com. The OAuth callback that doesn't validate the redirect URI. The "return to" parameter on the login page. All the same shape.

That's it. That's the list. If you've tested web apps for six months, you've seen all five. If you've tested for two years, you've seen all five dozens of times. And if you've tested for five years, you've written the same finding report so many times you could do it in your sleep.

The bit where it stops feeling like hacking
Here's what a real web testing session actually looks like.

You scope the target. You spend an hour mapping the app — endpoints, parameters, auth flows, what talks to what. You run your usual tools. You start at the top of your checklist and work down. Authentication. Session management. Access control. Input handling. Business logic. You poke at every parameter with a "user_id" in the name. You try to hit every endpoint with the wrong role. You check whether the API actually enforces what the UI suggests.

And somewhere along the way, you find one. Almost always, it's one of the five. You write it up. You report it. You get paid, or you get a dupe, or you get told it's "by design."

Then you do it again. And again. And again.

The exotic stuff — the chained exploit that goes from an XSS on a subdomain through a misconfigured CDN into an internal admin panel — is real, but it's maybe 5% of what you'll ever find. The other 95% is "this endpoint doesn't check the org ID, so I can read any customer's invoices by incrementing the number."

I've seen people celebrate finding a novel deserialization bug like they cured cancer. And it's cool. It is cool. But the guy who found the missing authorization check on the billing page did more damage with less effort, and nobody tweets about that.

Why it feels useless
So here's the actual complaint, and I think it's valid.

When every bug is one of five, and every tool finds those five, and every scanner is basically doing the same checks — what exactly are you bringing to the table?

The honest answer is: coverage. You're bringing coverage. You're the person who checked. You're not finding new categories of bugs. You're finding the same categories on a new target, or on a target that's been checked before but where the checks missed something. You're a smoke detector. Not a firefighter, not a chemist who invented a new fire suppressant. A smoke detector.

And for a lot of people, that's not why they got into this. They got into it because they watched Mr. Robot or read a blog about a $100k bounty or saw a DEF CON talk about some insane 0day chain. They wanted the hunt. What they got was a job that feels like QA with extra steps.

I've watched people burn out on this. Not because it's hard — because it's repetitive. Because after you've found your hundredth IDOR, the thrill is gone, and you're left with the realization that the thing you're doing is a maintenance activity, not an intellectual adventure.

The counterargument, which I actually believe
Okay. Everything I just said is true, and I still think the "web testing is useless" take is mostly wrong. Here's why.

Boring bugs are the ones that actually hurt people. Novel 0days are what get the conference talks. Broken access control is what gets the data breach headlines. A missing auth check on an internal API is how 100 million records get dumped on a forum. The "boring" bugs are boring because they're everywhere and they're easy, not because they're unimportant. They're the leading cause of everything.

Finding the same bug class over and over is a skill. Not the fun kind of skill, but a real one. The ability to systematically work through 500 endpoints in a week and find the four that are broken is not something everyone can do. It requires discipline, tooling, and a kind of patience that most security people don't have. It's the difference between a pentester and a CTF player.

Coverage is the entire job. The reason companies pay for pentests and bug bounties isn't to find the next billion-dollar 0day. It's to have someone other than the dev team check the obvious stuff. Because the dev team is tired and moving fast and has a hundred tickets, and the "obvious stuff" is exactly what they skipped. A bored tester doing the same five checks is doing something the dev team should have done but couldn't.

The exotic stuff pays more for a reason. And that reason is that it's rare. The market rewards rarity, and if you want to chase rarity, go ahead. Just know that you're not outperforming the guy doing IDORs by an amount that justifies the hours. You're just playing a different game with a different variance profile.

The real problem isn't web testing. It's the framing.
Here's where I land.

Web testing is fine. It's useful. It prevents real breaches and it pays real bills. What's broken is how it's sold, both to newcomers and to the companies buying it.

Newcomers are sold a fantasy. "Become a hacker." "Find bugs." "Make $50k on HackerOne." The reality is a grind with a long tail, where the top 1% of hunters take most of the payouts, and the median hunter makes less than minimum wage in their first year. The bug classes don't change. The tools don't change much. The whole thing is closer to running a QA pipeline than to being Elliot Alderson.

Companies are sold the same fantasy in reverse. "We'll find all your vulnerabilities." They won't. They'll find the common ones. If the tester is good, they'll find some of the less common ones too. But the exotic bugs — the ones that require understanding a specific business logic or chaining three things — are hit or miss, and often the answer is "miss, because there wasn't budget for the week of investigation that would have found it."

So the honest version of the story is this: web testing is a maintenance function. It's the security equivalent of brushing your teeth. You don't do it because it's exciting. You do it because the alternative is expensive and painful and involves lawyers. And if you approach it with that understanding — as a job, not a hobby, and certainly not as a lifestyle — you'll be a lot happier doing it.

The easy bugs are already gone
Something I want to come back to, because it changes the picture a lot.

The five bugs I listed? Most developers already know about them.

Not "know about them" the way a pentester knows about them. Know about them the way a builder knows where the load-bearing walls are. The frameworks handle it. React escapes by default. Rails has CSRF tokens on by default. Django autoescapes templates. Laravel's ORM parameterizes by default. Spring Security gives you authentication and authorization primitives that are correct if you use them the way they're meant to be used.

The modern dev who builds a new SaaS in 2025 using Next.js and Prisma and Clerk is starting from a baseline where XSS and SQLi and CSRF are largely handled for them unless they actively do something stupid. Which they sometimes do. But not as often as they used to.

Add to that: security training is now standard. SAST tools run in CI. Dependency scanners flag vulnerable packages. Code review catches a lot. Bug bounties start on day one for any company with funding. The bar has been raised. Not to where the bugs don't exist — they absolutely do — but to where the easy bugs have gotten rare on new targets.

That's the part nobody tells you when you're starting out. You read a blog about IDOR and think "wow, every app must be full of these." And then you test a modern app and find... nothing obvious. Because they're using a framework that gives every object an owner check by default, or they're using a pattern that just doesn't have the bug class you're looking for.

So what happens is this: the new, well-funded, well-engineered sites are where every bug hunter is looking, because they pay the most and they're the most visible. And they're also the hardest to find bugs on, because they've been hardened. The overlap between "high payout" and "easy to find bugs" is basically empty.

Which is why, honestly, the better targets are often the opposite.

The graveyard is where the bodies are
I'm talking about sites that haven't been touched in five years.

Small business sites. Local government portals. University systems. Hospital intake forms. Old forums. Trade association membership databases. Anything running on PHP 5 or an old version of Drupal or a custom MVC somebody's cousin wrote in 2013. Sites that were built once, launched, and then nobody ever looked at them again because "if it ain't broke."

These sites are archeological digs. They have every bug.

No CSRF tokens anywhere. Password reset that just emails you the password. Admin panels at /admin with no auth beyond a cookie that's literally admin=1. SQL injection in a search box because the query is built by string concatenation. Stored XSS in the comment system because the output encoding is nl2br($comment) and nothing else. Rate limiting? Never heard of it. Security headers? What are those. HTTPS? Yes, but only on the login page, and only because their host forced it.

I'm not exaggerating. I've seen all of this in the last year. Not in a lab, not in a CTF, on live production sites belonging to real organizations with real users.

The reasons these places still have these bugs are boring. They don't have a dev team. They have one guy who "does the website" along with his actual job. They don't have a security budget. They don't have a bug bounty program. They don't read Hacker News. They upgraded to PHP 7 in 2019 and thought that was the big modernization project for the decade. Nobody has ever reported anything to them because nobody has ever looked.

And here's the thing — nobody is looking because nobody gets paid to look.

The catch
That's the trap. The bugs are there. The bugs are easy. But:

Old sites don't have bug bounty programs, because they don't know what that is.

Old sites often don't have a security contact, because they don't have a security team.

Old sites, when you report a critical SQLi to them, will often respond with "who are you, why are you hacking us, we're calling the police" because they've never received a vulnerability report before and don't know how to handle one.

Old sites often won't pay. Ever. Not because they're malicious, but because the person reading your email doesn't know there's a market rate for this and thinks you're trying to extort them.

So the math is: the bugs are 100x easier to find and 100x harder to get paid for. Which is why the bounty hunters don't go there, and why the bugs stay unpatched for another five years, and why the whole thing is a self-reinforcing cycle where nobody wins except the people who eventually break in for real.

What this means for you
If you're doing this for money — bug bounties, the standard model — you're competing on the hardest targets, against the sharpest people, for the same bugs that everyone else is trying to find. That's a bad game to be in as a beginner.

If you're doing this because you want to actually find bugs — because the puzzle is interesting, because you want to sharpen your skills, because you want to build a reputation that isn't just "I found a low-hanging XSS on a program that pays out $50" — then the old, forgotten, unmaintained corners of the internet are where you want to be.

Not for the payout. For the practice. For the CVEs. For the writeups. For the experience of finding a bug that has been sitting there for eight years waiting for someone to notice it. That's the part of this job that still feels like what you imagined when you got into it.

And every once in a while, you find an old site that does have a security team — maybe they just launched a bounty, maybe they're a mid-size company that's finally getting serious — and you find the bug that would have been trivial for anyone to find five years ago but that nobody looked for because it was "just a small site." That payout lands, and it lands hard, because you were the only one looking.

The lesson, if there is one, is this: the crowd goes where the money is. The money goes where the bugs are hard. The bugs are easy where the crowd doesn't go. That's the whole map. If you want to find easy bugs, stop following the crowd.

But also — and this is the part that'll get me yelled at by the bounty bros — the reason those old sites have easy bugs is that nobody's paying anyone to find them. And the reason nobody's paying is that the people who own those sites don't know they need it. Which is a system-level failure, not a personal one. You can exploit the gap, or you can try to close it, or you can just note that it exists and move on. But it's worth knowing it's there.

If you actually want to do this
Then embrace the boredom.

Learn the five bugs cold. Not the OWASP descriptions — the actual patterns, in the actual code, in actual products. Build a checklist and refine it. Get fast at mapping an app. Get good at writing reports that developers will actually read instead of dismissing. Understand the business logic of each target, because the bug classes are the same but the impact of each bug is different per app, and impact is what gets paid.

Then go do it. Over and over. On targets nobody's talking about, in languages nobody's excited about, against companies that aren't on the front page of TechCrunch. That's where the money is. That's where the bugs that actually matter live.

And accept that the day you find a really novel bug — if you ever do — it'll feel great for about a week, and then you'll be back to checking whether ?user_id= lets you read someone else's data. Because that's what the job is. The novel bugs are a side effect of doing the boring work well, not the point of it.

The interesting bugs aren't extinct. They've just moved to where nobody's looking.

Sorry to ruin the fantasy. But it's better to know going in.

Top comments (0)