惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Microsoft Azure Blog
Microsoft Azure Blog
GbyAI
GbyAI
P
Proofpoint News Feed
Engineering at Meta
Engineering at Meta
Recent Announcements
Recent Announcements
L
LangChain Blog
B
Blog
阮一峰的网络日志
阮一峰的网络日志
Microsoft Security Blog
Microsoft Security Blog
博客园 - 【当耐特】
M
MIT News - Artificial intelligence
D
Docker
WordPress大学
WordPress大学
J
Java Code Geeks
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
The GitHub Blog
The GitHub Blog
博客园 - 叶小钗
Last Week in AI
Last Week in AI
Stack Overflow Blog
Stack Overflow Blog
有赞技术团队
有赞技术团队
MyScale Blog
MyScale Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
MongoDB | Blog
MongoDB | Blog
博客园 - Franky

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
Inside a Real Production Server Breach
ALI MANSOOR · 2026-05-24 · via DEV Community

Just a normal day.
23rd May, 2026.

Wake up in the morning, pick up my friend from his house, head to the gym.

Somewhere between sets, he casually mentions:

"One of my client's apps went down. I've been awake for the last 2-3 hours trying to fix it."

We start discussing it casually.

He tells me:

  • git status showed a huge number of untracked files
  • index.php had been replaced
  • he quickly stashed changes
  • restarted apache2
  • the app came back online

At that point, it was obvious:

Someone had access to the server.


The Investigation Begins

Fast forward to the evening.

We hop on a call and start investigating properly.


Step 1 — Check for Suspicious Processes

First thing:

ps aux --sort=-%mem | head

top

htop

We also checked for suspicious network connections:

ss -tulpn

netstat -antp

Nothing unusual.

No obvious crypto miners.
No rogue reverse shells.
No suspicious high CPU usage.


Step 2 — Check Active Users & Login History

Now we move toward authentication logs.

who

w

last -a

lastlog

Then:

cat /var/log/auth.log | grep "Accepted"

And there it was.

A suspicious login around the exact same time the server went down.

Even more interesting:

The attacker was exploring the server manually.

We saw commands like:

pm2 list

docker ps

cd /var/www
ls -la

find . -type f

This wasn't automated malware blindly running.

Someone had interactive shell access.


The Weird Part

The traffic was coming from an Amazon IP address.

And not just any region.

It originated from the same country as the client.

That initially made things confusing because AWS IPs often look "legitimate" during quick inspection.


Step 3 — Inspect the Web Directory

Now we check the actual application files.

git status

Absolute chaos.

Dozens of unexpected PHP files.

Mostly inside:

/var/www/public_html

Some had random names like:

x.php
shell.php
cache.php
1index.php

Classic indicators of uploaded web shells.

At that moment, one thing immediately came to mind:

LFI / Arbitrary File Upload

If attackers can upload executable PHP files into a web-accessible directory, game over.


Step 4 — Trace the Upload Vector

I ask him:

"Can users upload files anywhere on the platform?"

He says:

"Only paid users can upload."

Then adds:

"But there is a free trial."

Bingo.


Step 5 — Find the Attacker Account

We inspect recent signups.

Sure enough:

A suspicious user registered around 3-4 days earlier using the free trial flow.

Now we know where to look.


Step 6 — Check User Uploads

We inspect the upload directories.

ls -la /var/www/assets/uploads/

Then:

find /var/www/assets/uploads -type f | grep ".php"

And there it was.

A PHP script uploaded directly into the user's upload directory.

/assets/uploads/1234/xannyanaxium.php

The attacker was simply visiting:

https://example.com/assets/uploads/1234/xannyanaxium.php

And it presented with a kind of a control panel, to upload further files, execute commands and whatnot.


What Happened

The application allowed users to upload files.

But:

  • file extensions were not validated properly
  • uploaded files were stored in a publicly accessible directory
  • PHP execution was allowed inside uploads
  • attackers could execute arbitrary code

This resulted in:

Remote Code Execution (RCE)

Once the attacker uploaded a PHP web shell, they effectively had server access.


Example of a Dangerous Upload

A minimal malicious PHP shell can be as small as:

<?php system($_GET['cmd']); ?>

Which allows attackers to run:

shell.php?cmd=id

Or worse:

shell.php?cmd=rm+-rf+/


Immediate Remediation Steps

1. Disable PHP Execution in Upload Directories

Inside uploads directory:

nano /var/www/assets/uploads/.htaccess

Add:

php_flag engine off

Or for Nginx:

location /uploads/ {
    location ~ \.php$ {
        deny all;
    }
}


2. Restrict Upload Extensions

Allow only:

jpg
jpeg
png
pdf
webp

Never trust client-side validation.

Validate server-side.

Example in PHP:

$allowed = ['jpg', 'jpeg', 'png', 'pdf'];

$ext = strtolower(pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION));

if (!in_array($ext, $allowed)) {
    die("Invalid file type");
}


3. Rename Uploaded Files

Never preserve original filenames.

Instead:

$newName = bin2hex(random_bytes(16)) . ".jpg";


4. Store Uploads Outside Web Root

Bad:

/var/www/public_html/uploads

Better:

/var/app_uploads

Serve files through application logic instead.


5. Hunt for Persistence

Attackers often leave backdoors.

Search aggressively:

find /var/www -type f -name "*.php" | grep -E "(shell|cmd|cache|tmp)"

Search recently modified files:

find /var/www -mtime -7

Search suspicious functions:

grep -R "system(" /var/www
grep -R "exec(" /var/www
grep -R "base64_decode" /var/www


6. Rotate Everything

Assume compromise.

Rotate:

  • SSH keys
  • database passwords
  • API keys
  • JWT secrets
  • cloud credentials
  • payment provider keys

Everything.


It all came down to one thing:

Never allow executable uploads into a public directory.