Skip to main content

skip to main content

developerWorks  >  Tivoli  >

Software security principles: Part 4

Keep it simple, keep it private

developerWorks
Document options

Document options requiring JavaScript are not displayed


Learn and share!

Exchange know-how with your peers -- try our new Pass It Along beta app


Rate this page

Help us improve this content


Level: Introductory

Gary McGraw (gem@cigital.com), Vice president of corporate technology, Cigital
John Viega (viega@cigital.com), Senior research associate and consultant, Cigital

01 Dec 2000

In this installment, Gary and John present a set of 10 principles that can help you remove the majority of security problems from your code. Last time, they focused on the principles of least privilege and compartmentalization, both of which can help you design high-quality access models. This time around, they'll show you how simplicity is more important when it comes to security than most people suspect. They'll also discuss privacy concerns; giving out too much information can ruin you.

Principle 6: Simplicity

In many areas, you're likely to hear the KISS mantra -- "Keep it simple, stupid!" This applies just as well to security as anywhere else. Complexity increases the risk of problems; this seems unavoidable in any system.

Clearly, your designs and implementations should be as straightforward as possible. Complex designs aren't going to be as easy to understand, and are therefore more likely to have lingering problems that will be missed. Complex code tends to be harder to analyze and maintain. It also tends to be far more buggy. We don't think this will come as a big surprise to anyone.

Similarly, you should consider reusing components whenever possible, as long as the components you're considering are of good quality. The more times a particular component has been successfully used, the more you should avoid rewriting it. This consideration particularly holds true for cryptographic libraries. Why would you want to re-implement AES or SHA-1 when there are several widely used libraries out there? Those libraries are a lot more likely to be robust than something you put together in-house. Experience builds assurance, especially when those experiences are positive. Of course, there is always the possibility of problems, even in widely-used components. However, it's reasonable to assume that there's less risk involved in the known quantity.



Back to top


Those bells

It also stands to reason that adding bells and whistles tends to violate the simplicity principle. True enough -- what if those bells and whistles are security features? When we discussed defense in depth, we said that we wanted redundancy. Here, we seem to be arguing the opposite. We previously said, "don't put all your eggs in one basket." Now we're saying, "be wary of having multiple baskets." Both notions make sense, even though they're obviously at odds with each other.

What you need to do is strike a balance that is right for your particular project. When adding redundant features, you are generally trying to improve the perceived security of the system. Once you've added enough redundancy to address whatever security margin you've decided upon, then you should not add extra redundancy. In practice, a second layer of defense is usually a good idea, but you should carefully consider a third layer.

Despite its obviousness, the simplicity principle has its subtleties. First, you must strive to build as simple a system as possible, while still meeting your security requirements. Yes, an online trading system without encryption is certainly simpler than an otherwise equivalent one that has it. But there's no way that it's more secure.



Back to top


Choke points

Another way to improve the simplicity of your software is to funnel all security-critical operations through a small number of choke points in your system. A choke point is a narrow interface to a system that you force all traffic to go through, so that you can easily control it. You should avoid spreading security code throughout a system, because it becomes more difficult to maintain. In addition, it's far easier to monitor what your users are doing if they're all forced to work through a few small channels. This is the same theory behind sports stadiums with only a few entrances; if there were lots of entrances, it would be much harder to collect tickets. You'd need a lot more staff to get the same quality results.

One important thing to remember about choke points: There should be no secret ways around them. For example, if a stadium has an unsecured chain link fence, you can be sure that people without tickets will get in. Providing "hidden" administrative features or "raw" interfaces that savvy attackers could penetrate can easily backfire. There have been plenty of examples in which a hidden administrative backdoor could be accessed by a knowledgeable intruder, such as a backdoor in the Dansie shopping cart, or a backdoor in Microsoft FrontPage, both discovered in the same month (April, 2000). The FrontPage backdoor became somewhat famous due to a hidden encryption key that read, "Netscape engineers are weenies!"



Back to top


Usability

Another often-overlooked, but incredibly important aspect of simplicity is usability. Anyone who needs to use a system should be able to get the best security you have to offer easily, and should not be able to introduce insecurities. Usability applies to both the people who use your product and the people who have to maintain your codebase, or program against it.

