My blog was hacked and Claude and I just fixed it

jlengrand1 pts0 comments

My blog was hacked and Claude and I just fixed it

-->

Sign in<br>Subscribe

How it started<br>It all started from a message on Linkedin yesterday "Hey, you've been hacked I'm getting fake captchas on your blog".<br>Obviously I checked and saw nothing wrong. But I also remembered about someone telling me something very similar a couple weeks back on Mastodon. So I checked from all of the devices I could think of in the house and couldn't reproduce either, even with a VPN from the location of the user who reported the issue.<br>At this point, I dismissed it as something coming from the user side. Maybe they had an infected browser extension running. Just as a safe check, I decided to send a call for help on social media to ask people to check the blog and let me know if they saw anything weird. No new reports, either....<br>Starting the investigation<br>After a couple hours I still had an uneasy feeling, so I started reading online and found the exact issue the users were reporting. I fired up Claude Code on my server and started investigating to see if I could find something.<br>For reference I run a self-hosted Ghost instance on Digital Ocean (currently migrating to Hetzner, but that's another story) on top of an Ubuntu with Nginx as reverse proxy.<br>I spent the next hour or so poking at my server with Claude and we arrived at the same conclusion :<br>The error is on the other side.<br>I can reproduce 😖!

But that's when a third report from an old friend finally came in that it all finally clicked in my head.<br>This all seems to be very Windows related! So I fired up by gaming rig and voila : here's the popup<br>With the ugly scary don't do it follow up message:

The good news : I could reproduce. The bad news ? Well my server is actually infected (remember this next time you're tempted to trust AI to make conclusions for you :)).<br>Time to investigate<br>Now that I could reproduce myself, I had access to the source of the generated popup<br>So it was a matter of finding where this was embedded. The popup seems to be created in a rcoverlay id. Let's dive deeper into what's in there.<br>I made a curl request with a Windows user-agent to see if anything suspicious could be found<br>curl -s -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36" \<br>https://lengrand.fr/ways-in-which-genai-has-changed-my-coding-so-far/ | grep -i "rc_overlay\|_rc_\|robot\|script"There we go, it looks like somehow a script is injected into the footer of all of my posts and activated only on Windows machines.<br>BTW, if we forget the fact that Claude is often wrong about its conclusions, it's definitely been a great companion and helped me speed up my research by a bunch!<br>Now that we know what to look for, it gets easier. Nothing in the ghost install files, nothing on the reverse proxy side, the next logical target is the database. And as expected :<br>$ mysql ghost_prod -e "SELECT COUNT(*) FROM posts WHERE codeinjection_foot LIKE '%eralfduolccitats%';"<br>+----------+<br>| COUNT(*) |<br>+----------+<br>| 148 |<br>+----------+

mysql ghost_prod -e "SELECT id, slug, codeinjection_foot FROM posts WHERE codeinjection_foot LIKE '%eralfduolccitats%' LIMIT 1";Bingo, the malicious script tag has been added to all of my articles inside the database directly, in the codeinjection_foot column.<br>That's sneaky, because the code injection settings of my ghost admin interface is where I looked for clues at the very beginning of my research. But since those changes were directly written in the database so my instance looked clean at first glance.<br>And now, the fix<br>Now that we know where the problem is, the fix comes rather easy. I don't actually have any footer injection on my instance, so I've simply set the columns to NULLfor all of the articles in my database.<br>$ mysql ghost_prod -e "UPDATE posts SET codeinjection_foot = NULL WHERE codeinjection_foot LIKE '%eralfduolccitats%';"<br>$ mysql ghost_prod -e "SELECT COUNT(*) FROM posts WHERE codeinjection_foot LIKE '%eralfduolccitats%';"<br>+----------+<br>| COUNT(*) |<br>+----------+<br>| 0 |<br>+----------+(Bit of a scary command to run, I can't think the snapshot capabilities of Digital Ocean enough). If you run this yourself, make sure to make backups first!<br>Cleanup<br>The last steps were to make sure the issue wasn't happening any more, and plugging any hole I could think of. So I<br>updated my server and the ghost install<br>changed my password<br>checked for unknown users in my ghost instance<br>rotated all my keys<br>The issue seems to have happened somewhere 2 days ago, date at which all of my articles were updated. They do have an update time in the database, which makes me believe that the changes were done via ghost itself, rather than a direct access to the server<br>SELECT slug, updated_at FROM posts WHERE updated_at >= '2026-05-16' ORDER BY updated_at DESC LIMIT 20;

+-------------------------------------------------+---------------------+<br>| slug | updated_at...

from codeinjection_foot ghost like posts claude

Related Articles