 | 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.
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.
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!"
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 isnt
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.
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.
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.
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.
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
|  |