17 Plan B: Plugging the Holes in Your Existing Application

It’s a lot harder to secure an application that’s already been written than it is to write it securely in the first place. Unfortunately, it’s also a much more common scenario. That’s just life, so in this chapter we give you some concrete ways to harden an existing application.

Set Up Your Environment

If you’re already using a three-stage deployment system, you’re ahead of the pack and odds are your code is more stable and more secure because of it. If not, read this section carefully and give some serious thought to implementing this type of system.

Using a Three-Stage Deployment

The three stages of deployment are development, test, and production. You should have a separate server for each stage, although thanks to virtual server technology you can implement this system with only two machines—one purely for production, one with two virtual servers for development and testing, as shown in Figure 17.1.

Figure 17.1. Three-stage deployment system using two machines.

Three-stage deployment system using two machines.

Development

The reason for a dedicated development box, sometimes called a sandbox, is that it gives you the freedom to make mistakes without worrying about breaking anything. On your development box, you can install experimental code libraries, write proof-of-concept code, and play around with exploit techniques to better understand how to defend against them. You wouldn’t want to risk trying out a SQL injection attack technique on your live application—if it works, you could do some serious damage. In your sandbox, however, if the exploit works and you corrupt your data, nothing too important is lost.

To set up a development box, you’ll need a computer or virtual server with the same basic configuration as your production server. Make sure you have the same version of the operating system, database, and PHP. Install all the libraries and tools you use in production, and load a copy of the production data into your development database. Finally, load a copy of the application code from production. Your development box will start out as an exact replica of production, but it won’t stay that way.

Testing

Your test server should also start out as an exact replica of production, but this server needs to stay that way. The only difference between test and production is the new code that you’re ready to deploy.

The purpose of deploying new code on the test server first is that sometimes even a small bug fix will break another part of the application. Your automated tests should catch those bugs, but you never know. You’ll also catch any dependency problems by deploying to a test server. If you use an off-the-shelf code library in development, but don’t have that library (or one of its dependencies) on your production server, the new code you’ve added to your application won’t work.

Installing the code to a test server will catch the problem before it becomes a crisis. It’s a last line of defense before your application goes live and (potentially) crashes the entire production Web server. If your application breaks something, ideally you’ll catch that in your development sandbox. If you don’t, installing to an exact replica of production will let you know if you’ve missed something.

Many programming groups use a mirror image of production as their test server and sync the two systems and their data regularly. You should at least sync your test server to production before you install a new version of your code. That way you can be absolutely certain that nothing in the new code will break your production site.

Production

Production is the server that’s open to the public. Everything else is just a dress rehearsal—code running on a production server is on stage before the public. At the point the code is deployed to the production server, it should have already been through the full development process (including automated and manual testing) and have been running on the test server for a while.

Using Version Control

A version control system is like putting the most obsessive pack rat you know in charge of your code. It saves every version of the code you produce just in case you need to go back and review the changes you made six months (or six years) ago. This may seem a bit extreme, but it’s an essential tool for anyone writing a production-ready application. How many times have you fixed a bug only to realize that your fix broke something else? Version control allows you to revert, not only to the last known good version, but literally to any version ever created. There are two main version control systems. Which one you use depends on whether you operate in a Windows environment or a UNIX/Linux/Mac environment:

• Visual SourceSafe is Microsoft’s version control system.

It is part of Microsoft’s Visual Studio. Visual SourceSafe is available from http://msdn.microsoft.com/en-us/vs2005/aa718670.aspx.

• CVS is an open-source version control system.

It has been the de facto standard for open-source version control for as long as most programmers on the Web can remember. If you’ve installed PHP or virtually any other open-source software package, odds are you’ve used CVS whether you knew it or not. Mac OS X and most UNIX and Linux distributions come with CVS. To obtain the latest version of CVS and to read the documentation, go to www.nongnu.org/cvs/.

• Subversion is the modern replacement for CVS.

It was written to address some of the problems inherent in CVS and to give programmers more granular control over what is stored in version control. Subversion is also open-source, and you can get a copy at http://subversion.tigris.org/.