Designers and programmers always seem to think they have an intuitive grasp of what is easy to use. However, usability tests generally prove them wrong. Marginal usability might be O.K. for applications with average functionality, because your product might be cool enough that ease of use isn't a real concern (lucky you.) When it comes to security, however, usability becomes more important, because if the user interface for security isn’t incredibly easy to use, many users will be vulnerable.  Nonetheless, most people will still ignore it.

Strangely enough, there's an entire science of usability. We definitely think that all software designers should read two books in this field, The Design of Everyday Things, by Don Norman, and Usability Engineering, by Jakob Nielson (see Resources). This space is too small to give adequate coverage of this material. However, we can give you some relevant tips, as they apply to security:

1) The user will not read documentation. If the user needs to do anything special to get the full benefits of the security you provide, then the user is unlikely to receive those benefits. Therefore, you should provide security by default. A user should not need to know anything about security or have to do anything in particular to be able to use your product securely. Of course, security is a relative term; you will have to make some decisions as to the security requirements of your users.

Consider enterprise application servers that have encryption turned off by default. Generally, you can turn it on with some menu option on an administrative tool somewhere. Even if a system administrator stops to think about security, that person will likely think, "They must have encryption on by default." We've seen plenty of servers that didn't.

2) Talk to users to figure out what their security requirements are. As Nielson likes to say, vice presidents are not users. You shouldn't assume that you know this information; go directly to the source. Try to provide users with more security than they think they need.

3) Recognize that users aren't always right. Most users aren't well-informed. They may not understand security issues, so you should still try to anticipate their needs. It's a good idea, however, to err on the side of security. If your assessment of their needs provides more security than theirs, use yours (actually, try to provide more security than you think they need). If theirs provides more, definitely trust them.

For example, think about a system, such as a WWeb portal, where one service you provide is stock quotes. Your users might never think there's a good reason to secure that material. After all, stock quotes are for public consumption. But there is a good reason -- an attacker could tamper with the quotes users get. Users might then decide to buy or sell stock based on bogus information, and lose their shirts. Sure, you don't have to encrypt the data -- you can use a message authentication code (MAC) -- but most users are unlikely to anticipate this risk.

4) Users are lazy. They're so lazy that they won't actually stop to consider security, even when you throw up a dialog box that says "WARNING!" in big, bright red letters. To the user, dialog boxes are an annoyance that keeps them from doing what they want to do. For example, a lot of mobile code systems (for example, those running Active X controls when browsing the WWeb with Internet Explorer) will display a dialog box that tells you who wrote the code, and asks you if you really want to trust that person. Do you think anyone actually reads that stuff? Nope. Users just want to get to running the code, and will take the path of least resistance without considering the consequences.



Back to top


Principle 7: Promote privacy

Users generally consider privacy a security concern. You shouldn't do anything that could compromise the privacy of the user. And you should be as diligent as possible in protecting any personal information that a user gives you. You've probably heard stories about malicious hackers being able to access entire customer databases from the Web. It's also common to hear about attackers being able to hijack other users' shopping sessions, and thus gain access to private information. You should make every effort not to get yourself into this doghouse; you can quickly lose the respect of your customers if they think you handle privacy concerns poorly.



Back to top


The privacy/usability conundrum

Maintaining privacy can often be a trade-off with usability. For example, you're better off deleting credit card numbers as soon as you use them. That way, even if your Web site is broken into, you're not storing anything valuable long-term. Users hate that solution, though, because it means they have to type in their credit card data every time they want to buy something. It makes the convenience of "one-click shopping" impossible.

The only solution here is to store the credit card information, but it's important to be very careful about this. You should never show the user his own credit card number, in case someone manages to get unauthorized access. A common solution is to show a partial credit card number, with some digits blacked out. This isn't a perfect solution, either. It's always best to keep the credit card number under lock and key; there's no reason to ever show it to the user.

We recommend asking for the issuing bank, and never revealing any part of the actual number once you get it. The next time the user wants to select a credit card, let him do it by bank. If he needs to change the number because he's obtained a new card, let him type in the information anew.

On the server side, you should encrypt the credit card number, then enter it into the database. Keep the key for the credit card number on a different machine (this requires decrypting and encrypting on a machine other than the one your database resides on). That way, if your database gets compromised, the attacker will still need to find the key, which requires breaking into another machine. Anything you can do to raise the bar will help.



Back to top


Secrets and lies

User privacy isn't the only kind of privacy you should consider. Malicious hackers tend to launch attacks based on information that's easily collected from your system. Services on your machine tend to give information about themselves that can help the attacker figure out how to break in. For example, the Telnet service tends to give the operating system name and version.

