Maintain control over all inputs
Improper input validation is the number one killer of healthy software, so ensure input conforms to expectations. For example, an identifier that you expect to be numeric shouldn’t ever contain letters. Incorrect input validation can lead to vulnerabilities when attackers can modify their inputs in unexpected ways.
Maintain control over all outputs
Insufficient output encoding is the often-ignored sibling to improper input validation, but it is at the root of most injection-based attacks. When your program generates outputs to other components in the form of structured messages such as queries or requests, it needs to separate control information and metadata from the actual data. If available, use structured mechanisms that automatically enforce the separation between data and code.
Lock down your environment
Run your software in a restricted environment, using available security features to limit the scope of what your software can do to its host systems and adjacent networks. Even if an attacker manages to find and exploit a vulnerability, an environmental lockdown can limit what the attacker can do, reducing the overall severity of the problem and making the attacker work harder. In some cases, the lockdown may prevent the problem from becoming a vulnerability in the first place.
Assume your code can be read by anyone
When it comes to security, your code operates in a hostile environment. Attackers can analyze your software – even if it’s obfuscated – and figure out what’s going on. They can modify external components to ignore security controls. They can try any type of attack against every component in the system. If your code is distributed to your consumers, even better – they can run your software and attack it in their own environment, forever, without you ever knowing about it.
Use industry-accepted security features
Tricky after Heartbleed, but investigate which of the security algorithms available is the strongest for cryptography, authentication, and authorization, and use it by default. Use well-vetted, industry-standard algorithms that are currently considered to be strong by experts in the field, and select well-tested implementations. Stay away from proprietary and secret algorithms.
Play it safe
Use libraries and frameworks that make it easier to avoid introducing weaknesses. Solid, security-relevant libraries may save development effort and establish a well-understood level of security. If a security problem is found, the fix might be local to the library, instead of requiring wholesale changes throughout the code. With experience, you may go custom.
Security end to end
Integrate security into the entire software development lifecycle.
Weaknesses and vulnerabilities can only be avoided when secure development practices are integrated into all phases of the software life cycle, including (but not limited to) requirements and specification, design and architecture, implementation, build, testing, deployment, operation, and maintenance. Create a software security group.
There are no shortcuts
There is no single tool, technique, or process that will guarantee that your software is secure. Each approach has its own strengths and limitations. Approaches include automated static code analysis, manual static code analysis, and automated dynamic code analysis.
Sometimes access works
Allow locked-down clients to interact with your software. If a user has a locked-down client that does not support all the features used by your application, consider allowing that user some access, instead of completely denying access, which may force the user to degrade the client’s security stance. This may help protect users and slow the propagation of malware.
With the Heartbleed vulnerability on people’s minds we thought it a good time to revisit the CWE/SANS Institute’s advice for eliminating or reducing the severity of the leading mistakes developers make when creating software. Follow these tips and your code will be more secure. For more detail click here. All images from Shutterstock