If you’re diving into cybersecurity, especially binary exploitation, you’ve probably come across stack canaries. They’re one of the many security measures designed to prevent stack-based buffer overflows, a common attack technique used by hackers to take control of a system.
But are stack canaries foolproof? Not exactly. While they make exploitation harder, they aren’t invincible.
What Are Stack Canaries?
Think of a canary in a coal mine—a small bird miners used to detect deadly gases. If the bird stopped singing, it was a warning sign that something was wrong. Stack canaries work in a similar way.
They are random values (or "canary values") placed between the function’s saved return address and the local variables on the stack. Their job? To detect if a buffer overflow has occurred. If an attacker tries to overwrite data on the stack, the canary value changes.
When the program checks this value before returning, it notices the change and terminates execution to prevent the attack.
How Stack Canaries Work
- Before a function starts executing, a random canary value is placed on the stack.
- During execution, if a buffer overflow happens, it would have to overwrite this canary value to reach the return address.
- Before returning from the function, the program checks if the canary value has changed.
- If the canary is modified, the program immediately crashes, preventing code execution.
Do Stack Canaries Prevent Overflow?
Yes and no. Stack canaries prevent certain types of buffer overflow exploits, but they don’t eliminate the threat entirely.
Here’s what they do well:
✔️ They stop simple buffer overflows where an attacker blindly overwrites data.
✔️ They make return address overwrites more difficult.
✔️ They increase the difficulty of exploitation by requiring additional steps to bypass.
But here’s where they fall short:
❌ They don’t stop overflows that don’t touch the canary (e.g., modifying function pointers).
❌ If an attacker leaks the canary value, they can overwrite it without breaking it.
❌ Canaries don’t protect heap-based overflows, only stack-based ones.
So while they’re a solid layer of defense, relying only on stack canaries is a mistake.
Stack Canaries in Action
Let’s walk through a simple C program that demonstrates how stack canaries detect buffer overflows.
🚀 The Vulnerable Code
Here’s a basic program that contains a buffer overflow vulnerability:
#include <stdio.h>
#include <string.h>
void vulnerable_function() {
char buffer[16];
printf("Enter input: ");
gets(buffer); // Unsafe function
}
int main() {
printf("Running secure function...\n");
vulnerable_function();
printf("Function executed successfully.\n");
return 0;
}
✅ What’s happening here?
- The function vulnerable_function() allocates a small buffer of 16 bytes.
- The gets() function is used to take user input without checking the input length, making it vulnerable to a buffer overflow.
- If the user enters more than 16 characters, it overwrites adjacent memory, potentially corrupting the return address.
🚨 Why is this dangerous?
- An attacker could overwrite the return address and execute malicious code.
{{cool_component}}
Are Stack Canaries Vulnerable?
Short answer? Yes.
Stack canaries are not a perfect defense mechanism. While they make buffer overflows harder to exploit, attackers have developed ways to bypass them. Here’s why stack canaries are vulnerable:
1. Canary Leaks
- If an attacker can read memory (using vulnerabilities like format string attacks or information disclosure bugs), they can find out the canary value.
- Once they know the canary, they can overwrite the stack without breaking it, rendering the protection useless.
2. Non-Terminating Overflows
- Some buffer overflows don’t need to overwrite the return address.
- Instead, they overwrite adjacent function pointers, long jumps, or structured exception handling (SEH) pointers—bypassing the canary completely.
3. Partial Overwrites
- Instead of overwriting the full return address, an attacker might modify only a single byte or two, keeping the canary intact while still achieving control over execution.
4. No Protection for Other Vulnerabilities
- Heap overflows, use-after-free exploits, and race conditions aren’t affected by stack canaries.
- If an attacker combines different types of vulnerabilities, they can sidestep canary-based protections.
In short, stack canaries slow down attacks, but they don’t make a system unhackable.
Bypassing Stack Canaries
Now for the fun part—how to overcome stack canaries. Attackers have several techniques to defeat them. Here’s how they do it:
1. Canary Leaking
- Attackers use information disclosure vulnerabilities to read memory and extract the canary value.
- Common techniques include format string vulnerabilities, memory leaks, or even brute force in some cases.
- Once they know the canary, they can overwrite it correctly to maintain execution flow.
2. Jumping Over the Canary
- Instead of overwriting the return address directly, attackers overwrite function pointers or exception handlers.
- This completely bypasses the need to modify the canary while still achieving remote code execution.
3. Partial Overwrite Attacks
- If an attacker can only overwrite a few bytes, they can change function behavior without touching the canary.
- A common trick is overwriting the least significant byte of a pointer to redirect execution.
4. Heap-Based Attacks
- Since stack canaries only protect the stack, an attacker might use a heap overflow or use-after-free exploit instead.
- By corrupting heap metadata, they can gain control over execution without dealing with the canary.
5. Brute Force (Rare, but Possible)
- In some scenarios (like 32-bit systems with weak randomization), attackers can brute force the canary value.
- If a crash doesn’t result in termination, they can guess the value bit by bit.
While none of these techniques are foolproof, they show that bypassing stack canaries is possible with the right conditions.
How to Test If a Binary Uses Stack Canaries
Before exploiting or securing a binary, it’s useful to check whether stack canaries are enabled. Here’s how:
🔍 Check Using checksec
Install checksec if you haven’t already:
sudo apt install checksec # On Debian-based distros
Now, run:
checksec --format=long --binary vulnerable_binary
If stack canaries are enabled, you’ll see "Canary found" in the output:
[*] vulnerable_binary:
RELRO : Full RELRO
Stack Canary : Canary found
NX : NX enabled
PIE : PIE enabled
If stack canaries are disabled, the output will show "Canary not found".
✅ Why is this important?
- If stack canaries are enabled, attackers need to leak the canary value to bypass protection.
- If stack canaries are disabled, the binary is more vulnerable to simple buffer overflow exploits.
How to Defeat Stack Canaries (From a Security Perspective)
If you’re defending against buffer overflow attacks, relying on stack canaries alone isn’t enough. Here’s what you can do to improve security:
✅ Use Address Space Layout Randomization (ASLR)
- This makes memory addresses unpredictable, reducing the effectiveness of canary leaks.
✅ Implement Control Flow Integrity (CFI)
- CFI ensures that execution flow remains as intended, even if an attacker bypasses canaries.
✅ Enable Data Execution Prevention (DEP)
- This prevents execution of injected shellcode, even if an overflow happens.
✅ Use Stack Cookies with More Randomization
- Modern stack canaries include per-process and per-thread randomization to make brute force attacks impractical.
✅ Monitor for Information Leaks
- Since leaking the canary is the easiest bypass, preventing memory leaks is a high priority.
✅ Use Compiler-Based Protections (e.g., StackGuard, ProPolice, or Shadow Stacks)
- These add additional layers of protection to prevent various overflow techniques.
Stack canaries are useful, but a multi-layered security approach is always better.
Performance Overhead of Stack Canaries
While stack canaries improve security, they do have a small performance cost:
💡 Bottom Line: Stack canaries are a strong security measure, but they don’t cover all types of memory corruption and come with a small performance cost.
Conclusion
Stack canaries are a solid but imperfect defense mechanism. They do a good job of preventing basic buffer overflows, but they’re not invulnerable. Attackers have found ways to bypass stack canaries using memory leaks, function pointer overwrites, and even brute force.
So, do stack canaries prevent overflow? Yes, but not all overflows. The best way to stay secure is to combine canaries with ASLR, DEP, CFI, and other security measures to create a more robust defense.
Set a meeting and get a commercial proposal right after
Build your Multi-CDN infrastructure with IOR platform
Build your Multi-CDN infrastracture with IOR platform
Migrate seamleslly with IO River migration free tool.