Why old PHP government portals keep getting hacked
It is rarely a clever attack. It is usually the same five mistakes, sitting in code nobody has looked at since it went live.
When a government website gets defaced or a database turns up for sale, the news usually calls it a sophisticated attack. In our experience it almost never is. Most of the PHP systems we audit fall to the same handful of problems, and most of them were written into the code on day one.
That is not a criticism of whoever wrote them. A lot of these portals were built around 2010 to 2015, often in a hurry, by small teams working to a fixed budget and a launch date. PHP was a different language then. What counted as normal practice has moved on. The code has not.
1. SQL built from raw input
The classic. A search box or a URL parameter is dropped straight into a query, something like "SELECT * FROM applicants WHERE cnic = '" . $_GET['cnic'] . "'". Anyone who knows to type a quote mark can read the whole table, and sometimes write to it as well.
Old code that still uses the removed mysql_* functions is almost always affected, but the newer mysqli functions are not safe on their own either. What fixes it is parameterised queries (prepared statements), used every time without exceptions.
2. File uploads that trust the filename
Citizen portals collect a lot of uploads: CNIC scans, photos, degree certificates. The usual mistake is checking the extension the browser sends, saving the file in a public folder, and keeping the original name. Upload a file called photo.php with some PHP inside, visit the link, and the server runs it.
The fix is to check the actual file content, rename everything on the way in, store uploads outside the web root and serve them through a script that checks permissions.
3. A PHP version that stopped getting fixes years ago
PHP 5.6 reached end of life in December 2018. PHP 7.4 reached it in November 2022. Any vulnerability found in those versions since then is public and will not be patched. We still find both in production regularly, sometimes on servers that have not been updated since they were installed.
Upgrading is rarely a weekend job, because old code breaks on new PHP in dozens of small ways. That is why it keeps getting postponed, and why it is usually the second thing we plan after closing the urgent holes.
4. Weak password storage and sessions that never expire
Passwords stored with md5(), or not hashed at all. Admin sessions with no timeout. No protection against cross-site request forgery, so a logged-in officer who opens the wrong link can approve something without knowing it. Permission checks on the menu, but not on the page the menu links to.
None of this is exotic. PHP has had password_hash() built in since version 5.5. The fixes are small; the work is finding every place they are needed.
5. Things left lying around
Database backups in the web root. A phpinfo() page left over from setup. An old copy of the admin panel at /admin_old/ that still works and has none of the later fixes. Config files with passwords committed to a repository that was public for a while.
The most dangerous file on a server is often the one nobody remembers creating.
What to do first
If you are responsible for one of these systems and have no budget for a full audit yet, start here:
- Find out exactly which PHP version is running in production. Write it down.
- Search the web root for
.sql,.zip,.bakandphpinfofiles and remove them. - Change the database password and any API keys, especially if the code has ever been shared or emailed.
- Check where uploaded files are stored and whether a
.phpfile placed there would run. - Make sure there is a recent backup, and that someone has actually tried restoring it.
None of this replaces a proper review, but it closes the doors attackers check first. If you would like a second pair of eyes on a specific system, we are happy to take a look.
Want us to look at your system?
Tell us what it runs on and what it does. We’ll tell you honestly whether it needs work.
Keep reading
Rewrite or fix in place? How we decide with legacy PHP
Everyone wants to start fresh. Sometimes that is right. Usually it is the most expensive way to end up with the same problems.
5 min readSaaS or GaaS? How to tell which one your product should be
SaaS sells access to a tool. GaaS sells the finished job. Most products in 2026 need a bit of both, and the split decides your pricing, your margins and your risk.
6 min read