If you’re writing an application that’s meant for anything beyond a simple script, you should store your code in a version control system. Installing and using a version control system will be well worth it the first time you accidentally delete a file you’ve been working on or need to revert to a previous version of your code.

Application Hardening Checklist

Hardening an existing application is a four-step process:

1. Check your server security.

2. Find the vulnerabilities in your code.

3. Fix the most obvious problems.

4. Have your code peer-reviewed.

We’ll discuss each step in this section.

Check Your Server Security

The first step in hardening an existing application is to examine the environment it runs in. If the server or database isn’t secure, having a secure application won’t do much good. Secure the server, then move on to securing your application. For more detailed information on securing the server, review Chapter 11, “Securing Apache and MySQL”; Chapter 12, “Securing IIS and SQL Server”; and Chapter 13, “Securing PHP on the Server.”

Find the Vulnerabilities in Your Code

Once you’re sure the server is as secure as possible, it’s time to take a good hard look at your code to see which vulnerabilities are lurking around.

Perform White-Box Tests

White-box testing is done using an automated tool that crawls through your code looking for common and obvious vulnerabilities.

Perform Black-Box Tests

Black-box testing tells you how your code will stand up to an actual attack by subjecting it to a dry run of various types of exploits and attacks. A black-box test launches an actual SQL injection, cross-site scripting, buffer overflow, or some other type of attack against your application. When the server or the database is compromised, you’ll know you’ve found a vulnerability. Fuzzing, which we discussed in Chapter 15, “Introduction to Exploit Testing,” is a great example of black-box testing.

Fix the Most Obvious Problems

Once you know the weaknesses in your code, it’s time to start fixing things. You won’t be able to fix everything all at once, so the three most important areas to concentrate on are

• Variable sanitation

• Data storage

• Encapsulating risky tasks

By this point, you should already have a good idea of how vulnerable your application is in each of these areas. Of course, if your testing revealed other problems, include those in your task list as well.

Sanitize Variables

We’ve discussed sanitizing variables, sanitizing user input, and sanitizing data pretty extensively throughout this book, and this is why: Lax variable sanitation is one of the most prevalent causes of security breaches, and it’s one of the easier ones to fix. We won’t rehash how to sanitize variables here—you can go back and read Chapter 4, “Buffer Overflows and Variable Sanitation,” if you need to review the nuts and bolts. When you have checked literally every variable that holds data originating from outside your own code, your application will be more secure than the vast majority of Web applications on the Internet.

Store Data Securely

Once you’ve sanitized all that data, you’ll want to make sure you’re storing it securely. This is most important when dealing with sensitive data such as passwords, credit card numbers, Social Security numbers, and other inherently valuable data. You probably don’t need to encrypt your mailing list, because if it were compromised the repercussions wouldn’t be catastrophic. You know your data, so you know best whether the increased security offered by encrypting the data is worth the trade-off in slower execution times.

Encapsulate System Calls and Other Risky Maneuvers

We have discussed creating an API to encapsulate tasks that carry some risk, such as system calls and filesystem manipulations. Segregating those tasks from the main body of your code allows you to keep very tight control over the data that is passed to those functions, preventing a malicious user from using system calls to gain access to your server. Review Chapter 3, “System Calls,” for more information on creating API functions.

Have Your Code Peer-Reviewed

Once you’ve tested your code, found a handful of vulnerabilities, and fixed them, it’s a good idea to have someone else double-check that you haven’t introduced some glaring security hole. Anytime you make major changes to your code, having an actual human with some knowledge of Web application programming—and ideally a base understanding of security—do a sanity check is always a good idea. Peer review isn’t meant as a replacement for automated system and unit tests, but as a supplement to them. We discuss finding a good peer reviewer in the Epilogue, “Security Is a Lifestyle Choice: Becoming a Better Programmer.”

Wrapping It Up

In this chapter, we discussed several specific things you can do to harden an existing application. Any one of the tasks we mention will increase the security of your application, but implementing most or all of them should leave you confident that your application will withstand most common attacks. It’s not a guarantee of security—there will always be new vulnerabilities and new exploits—but at least you’ll know that if someone is going to hack your application, he or she is going to have to work at it.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset