![]() |
|
|||||||||||||||
|
||||||||||||||||
|
| Software security principles: Part 1 | ||||
In this series of articles, Gary and John offer the 10 most important points to keep in mind when designing and building a secure system. This installment explores the importance of reinforcing the weakest -- and most susceptible -- parts of your system. And it's worth noting that the problem isn't necessarily a weakness in the software. Software security is certainly a vast, complex topic. One of the biggest challenges to the field is that new types of security flaws that completely defy all known patterns are always possible. For a good example, we need look no further than cryptography, where it is relatively easy to build algorithms that resist the best-known attacks on other algorithms. Protecting against unknown attacks is a far greater challenge. Moreover, there is plenty of room for new attacks to emerge; every few years a significant one does. Another serious challenge is that just keeping up with known problems is difficult, because there are so many of them. Sure, it's not practical to protect against every possible type of attack. However, we can avoid being overwhelmed with the large volume of knowledge by using a good set of principles when designing and building software. In the next several installments we will present 10 principles for developing secure software. The goal of these principles is to isolate the most important points you should keep in mind when designing and building a secure system. Following these principles should help you avoid lots of common security problems. Of course, this set of principles will not be able to cover every possible flaw that could show up. We don't pretend that any set of principles could; we are just trying to follow the "90/10" rule -- avoid 90% of the potential problem by following 10 simple rules. Today we'll start out with the first, which is to focus energy on the weakest parts of your system. Principle 1: Securing the weakest link It's probably no surprise to you that attackers tend to go after low-hanging fruit. If they target your system for whatever reason, they're going to take the path of least resistance. That means they'll try to attack the parts of the system that look weakest, and not the parts that look strong. Even if they spend an equal effort on all parts of your system, they're far more likely to find problems in the parts of your system most in need of improvement. This intuition is widely applicable. There's generally more money in a bank than a convenience store, but which one is more likely to be held up? The convenience store, of course. Why? Because banks tend to have much stronger security precautions; convenience stores are much easier targets. Let's say that you own an average bank and an average convenience store. Would it be more cost-effective for you to add extra doors to your vault, and double your security staff, or to take the same money and hire security officers for your convenience store? The bank probably already keeps tellers behind bulletproof glass, and has cameras, security guards, a locked vault, and doors with electronic passwords. In contrast, the convenience store probably has a less sophisticated camera system, and little else. If you're going to invest in the security of any one part of your financial empire, the convenience store would be the best choice, because it's at much greater risk. This principle has obvious applications in the software world, but most people don't pay any attention. In particular, cryptography is seldom the weakest part of a system. Even if you use SSL-1 with 512-bit RSA keys and 40-bit RC4 keys, which are considered incredibly weak cryptography, an attacker can probably find much easier ways in. Sure, it's breakable, but doing so still requires a large computational effort. If the attacker wants access to the data that travels over the network, then they'll probably target one of the endpoints, try to find a flaw like a buffer overflow, and then look at the data either before it gets encrypted or after it gets decrypted. All the cryptography in the world can't help you if there's an exploitable buffer overflow -- and buffer overflows abound in C code. For this reason, while cryptographic key lengths can certainly have an impact on the security of your system, they aren't all that important in most systems, where far greater things are wrong. Similarly, attackers generally don't attack a firewall itself, unless there's a well-known vulnerability in the firewall. Instead, they'll try to break the applications that are visible through the firewall, because they're generally much easier targets. Identifying what you perceive to be the weakest components of a system should be easy if you perform a good risk analysis. You should address what seems to be the most serious risk first, instead of the risk that seems easiest to mitigate. Once it's clear that some other component is a bigger risk, you should focus your efforts elsewhere. Of course, you could apply this strategy forever, because security is never a guarantee. You need some stopping point. You should stop when all your components appear to be within the threshold of acceptable risk, by whatever metrics you define in your software engineering process. Social engineering: A common weak link Even if they do ask questions to authenticate the person on the other end of the phone, what are they going to ask? Birth date? Social Security number? Mother's maiden name? All of that information is easy to obtain if you know your target. This problem is a common one, and is incredibly difficult to solve. One good strategy is to limit the capabilities of technical support as much as possible. For example, you might choose to make it impossible to change a password; if you forget it, then you must create another account. Of course, that particular example is generally not a good solution, because it is a huge inconvenience for users. The following elaborate scheme is a better example. Before deploying the system, a large list of questions is composed (say, no fewer than 400 questions). These questions should be generic enough that any one person should be able to answer the question. However, the correct answer to any single question should be pretty difficult for anyone other than the respondent to guess. When the user creates an account, we select 20 questions from the list, and ask the user to answer six of them for which he has answers, and is most likely to give the same answer if asked again in two years. Here are some potential sample questions:
When someone forgets their password, and calls technical support, technical support can only refer them to a Web page. The user is given three questions from the list of six, and must answer two correctly. If the user answers two correctly, then we do the following:
We should probably only allow any one person to authenticate in this way a small handful of times (say, three). The result of this scheme is that users can still accomplish what they need to when they forget their passwords, but tech support is protected from social engineering attacks. Next time
| ||||||||||||||||||||||||||||||||||||||||||||||||
| About IBM | Privacy | Terms of use | Contact |