Why your site gets hacked: 8 flaws we find in almost every project

Why your site gets hacked: 8 flaws we find in almost every project

When a client comes to us after a breach, the picture repeats: it wasn't a genius hacker defeating something hardened. Usually an automated script scanning the internet found a known open door. Let me list those doors.

1. An outdated WordPress or plugin

This is the number one cause by a wide margin. A plugin not updated in a year has a publicly disclosed vulnerability — and scripts hunt for exactly that. If your WordPress site isn't updated monthly, it isn't "working" — it's waiting its turn.

Fix: regular updates, remove any unused plugin (a deactivated plugin is still a vulnerability), and never use pirated plugins — many ship with a planted backdoor.

2. SQL injection

When code takes user input and drops it straight into a database query. The attacker types something into a search box that makes the query return the whole users table with passwords.

Fix: prepared statements, always. Any modern framework — Laravel, Django, Rails — does this by default when used properly. The hole appears when someone hand-writes a query "to be faster."

3. Unchecked file uploads

The "upload your profile picture" field that accepts any file. The attacker uploads a PHP file instead of an image, opens it in the browser, and now controls your server.

Fix: validate the actual file type rather than the extension, store uploads outside the web root or in separate object storage, and disable execution in the upload directory.

4. Weak passwords and no two-factor

An admin panel on a predictable path plus the password "admin123" is a matter of time. Scripts try thousands of attempts a minute.

Fix: rate-limit logins, two-factor on admin accounts, and passwords hashed with bcrypt or argon2 — not encrypted, and never MD5.

5. Broken access control

This is the one we find most in custom systems. The URL `/invoice/1052` shows an invoice. The user changes it to 1053 and sees another customer's invoice. The system checked that you're logged in but forgot to check the invoice is yours.

Fix: every data query must be filtered by the user's identity, not merely gated behind a login check.

6. Secrets committed in code

API keys and database passwords written inside files, with the project pushed to GitHub. There are bots whose only job is scanning public repositories for exactly these keys.

Fix: all secrets in environment variables outside the code, with the env file git-ignored from day one.

7. Error messages that tell everything

An error page exposing the file path, framework version and database query. That hands an attacker a complete map of your system.

Fix: in production, a generic message for the user and details in an internal log.

8. No tested backups

Not exactly a vulnerability, but it's the difference between "a bad day" and "a catastrophe." The worst case is a backup that exists but nobody ever tried restoring — and when it matters it turns out incomplete or corrupt.

Fix: automated daily backups, stored separately from the server, and tested with a real restore periodically.

Bottom line

Security isn't a product you buy once, it's a habit. Updates, correct access control, secrets outside code and tested backups cover most real-world risk. If you're unsure about your site's current state, we run a security audit that produces a report of findings ranked by severity.

More articles

Custom ERP: the real cost and timeline, honestly →Native or Flutter? Choosing your app stack without regret →The spec document: what separates a shipped project from a year of delays →

Got a product idea? Let's turn it into working code.