Core Security Principles
- J.D. Meier, Alex Mackman, Michael Dunner and Srinath Vasireddy
Adopt the principle of least privilege.
Processes that run script or execute code should run under a least privileged account to limit the potential damage that can be done if the process is compromised. If a malicious user manages to inject code into a server process, the privileges granted to that process determine to a large degree the types of operations the user is able to perform. Code that requires additional trust (and raised privileges) should be isolated within separate processes.
The ASP.NET team made a conscious decision to run the ASP.NET account with least privileges.
Use defense in depth.
Place check points within each of the layers and subsystems within your application. The check points are the gatekeepers that ensure that only authenticated and authorized users are able to access the next downstream layer.
Don't trust user input.
Applications should thoroughly validate all user input before performing operations with that input. The validation may include filtering out special characters. This preventive measure protects the application against accidental misuse or deliberate attacks by people who are attempting to inject malicious commands into the system. Common examples include SQL injection attacks, cross-site scripting attacks, and buffer overflow.
Use secure defaults.
A common practice among developers is to use reduced security settings, simply to make an application work. If your application demands features that force you to reduce or change default security settings, test the effects and understand the implications before making the change.
Don't rely on security by obscurity.
Trying to hide secrets by using misleading variable names or storing them in odd file locations does not provide security. In a game of hide-and-seek, it's better to use platform features or proven techniques for securing your data.
Check at the gate.
You don't always need to flow a user's security context to the back end for authorization checks. Often, in a distributed system, this is not the best choice. Checking the client at the gate refers to authorizing the user at the first point of authentication (for example, within the Web application on the Web server), and determining which resources and operations (potentially provided by downstream services) the user should be allowed to access.
If you design solid authentication and authorization strategies at the gate, you can circumvent the need to delegate the original caller's security context all the way through to your application's data tier.
Assume external systems are insecure.
If you don't own it, don't assume security is taken care of for you.
Reduce Surface Area
Avoid exposing information that is not required. By doing so, you are potentially opening doors that can lead to additional vulnerabilities. Also, handle errors gracefully; don't expose any more information than is required when returning an error message to the end user.
Fail to a secure mode.
If your application fails, make sure it does not leave sensitive data unprotected. Also, do not provide too much detail in error messages; meaning don't include details that could help an attacker exploit a vulnerability in your application. Write detailed error information to the Windows event log.
Security is a concern across all of your application layers and tiers.
Remember you are only as secure as your weakest link.
If you don't use it, disable it.
You can remove potential points of attack by disabling modules and components that your application does not require. For example, if your application doesn't use output caching, then you should disable the ASP.NET output cache module. If a future security vulnerability is found in the module, your application is not threatened.