- Validate input. Validate inputs from all untrusted data sources. Proper input validation can eliminates the vast majority of software vulnerabilities. Be suspicious of most external data sources, including command line argument, network interfaces, environmental variables, and user controlled files .
- Heed compiler warnings. Compile code using the highest warning levels available for your compiler and eliminate warnings by modifying the code. Use static and dynamic analysis tools to detect and eliminate additional security flaws.
- Architect and design for security policies. Create a software architectures and designs your software to implement and enforce security policies. For example, if your system requires different privileges at different time, consider dividing the system into distinct intercommunicating subsystems, each with an appropriate privilege sets.
- Keep it simple. Keep the design as simple and small as possible . Complex designs increase the likelihood that error will be made in their implementation, configuration, and use. Additionally, the effort required to achieve an appropriate level of assurance increases dramatically as security mechanisms become more complex.
- Default deny. Base access decisions on permission rather than exclusions. This means that, by default, access is denied and the protection scheme identifies condition under which access is permitted.
- Adhere to the principle of least privilege. Every process should execute with the the least set of privilege necessary to complete the jobs. Any elevated permission should be held for a minimum time. This approach reduces the opportunities an attacker has to execute arbitrary code with elevated privileges.
- Sanitize data sent to other systems. Sanitize all data passed to complex subsystems such as command shell, relational database, and commercials off-the-shelf (COTS) components. Attackers may be able to invoke unused functionality in these component through the use of SQL, commands, or other injection attacks. This is not necessarily an input validation problems because the complex subsystem being invoked does not understand the context in which the call is made. Because the calling processes understand the contexts, it is responsible for sanitizing the data before invoking the subsystem.
- Practice defense in depth. Manage risk with multiple defensive strategies, so that if one layer of defense turns out to be inadequate, another layer of defense can prevents a security flaw from becoming an exploitable vulnerability and/or limit the consequences of a successful exploit. For examples, combining secure programming techniques with secure runtime environments should reduce the likelihood that vulnerabilities remaining in the code at deployment time can be exploited in the operational environment [Seacord 05].
- Use effective quality assurance techniques. Good quality assurance techniques can be effective in identifying and eliminating vulnerabilities. Fuzz testing, penetration testing, and source code audits should all be incorporated as part of an effective quality assurance program. Independents security reviews can lead to more secure systems. External reviewer bring an independent perspective; for example, in identifying and correcting invalid assumptions.
- Adopt a secure coding standard. Develop and/or apply a secure coding standard for your targets development language and platform.
Take your time to comment on this article.