AD2014: DoNotDisableStackProtectionForFunctions¶
Summary¶
| Property | Value |
|---|---|
| ID | AD2014 |
| Name | DoNotDisableStackProtectionForFunctions |
| Category | Security |
| Severity | Warning |
| Applies to | PE (Windows) with PDB files |
Description¶
Application code should not disable stack protection for specific functions using #pragma strict_gs_check(off), #pragma runtime_checks, or __declspec(safebuffers). These mechanisms bypass the security provided by /GS.
How It Works¶
The rule examines:
- PDB compilation flags for disabled security checks
- Command lines for
/GS-flags - Compiland information indicating security check overrides
Why This Matters¶
Disabling stack protection for specific functions creates precisely-targeted vulnerabilities that attackers actively seek out. A single unprotected function in an otherwise-hardened application becomes the focus of exploitation attempts.
The Targeted Attack Surface¶
When /GS is selectively disabled:
#pragma strict_gs_check(off)
void parse_network_data(char *input, size_t len) {
char buffer[1024];
// ... buffer overflow here becomes easily exploitable
}
#pragma strict_gs_check(on)
An attacker who discovers this function will: 1. Focus all exploitation efforts on this specific entry point 2. Exploit it trivially since there's no cookie check 3. Bypass the application's other security measures
Why Developers Disable Protection¶
Common (usually misguided) reasons:
| Reason Given | Reality |
|---|---|
| "Performance" | /GS overhead is <1%, usually unmeasurable |
| "Compiler warnings" | Fix the code, don't disable protection |
| "Legacy compatibility" | Refactor incrementally |
| "Won't be exploited" | Attackers specifically look for these |
Attack Economics¶
Selective disabling is worse than global disabling:
| Configuration | Attacker Strategy |
|---|---|
| /GS globally enabled | Must bypass cookies everywhere |
| /GS globally disabled | Many attack vectors, but obvious in audits |
| Selective /GS- | Target specific functions, hidden from quick audits |
Detection Challenges¶
Selective disabling is hard to detect in code review:
#pragmastatements may be in distant header files__declspec(safebuffers)doesn't obviously mean "insecure"- Per-function compiler flags require build system analysis
Real-World Examples¶
Security researchers have found critical vulnerabilities in functions with disabled stack protection:
- Network parsers: Developers disabled /GS for "performance" in hot paths
- Cryptographic code: Misunderstanding led to disabling in sensitive functions
- Legacy wrappers: Old code grandfathered in without protection
The Safebuffers Problem¶
__declspec(safebuffers) was intended for functions the developer "knows" are safe:
In practice: - Developers overestimate their code's safety - Code changes over time - Future maintainers may not understand the implications
Defense in Depth Failure¶
Stack protection is one layer of defense. Removing it for any function: - Eliminates that protection layer for that attack surface - May cascade if the function is called by other vulnerable code - Reduces overall security posture
Resolution¶
Remove #pragma strict_gs_check(off)¶
// Bad
#pragma strict_gs_check(off)
void vulnerable_function() {
char buffer[100];
// ...
}
#pragma strict_gs_check(on)
// Good - remove the pragma entirely
void secure_function() {
char buffer[100];
// ...
}
Remove __declspec(safebuffers)¶
Remove /GS- from Command Line¶
Check your build scripts for /GS-:
Check Individual Source Files¶
Some files may have /GS- in their properties:
- Right-click source file → Properties
- C/C++ → Code Generation
- Ensure "Security Check" is not "Disable (/GS-)"
When to Suppress¶
This rule may be suppressed for:
- Performance-critical paths: After security review confirms safety
- Assembly interop: Functions that don't use C stack layout
- Leaf functions: Functions with no buffers and no calls
- Documented exceptions: With explicit security review
Caveats¶
- Sometimes disabled for compatibility with inline assembly
- May be disabled in legacy code for performance
- Third-party libraries may disable protection
Safe Alternatives¶
If you're disabling /GS for performance, consider:
- Profiling first: Is
/GSactually the bottleneck? - Restructuring: Move buffers to non-critical functions
- Stack-allocated arrays: Replace with heap allocation
- Compiler optimization: Modern compilers optimize
/GSwell
Example Review Process¶
Before suppressing this rule:
- ✅ Function has no stack buffers
- ✅ Function makes no calls
- ✅ Function doesn't take user input
- ✅ Security team has reviewed
- ✅ Documented in code comments
Related Rules¶
- AD2011: EnableStackProtection
- AD2012: DoNotModifyStackProtectionCookie
- AD2013: InitializeStackProtection