Because some people like lists, here is a list of the top 10
recommended, language-neutral, secure coding practices (adopted from https://www.securecoding.cert.org/confluence/display/seccode/Top+10+Secure+Coding+Practices).
1.
Validate
input. As mentioned in my first security blog post, validating input can
eliminate the vast majority of software vulnerabilities. External data sources
you are using, e.g. pulling from databases, using APIs, etc., have the
capability of having malformed objects or “inappropriate” syntax designed to
break your system.
2.
Use
compiler warnings. When using compiled code (as opposed to interpreted code
like Python), ensure the compiler is set to generate the highest warning levels
and don’t ignore the warnings when compiling. By eliminating the warnings, you
are ensuring that security vulnerabilities don’t exist in your code, to the
best of your ability.
3.
Design
based on security policies. Develop your software architecture and develop
the code base around established security policies. For example, design your
system to have independent subsystems that can communicate with each other;
each subsystem has a different privilege level so the highest privilege isn’t
being used all the time. A similar example of this is that Windows XP and older
versions defaulted to giving each user administrator privileges, making it easy
for malware to execute.
4.
KISS (Keep It Simple, Stupid). The more
complex you design something, the more likely errors and vulnerabilities will
creep in. If your programming language allows for subroutines, subprocesses,
modules, etc., then use them to break up the program into smaller parts. It is
easier to troubleshoot and debug these smaller sections than try to work with a
monolithic program.
5.
Deny by
default. When setting permissions, assume access is denied until proven
otherwise. Also, ensure that conditions are identified for when access is
permitted.
6.
Use the
concept of least privilege. Much like #5 above, every process should be
executed with the minimum privileges required to complete the job. If a process
has to have a higher level of access, that access should be removed as soon as
possible. This removes many of the avenues malicious attacks can use for
privilege escalation.
7. Sanitize data transfers. When passing
data to other subsystems, such as databases, other programs, command shells,
etc., sanitize the data first. Unused functionality within these other systems
can be attacked through a number of vectors. Sanitizing your data can remove some of these
vectors, as your program knows the context of the data transfer; the called
system doesn’t know anything about the transfer and will accept whatever it is
given.
8. Practice defense in depth. Use multiple
defensive measures so attacks have to circumvent a variety of countermeasures
in order to run. For example, use a sandbox environment (like a virtual
machine) when testing unknown code to minimize the risk of damaging your
system.
9. Make use of quality assurance testing.
Good QA can identify and remove vulnerabilities. When possible, have someone
else look at your code; the programmer may become so used to looking at the
code that he or she may miss something obvious. Automated tools can quickly
find common errors while audits can track frequent problems and provide better
education.
10. Create a secure coding standard.
Develop and implement a secure standard for programmers, taking into
consideration the programming language(s) used and the target platforms.
11. Define security requirements. Identify
security requirements early in the development cycle and, whenever changes are
made to the development plan, ensure the changes are vetted against the
requirements.
12. Use threat modeling. Anticipate
possible threats to the software and develop mitigation strategies to address
these threats. Identify key assets of the software and system, decompose the
application, categorize threats, and then rate the threats.
No comments:
Post a Comment