Good development leads to good security
Good application security is paramount in this day and age. With network security becoming better and better attackers are starting to look at applications to be the doorway into corporate networks. Good development can help make a system more secure or at least make it easier to spot the gaping holes that let your neighbor's teenager have some fun on a Sunday night. Before we get started I am not going to say anything like "coders need to code with security in mind" or anything like that my idea is this: good development practices impact a code-base in many ways and only one of them is saving your monitor from flying out the window ;).
There are many key ideas that I use to define good development:
Low cohesion - high coupling is found in many classic books (Code Complete, The Pragmatic Programmer, etc...) as the correct way to develop systems. This also helps in security by allowing us to only focus on a small part of the project instead of trying to keep too many things in our brain. Many security problems that I have seen have been caused when a huge class is written where variables are touched by many different methods that all do different things (i.e. a method to do driving and another method to do email).
The Smallest interface possible idea goes along with the previous point but it also ties into the security rule of only giving users the minimum access they need to do their job. If you give users the ability to modify variables that are used throughout a class it could have disastrous consequences that were never dreamed of. Anything that calls upon one class is considered a user in this case. Now, why does this matter if you are doing closed-source code that is only used in your specific corporation? Well, it also helps with development. By only giving users the ability to access only certain methods within an object you allow them to make fewer choices (as long as you don't make them create hacks to work with your code) and just like in usability the fewer choices users need to make the better.
Never trust any input (sanitize, sanitize, sanitize) yes, yes, yes, we have all seen this rule in secure coding documents. However, this also falls under a different term in programming and that is "programming by contract". A precondition (part of programming by contract) is a way to make sure the method is in a usable state before doing any work it is also a way to make sure values passed in are usable. For example a price for a product should be positive, if a malicious user tampers with the value or if someone just enters in a wrong value neither should be accepted. When accepting input from users we need to make sure nothing entered can meddle with our system by checking first and if needed sanitizing (i.e. removing any bad characters) we can then add in a safeguard by having a precondition on our "save", "display", etc.. methods to make sure nothing bad exists.
Don't display geek-speak errors to users falls more under usability but as developer's we have a responsibility to make things as easy for our users as possible. What I mean by "geek-speak errors" are errors that are returned straight from the compiler/interpreter or back-end system. So things like SQL errors or index out of range errors should be handled and a clear message letting the users know that something went wrong would be more appropriate. This helps the security of an application by not allowing attackers to see any error message that could help them. They might know that something went wrong but on what layer or what exactly happened they will not positively know.
The no public variables practice ties in with low coupling - high cohesion and smallest interface possible. If a calling program can directly access variables there is no way for you to make sure that the information in memory is ever safe. By only allowing accessor methods it will make for a single point that can be used to sanitize all input.
Make functions only long as they need to be and by that I mean they must only be five lines long....NOT. Lets all admit it as developers sometimes functions just need to be longer than can be kept on a single screen. The reason we want short methods for security reasons is to more easily find potential security issues. I have slogged through 2,000 line methods and trust me it is not pretty and prone to give developers nightmares :) as I am sure anyone else who has had the joy hell. So for the sake of security and the sanity of other developers keep your methods as short as they can be.
Reuse as many verified components as possible makes development quicker and easier to produce a secure system. By verified components I mean ones that have had a security audits done so that it is known to be secure against attacks. Components can mean anything from encryption algorithms to database abstraction layers.
KISS (Keep It Simple Stupid) is a great idea to remember when developing code it also allows for developers and auditors to go through the code and quickly understand and/or find bugs that could be there. Doing this has so many advantages that are talked about ad nauseum all over the net. However, very rarely is it talked about in terms of security. If someone has to wade through four libraries and three layers of indirection there is a bigger chance that security issues (and bugs) will be missed and it will just be harder to maintain. As with most things trying to keep a system simple yet useful is a lot of work.
Conclusion
There are many key advantages to following good coding practices including: easier maintenance, securer code and less headaches from banging your head. Good coding makes it easier to find potential bugs and allows for data to be trusted (after being sanitized of course). It is tough work to produce systems that follow these guidelines but that is why developers who do tend to be in higher demand than ones that just rush through like a bull in a china shop. There are many other ideas that go into coding than what I have addressed this article but personally I don't want to write a book for my first post :).
There are many key ideas that I use to define good development:
- Low cohesion - high coupling
- Smallest interface possible
- Never trust any input (sanitize, sanitize, sanitize)
- Don't display geek-speak errors to users
- No public variables
- Make functions only long as they need to be
- Reuse as many verified components as possible
- KISS (Keep It Simple Stupid)
Low cohesion - high coupling is found in many classic books (Code Complete, The Pragmatic Programmer, etc...) as the correct way to develop systems. This also helps in security by allowing us to only focus on a small part of the project instead of trying to keep too many things in our brain. Many security problems that I have seen have been caused when a huge class is written where variables are touched by many different methods that all do different things (i.e. a method to do driving and another method to do email).
The Smallest interface possible idea goes along with the previous point but it also ties into the security rule of only giving users the minimum access they need to do their job. If you give users the ability to modify variables that are used throughout a class it could have disastrous consequences that were never dreamed of. Anything that calls upon one class is considered a user in this case. Now, why does this matter if you are doing closed-source code that is only used in your specific corporation? Well, it also helps with development. By only giving users the ability to access only certain methods within an object you allow them to make fewer choices (as long as you don't make them create hacks to work with your code) and just like in usability the fewer choices users need to make the better.
Never trust any input (sanitize, sanitize, sanitize) yes, yes, yes, we have all seen this rule in secure coding documents. However, this also falls under a different term in programming and that is "programming by contract". A precondition (part of programming by contract) is a way to make sure the method is in a usable state before doing any work it is also a way to make sure values passed in are usable. For example a price for a product should be positive, if a malicious user tampers with the value or if someone just enters in a wrong value neither should be accepted. When accepting input from users we need to make sure nothing entered can meddle with our system by checking first and if needed sanitizing (i.e. removing any bad characters) we can then add in a safeguard by having a precondition on our "save", "display", etc.. methods to make sure nothing bad exists.
Don't display geek-speak errors to users falls more under usability but as developer's we have a responsibility to make things as easy for our users as possible. What I mean by "geek-speak errors" are errors that are returned straight from the compiler/interpreter or back-end system. So things like SQL errors or index out of range errors should be handled and a clear message letting the users know that something went wrong would be more appropriate. This helps the security of an application by not allowing attackers to see any error message that could help them. They might know that something went wrong but on what layer or what exactly happened they will not positively know.
The no public variables practice ties in with low coupling - high cohesion and smallest interface possible. If a calling program can directly access variables there is no way for you to make sure that the information in memory is ever safe. By only allowing accessor methods it will make for a single point that can be used to sanitize all input.
Make functions only long as they need to be and by that I mean they must only be five lines long....NOT. Lets all admit it as developers sometimes functions just need to be longer than can be kept on a single screen. The reason we want short methods for security reasons is to more easily find potential security issues. I have slogged through 2,000 line methods and trust me it is not pretty and prone to give developers nightmares :) as I am sure anyone else who has had the joy hell. So for the sake of security and the sanity of other developers keep your methods as short as they can be.
Reuse as many verified components as possible makes development quicker and easier to produce a secure system. By verified components I mean ones that have had a security audits done so that it is known to be secure against attacks. Components can mean anything from encryption algorithms to database abstraction layers.
KISS (Keep It Simple Stupid) is a great idea to remember when developing code it also allows for developers and auditors to go through the code and quickly understand and/or find bugs that could be there. Doing this has so many advantages that are talked about ad nauseum all over the net. However, very rarely is it talked about in terms of security. If someone has to wade through four libraries and three layers of indirection there is a bigger chance that security issues (and bugs) will be missed and it will just be harder to maintain. As with most things trying to keep a system simple yet useful is a lot of work.
Conclusion
There are many key advantages to following good coding practices including: easier maintenance, securer code and less headaches from banging your head. Good coding makes it easier to find potential bugs and allows for data to be trusted (after being sanitized of course). It is tough work to produce systems that follow these guidelines but that is why developers who do tend to be in higher demand than ones that just rush through like a bull in a china shop. There are many other ideas that go into coding than what I have addressed this article but personally I don't want to write a book for my first post :).
0 Comments:
Post a Comment
<< Home