August 22, 2026
This Is How a Hacker Hacks: Part 5 — The Central Database, the Cleanup, and What It All Means

By CypherNova1337
4 min read
This Is How a Hacker Hacks: Part 5 — The Central Database, the Cleanup, and What It All Means
Parts 1–4 took us from an 18-year-old CMS to root on the backup server, with a password oracle in hand. Part 5 is the payoff, the integrity discipline that saved the evidence, and the part nobody writes about: leaving no trace.
1. The oracle pays off: the central campus database
The university's internal network had a MySQL server at its gateway address — the first host we'd probed days earlier, when it rejected everything we threw at it. That was before we understood the scheme. Now we had the oracle: the password is org@$. The box was commissioned in Buddhist year 2564. One try:
mysql -h <gateway> -u root -p'org@2564$'
Welcome to the MariaDB monitor.mysql -h <gateway> -u root -p'org@2564$'
Welcome to the MariaDB monitor.Root on the central campus database. The SHOW DATABASES; output ran off the screen — over a hundred databases: the Super Apps (yearly versions going back a decade), the exam system, the attendance API, big-data warehouses, the graduate school, teacher evaluations, general education, the budget system, petitions, authentication logs — and the ones that mattered most:
- [censored]_student — 1.36 million rows of student records
- studentmaster — the master student index
- studentcard — student card records tied to a national bank: full names in two alphabets, 13-digit national ID numbers, birthdates, emails, phone numbers, complete postal addresses, faculty and program codes, card photos rebate — tuition refunds; student_loan — student loans; student_fund — scholarship funds
- ora_data — the online registration system's data
The client's fear from day one — "did we leave any bank information open?" — had a two-part answer: no account numbers on the web systems, but the entire bank-linked student card dataset sat behind a root password that was derivable from any other password the admin had ever set.
We dumped the ten databases that matter (about 220MB compressed — the whole thing is text, and text compresses), verified every file's integrity, and added them to the evidence set. This is also where the engagement's rules paid off: the dump used --single-transaction --quick, SELECT-only, zero writes to their data.
2. Integrity discipline: the 23GB relay and the one bad part
The largest artifact of the engagement wasn't the database — it was a 23GB corpus of scanned national-ID documents (550+ applicants, every page scanned, QR codes included) that the client explicitly authorized us to pull. Moving 23GB out of a target without touching its bandwidth-visible surface is a logistics problem:
- Tar it on the backup server (streaming, no staging).
- Split into 2GB parts, hash each part on the source.
- Relay each part: source → pivot box → webroot staging file → HTTPS download.
- Delete each staging file; assemble locally; verify.
And here's the part that mattered: after reassembly, tar reported corruption — "a lone zero block" mid-archive. Every part's hash matched the remote manifest. The corruption was inside a part that had been correct when it was split, and one part had been corrupted in transit — our per-part verification caught exactly which one. One re-relay, one reassembly, and the archive verified clean: 2,600+ files, byte-perfect.
The lesson is boring and it saved the engagement: hash at the source, hash at the destination, compare per-part, never trust the sizes match. Sizes always match. Sizes are the easiest thing in the world to match.
3. The cleanup: being the attacker who leaves nothing
The client's final instruction before closeout was the one every pentest report skips: remove any evidence you were ever here, and put the admin password back.
The full list, executed over a long final session:
Restore:
- The admin password hash was restored byte-for-byte to the original (recovered from the pre-engagement backups) — the client's real password worked again.
- The admin's lastvisitDate was rolled back to its pre-engagement value; session rows from our window were deleted.
- A nightly backup dump that had captured our engagement hash was deleted. (Dumps before and after are clean.)
Remove — on the document system:
- The webshell component: files and its database row.
- Every artifact in /tmp: exploit binaries, upload chunks, scripts, askpass helpers, the setuid shell.
- PHP session files created during the window.
- SSH known_hosts entries for our targets.
- Staging files in the webroot.
Remove — on the backup server:
- The 23GB tar and its parts, ~300GB of converted VM images, samples, logs, scripts.
- All loop mounts and LVM activations reversed; loop devices detached.
- Disk usage returned to its pre-engagement value, byte for byte.
What we could not remove: the pivot box's Apache access log contains the request paths from our session (a few hundred lines, every one source-masked as the campus proxy's IP — no personal addresses were ever recorded). They rotate out with the weekly log rotation. And the campus WAF, which had been watching our traffic all week, now 403s the password-reset endpoint outright — the engagement itself taught their WAF a rule. We flagged both to the client: their reset page may now be blocked for legitimate users, which is the kind of collateral finding that only an honest closeout reports.
4. What the whole engagement means
If I had to compress a few days into a paragraph:
A university's e-document system — 18 years old, one user, WAF-fronted — fell to a password-reset bug from 2008 in two POST requests. A userspace polkit bug from 2021 made root on the 2016 box. Root's own history files handed over the backup server, whose keyring named every host in the estate. And a ten-year-old password formula — year of setup, never rotated — opened the central database holding the student body's identities and bank-linked cards.
Every single step used a vulnerability the defender could have closed years ago, and every pivot used the target's own operational habits as the attack surface.
The walls were real: dirtycow wouldn't race, a full filesystem faked its own health, credential sprays bounced. But walls only shape the path; they don't end it — not while the estate keeps ten-year-old passwords, readable backups, and a history file full of plaintext.
For defenders, the five cheapest wins from this story:
- Inventory your patch spread. The oldest box defines you. One 1.5.0 in a sea of current software is still a 1.5.0.
- Treat backups as an attack surface. World-readable dumps, unreadable-but-unmonitored arrays — backups are where secrets live forever.
- History files are credentials. .bash_history, .mysql_history, .viminfo contain your passwords. Rotate, truncate, or accept that root's diary will be read.
- Rotate, don't formula. A year-based password scheme is a keyring with a public index. Every reused credential converts one compromise into an estate-wide one.
- Monitor the boring signals. A root filesystem at 100% and a storage array throwing I/O errors went unnoticed for months. The attacker noticed in minutes. Your monitoring should be faster than your adversary's recon.
This series is based on an authorized penetration test. All identifying details have been changed; the techniques and CVE numbers are real, and so are the walls.
The author does security testing professionally. Nothing in this series should be applied to systems you don't own or aren't authorized to test.