Many popular web applications are implemented using a simple two-tier architecture. WordPress, which powers about a quarter of the world’s web sites, is a prime example. It is easy to understand why WordPress has become so popular. It is free, easy to use, incredibly flexible, simple to deploy, and tens of thousands of plug-ins are available. WordPress and plug-ins are written in PHP, which is easy to learn and customize.
The WordPress team takes security seriously, and has done a good job to prevent and quickly address security issues. However, from a security architecture perspective, WordPress, and other web applications that use the same architecture, are a breach waiting to happen.
In cybersecurity, the odds always favour the attacker. To succeed, the attacker only needs to find one exploitable vulnerability (or combination of vulnerabilities) to facilitate a breach. They only have to get it right once, and generally can make an unlimited number of attempts over an unlimited period of time. The defender, on the other hand, needs to get it right all the time, including software design, development, and system administration.
One of the ways to mitigate error-related risks is to implement multiple coordinated security controls, or as it is commonly called, defence in depth. A good security architecture takes the possibility of errors into account and seeks to minimize risk. WordPress is by no means the only web application with a poor security architecture, but its popularity makes for a good case study.
WordPress is written in PHP and is most commonly deployed on an open-source Linux Apache MySQL PHP (LAMP) stack. HTTP requests from users are processed by Apache, which invokes a PHP module to handle PHP script execution. A PHP file includes configuration information, including the IP address (or hostname) of the MySQL database and credentials to access it. WordPress requires full control of its database.
In many deployments the database is dedicated to a single WordPress instance. When deploying multiple WordPress sites, prudent administrators create a separate database with unique credentials for each site. However, WordPress also includes a database table name prefix option. This allows multiple WordPress sites to share a single database. WordPress Multisite installations also use a table name prefix approach and store data from all sites in the same database.
From an attacker’s perspective, the first target is the operating system. Automated SSH scanners, for example, seek out weak passwords that can be used to log on. Good system administration practices will mitigate most OS-level risks, but the possibility of an intrusion remains.
The second target is the web server. Misconfigurations (or possibly vulnerabilities) can allow an attacker to retrieve PHP source code and configuration information, including the database credentials. Since the configuration file is stored in the web server’s document root directory (a poor design decision), the only thing stopping an attacker from retrieving /wp-config.php is the fact that Apache’s PHP module should execute it instead of returning the content as an HTML or text page.
The third target is the WordPress software, installed plug-ins, and any other software (including CGI scripts) on the server. All WordPress modules, including third-party plugins, have unrestricted access to the database credentials and the database. They all execute in the web server’s context, allowing any software installed on the web server to access and use the database credentials. Since the credentials have unrestricted rights on the database, a vulnerable or malicious plug-in could add a WordPress user with admin rights, change the password of an existing user, or even delete the entire database.
To protect themselves, many site owners use WordPress backup plug-ins. While backups are a good practice, most implementations provide little protection against a destructive attack. For example, popular backup plug-ins provide the functionality to save backups locally and send them to external services such as Amazon S3 or Dropbox. To do so, the backup plug-ins require credentials to the external services and store them on the local server. If a WordPress site is compromised, it is trivial to obtain the credentials and use them to steal or delete the backups as well.
Finally, there is the database itself. In addition to the potential for compromise through application vulnerabilities (including SQL injections), in some cases it is possible to attack the database directly or indirectly through another application that uses the same database server.
Unfortunately there is no quick fix. Web applications such as WordPress should be designed to use a three tier architecture: Web, Application, and Database.
Users should continue to interact with a web server; the LAMP stack is fine. However, no credentials should be stored on it, nor should it have direct access to the database. Labelling the web tier as “untrusted” is tempting, but inaccurate since it has the ability to format data seen by users. It is also possible that a compromised web server could be used to capture user credentials. The key difference in this approach is that even if the web server is completely compromised, it should not be possible to perform arbitrary database functions.
All functions that involve retrieving and storing data should be performed through an application tier. A well defined, documented, and testable interfaces should separate the web tier user interface from application logic and access controls. A role-based access control model should mediate access to all application tier functions.
Finally, wherever possible, access controls should be implemented at the database level. This represents a significant change for most developers. The common practice of creating a single credential for the database that allows the application to do whatever it wants is highly undesirable from a security perspective. For example, when an anonymous user requests a public web page, corresponding database requests should not use credentials with grossly excessive privileges.
In an ideal implementation, each user would have their own database credentials, and even if an error in the web or application tier allowed a user to attempt an unauthorized operation, it would be blocked by the database. In some cases this is difficult to implement, but even having two database credentials known to the application tier (one for privileged and one for unprivileged operations) would represent a significant improvement over the status quo.
Have a security question you’d like answered in a future column? Email firstname.lastname@example.org
SAMSUNG GALAXY S8 PLUS
The Samsung Galaxy S8 Plus is a beautifully crafted smartphone with nearly no bezel, curvaceous in design and reflects a…
How to: Connect to Exchange Online Using Multi-Factor Authentication
Using PowerShell to manage your Microsoft cloud services like Exchange Online and using multi-factor authentication (MFA) separately is awesome. Using…