So how can you avoid giving out more information than necessary? First, you should be using a firewall to block unnecessary services, so that attackers can't obtain additional information from them. Second, whether you're protected by a firewall or not (defense in depth, remember?), you should try to remove all information of this nature from your software. You can change the telnet login to conceal operating system specs.

In fact, why not lie about this sort of information? It can't hurt to send a potential attacker on a wild goose chase by advertising your Linux box as a Solaris machine; remote Solaris exploits generally won't get someone onto a Linux box. The attacker might give up in frustration long before figuring out that you lied.

Leaving any sort of information around on your system can help potential attackers. Instead, you should do everything in your power to deter them. If you're using Rijndael as an encryption algorithm, it can't hurt to claim you're actually using Twofish. Both algorithms are believed to provide similar levels of cryptographic security, so there's probably no harm here.

Attackers collecting information from your environment can obtain all sorts of subtle information. For example, known idiosyncrasies of different Web server software can quickly tell you what software a system runs, even if the software is modified to not report its version. Such information channels are called covert channels, because they're not obvious. Usually, it's impossible to close up every covert channel in a system. This is probably the most difficult security issue to identify in a system. When it comes to privacy, your best strategy is to try to identify the most likely covert channels, and use them to your advantage by sending your potential attackers on a wild goose chase.



Back to top


Next time

In our next installment, we'll finish up our list of principles with three more. First, we'll examine why you shouldn't expect to be able to hide secrets in our systems, at least not without great effort. Second, we'll learn that it's important to be wary of extending trust to anyone, including ourselves. Third, we'll see that when we do need to trust, there's often good reason to follow the herd.



Resources

  • The Design of Everyday Things, by Don Norman, March 1990, Doubleday Books (ISBN: 0385267746).

  • Usability Engineering, by Jakob Nielson, September 1994, Morgan Kaufmann Publishers (ISBN: 0125184069)

  • Part 1 of this series emphasizes the importance of reinforcing the weakest -- and most susceptible -- parts of your system (Principle 1).

  • Part 2 focuses on defense in depth (Principle 2) -- which advocates the use of multiple defense strategies -- and secure failure (Principle 3) -- the notion that system failure is not necessarily the same as system vulnerability.

  • Part 3 emphasizes controlling access through least privilege and compartmentalization (Principles 4 and 5, respectively).

  • Check out John Viega's article "The Myth of Open Source Security" at OpenSourceIT/EarthWeb.

  • In a previous developerWorks article, "Make your software behave: Assuring your software is secure", Gary and John lay out their five-step process for designing for security.

  • Cigital is a leading authority on software risk management -- check out their site.

  • The developerWorks columns by Gary and John have been updated and expanded in the book Building Secure Software, which also includes plenty of new material. Pick up a copy today -- your users will thank you.


About the authors

Gary McGraw is the vice president of corporate technology at Cigital (formerly Reliable Software Technologies) in Dulles, VA. Working with Consulting Services and Research, he helps set technology research and development direction. McGraw began his career at Cigital as a research scientist, and he continues to pursue research in software engineering and computer security. He holds a dual Ph.D. in Cognitive Science and Computer Science from Indiana University and a B.A. in Philosophy from the University of Virginia. He has written more than 40 peer-reviewed articles for technical publications, consults with major e-commerce vendors including Visa and the Federal Reserve, and has served as principal investigator on grants from Air Force Research Labs, DARPA, National Science Foundation, and NIST's Advanced Technology Program. He can be reached at gem@cigital.com.


John Viega is a senior research associate, Software Security Group co-founder, and senior consultant at Cigital. He is the principal investigator on a DARPA-sponsored grant for developing security extensions for standard programming languages. John has authored over 30 technical publications in the areas of software security and testing. He is responsible for finding several well-publicized security vulnerabilities in major network and e-commerce products, including a recent break in Netscape's security. He is also a prominent member of the open source software community, having written Mailman, the GNU Mailing List Manager, and, more recently, ITS4, a tool for finding security vulnerabilities in C and C++ code. Viega holds an M.S. in Computer Science from the University of Virginia. You can contact him at viega@cigital.com.




Rate this page


Please take a moment to complete this form to help us better serve you.



 


 


Not
useful
Extremely
useful
 


Share this....

digg Digg this story del.icio.us del.icio.us Slashdot Slashdot it!



Back to top