Implementing a prefix for cookies introduces security measures in a way that renders the cookie ineffective in an insecure environment. This strategy enhances the visibility of the problem for developers. While an operational yet insecure cookie might go unnoticed until the next penetration test, a non-functional cookie will promptly trigger an investigation.
Functional Cookie Prefixes
Assigning a distinct name to a cookie grants it specific security attributes, a concept I previously discussed in my article on Securing Cookies with Cookie Prefixes. Cookies that commence with __Host-
must adhere to the following criteria:
- Set by an HTTPS site.
- Flagged as secure, ensuring they are only accessible to HTTPS sites.
- Not attached to a specific domain name. Interestingly, omitting a domain is more secure than specifying one.
- Path set to /, resulting in a singular canonical cookie for the entire site.
If an application attempts to set a __Host-
cookie that doesn’t adhere to these rules, the cookie won’t be established.
Cookie prefixes not only bolster cookie security but also have another significant impact: they transform misconfigurations into glaring functional issues.
Consider the scenario where a developer inadvertently removes the "Secure"
attribute from a session cookie. In the absence of cookie prefixes, the application continues to function without disruptions. While the cookie becomes less secure, no alarm bells are set off. The issue might only surface during the next penetration test.
However, with cookie prefixes in place, the application comes to a halt immediately. Users are unable to log in since their browsers refuse to store the session cookie. The bug responsible for removing the "Secure"
attribute is caught before even making it to the production stage.
This is an intriguing secure-by-default feature that not only enhances security but also simplifies the task of configuring cookies securely. If it functions at all, it is configured correctly.
Extending Secure by Default
Can we apply the same principle in other scenarios? Can security bugs be transformed into functional bugs to prevent security vulnerabilities?
CSRF Token Verification
When forms utilize random tokens to safeguard against CSRF attacks, these tokens should be validated upon form submission. If this validation is skipped, the application will continue to function, but it won’t be susceptible to CSRF attacks.
The framework could label the form as “dirty” and hinder its processing until the CSRF verification renders it “clean.” However, I believe this doesn’t offer a significant advantage over the framework directly checking the CSRF token.
Authorization Checks
Forgetting to apply the [Authorize]
attribute to a specific method renders it publicly accessible. While it continues to operate functionally, the security issue goes unnoticed by the developer.
A more effective solution is to render the method inaccessible altogether. Deny-by-default is often the appropriate approach, and it’s unfortunate that not many frameworks embrace it. Shifting the authorization layer to grant access instead of denying it ensures that misconfigurations quickly become evident when a page becomes inaccessible to all.
Disabling MIME Type Sniffing
The X-Content-Type-Options: nosniff header compels the browser to give more weight to Content-Type headers. This also breaks pages that possess incorrect content types or lack a content type altogether. While such bugs are relatively rare, enabling this header is virtually cost-free and ensures that these issues are identified early on.
Disrupting application functionality in the absence of a security measure prompts swift recognition of security concerns. This approach might seem counterintuitive, as it transforms a minor problem into a major one. However, when basic functionality testing is in place, this strategy prevents issues from reaching production without detection.