In Part 1 of this series, we were introduced to some of the fundamental security flaws that may afflict your PHP applications. In Part 2, let’s dive a bit deeper into some of the most advanced security flaws that may afflict your environment. Truth be told, there are potentially an infinite number of ways in which a software product can be compromised and have its security breached. Gene Spafford, computer security expert at Purdue University, said, “the only truly secure system is one that is powered off, cast in a block of concrete and sealed in a lead-lined room with armed guards.” Spafford has a point: any system that is exposed to the public may have a flaw, and it is only a matter of time before the flaws are discovered and quickly (hopefully) patched.
“The only truly secure system is one that is powered off, cast in a block of concrete and sealed in a lead-lined room with armed guards.” – Gene Spafford
Security is, without a doubt, a moving target
New security flaws are regularly found, and routine patches are immediately released for most of the major software applications you utilize in your application stack. No matter whether your web or database server, your operating system, your PHP runtime, or even the MVC framework that your time adopted, your point(s) of exposure may exist anywhere within the various components that make up your application ecosystem.
While the professional community has evolved and best-practices are becoming standard practices, there are still reason for concern, and you should never take your security lightly.
Security Best Practices
The term best-practice suggests a broad gray area of generally accepted knowledge that most developers and systems administrators adhere to. For the purposes of this article, I am using it as a catch-all for the general techniques that you should be aware. Each of this topics could, of course, expand into extensive conversations about each, but I’ll cover them from a high-level perspective.
Turn SSL on at all times
When accessing your application over the regular port 80, you are serving content to your users over an unsecure connection. This may not be an issue if you are not collecting private user data and only serving public-friendly content. Perhaps for a 5-page information website, port 80 may not be a problem. However, what if you allow the ability for your users to login and store extremely sensitive financial and personal information? Not only should your login page itself be protected via SSL over port 443, but you should enforce SSL over every connection with your web application (private and public information). It seems that SSL has become the de facto standard for most of the common web applications, including Facebook and Google.
If you are unsure how to access the port number, take a look at the global $_SERVER function. You can create checks at the beginning of your application to redirect to HTTPS if a user attempts to access your site via HTTP.
Hide all version numbers
For a hacker to compromise your system, part of the effort involves understanding what your system consists of. What good is knowing the security exploits of a particular version of the application you are running when the hacker does not know the version you are running? Unfortunately for the rest of us, this information is publicly accessible and extremely easy for hackers to obtain.
A fundamental search through your HTML can reveal information about your infrastructure and application stack that you never imagined would be exposed. From the Javascript libraries to the type of third-party monitoring tools you use, you are revealing far more information than you think you are. Even the information you pass along in your HTTP headers can help someone understand the web server, operating system, MVC frameworks, hosting provider, analytics tools, and other vital information necessary to build a plan to attack your product. You can see for yourself by navigating to builtwith.com and querying your favorite sites to see what technology stack they are running. Look into your particular application stacks to determine how to turn off the signature being sent back to the client so that you can hide this sensitive data.
Keep your errors in logs and away from the public
A common mistake is making errors publicly viewable. A skilled PHP application craftsman understands that application errors are not for the public to view. What does the public need to see? The public needs to see nothing more than a funny and friendly error! That is all your visitors need to see. All other errors should immediately go to your logs and/or yourAPM monitoring tool! The more information you make public, the more information you provide hackers to exploit. Your error messages may include information about the extensions you are using, the PHP runtime, server information, directories and paths, and other vital information necessary to conduct an attack on your application. Take a look at the display_errors, log_errors, and error_log declaratives.
Disable potentially harmful PHP functions
A suitable practice is to disable PHP functions that could potentially be hijacked and used for harm. I bet you did not know about this critical feature that PHP offers. As an additional layer of security, completely turn off certain functions that could execute harmful code if your application is ever compromised. The disable_functions declarative takes a list of functions you would like to make unavailable to PHP.
More Injection Attacks
In Part 1 of this post, we covered SQL injection and XSS attacks. We’ll cover a few more potentially harmful injection attacks that you are susceptible to.
Shell Injection
Have you ever been introduced to the shell_exec() function? What about exec(), passthru(), and system()? Each of these functions has the potential to do some incredibly significant damage to your system if ever compromised. Take for example shell_exec() — you can pass a string to this function, and it will execute whatever shell command was contained in that string.
My first recommendation is to disable these functions altogether if you are not using them anywhere in your application. If you are using these functions, you absolutely must sanitize your data before passing them through to your functions for execution.
eval()
eval() is a function that deserves a section of its own. eval() will execute PHP code that is passed to it as an argument. Generally speaking, there are very few scenarios in which you will ever need to use this function. The use of eval() is considered poor practice, and if you find yourself — or your application — using this function, then I strongly recommend that you revisit the need for it. Like other potentially harmful functions, my recommendation is to have this function never used and disabled entirely.
File Inclusion
include() and require() are standard functions in which a PHP script will include another file in its point of execution stream. While these functions serve an essential utility, they also are potentially harmful if compromised. By simply passing a directory path, whether relative or absolute, an intruder can reach any file available to PHP and include it in the execution stream, if successful. These two functions are used so commonly that disabling them is an impossible option. Thus, ensuring proper use and secure data sanitization (if passing variables) is the best practice when using require() and include().
Storing Secure Data
An entire book could probably be written on the practice of storing data securely. This topic, unfortunately, extends beyond the scope of this particular blog post. However, if I can stress the importance of at least understanding the sensitivity of storing critical data, then I may have partly accomplished my goal. Storing data such as the following should be given a security audit for both the sake of your customers and for regulatory compliance:
- Social Security numbers.
- Credit card numbers.
- Dates of birth
- Driver’s license numbers
- Health and medical records
- Bank account information
- Tax records
- Credit reports
Make no mistake, the list does not stop here as these are only examples of the type of information that you must treat as highly sensitive. Best practices vary, as do the legal implications of not ensuring proper procedures and practices required by various legal and regulatory bodies.
Keep private apps behind a VPN
If you have admin applications that are used only by your internal employees, then there should be no need to expose the application to the outside world. You can devise a private VPN so that even if your employees are remote, they are required first to connect to your private network first before they are allowed the option of accessing different private applications.
Having a private VPN will introduce an additional layer of security to your corporate assets, regardless, and also provide secure access to your private internal applications. Even if you set a .htaccess password for your most private applications — make no mistake — your software can be hacked and compromised the more exposure you provide it to the outside world.
Security is much of an art as it is a science. The more that you invest in best practices and security precautions, the safer your customers and your company will be. As PHP applications grow in scale to meet the demands of your business as it scales, the more vulnerabilities you and your organization will become exposed to. Understanding the various critical points of weaknesses will help provide the framework necessary to have a solid security plan in place.