OpenBSD Exploit Mitigations
Who am I?
- Nick Holland, EE, Unix Admin
- Working with OpenBSD since about 1998
- Many years as a ..uh.. "contributor" to the project
- Really, this is not my area of expertise!
- https://www.openbsd.org/papers.html for much more detailed and accurate info.
step 1: Avoid exploits!
The exploit that can't happen doesn't need to be mitigated!
yeah, it's dull. But it's Really Important.
- Code audit
- High Quality/high quantity/high utilization randomization
- Safer C library functions
- Peer review of all code committed
But shit happens...
- New exploit techniques discovered
- Mistakes slip through
- Not all tools are written with OpenBSD coder-level of care
- Virtually no apps are written with the OpenBSD level of care.
If you can't prevent exploits, mitigate 'em!
"If memory has been overwritten, how does one continue?"
- Fail fast, early
- Fail closed
- Stabilty and "robustness" is not a virtue!
"Mitigations are inexpensive tweaks which increase the difficulty
of performing attack methods:
- Low impact on normal operation
- Huge impact during attack scenario operation
Also, they act as a pressure towards robustness in software.
When a defect is detected, goal is to Fail Closed"
Some OpenBSD Mitigation techniques
- Privilege Separation (most major subsystems)
- Privilege Revocation (ping, traceroute)
- Stack Protection (propolice, retguard)
- W^X (now hard-enforced unless app is run from a wxallowed flagged FS)
- Randomize, Randomize, RANDOMIZE!
- malloc has over 20 hardenings.
- Some low-cost, always enabled.
- Some high cost.
- Libraries Order Randomizations
- Kernel Address Randomized Link (KARL)
- Pledge: Subset POSIX operations for an app.
- Unveil: "Unveil parts of a restricted file system view"
But things keep getting more interesting.
CISC -> RISC -> modern procs
- Complicated Instruction Set Computers -- CPUs with sophisticated instructions, often doing complex tasks in one operation. Classic: VAX.
- Many clock cycles per instruction.
- Variable instruction timing
- Often horribly inefficient
- Reduced Instruction Set Computers -- CPUs with simple, fast executing instructions
- Often approach one instruction per clock cycle
- Typically large number of registers
- But ... primative instructions
- Compiler to the rescue. Or not.
- Modern CPU -- Complicated, powerful instructions, with a throughput
approaching that of a RISC system.
- Jump Prediction
Complexity is the enemy of quality, poor quality leads to security
(...and security was probably never even thought
This ain't gonna be good.
Problem with pipelines
if SSN = B goto GG
What if the jump is taken, but inst2-inst4 is already in the pipeline?
Here's where magic happens.
Realistically, we don't know where this is going to end up going.
but for now... it looks like hyperthreading is a baaad idea. Just don't
Nick's Rule of Don't Run Bad Code on Your Computer still applies.
And that's not changed by virtualization.
Return Oriented Programming (ROP)
- Chunks of...code, not necessiarily intended as code.
- Ending with a "return" from subroutine code.
- Each chunk of code that actually does something useful is a "gadget"
- Stuff a set of bogus "return" addresses on the stack, and you can
create a program.
- Like writing a ransom note using newspaper clippings.
Dealing with ROP
- Randomizing memory layout helps
- Remove unintended returns
- Make intended returns hard to (ab)use
- every function has a random cookie.
- on calling a function, compute cookie ^ return address, store.
- on return from function, compute saved value ^ return address, compare to coookie, and abort if wrong.
- ... a better stackprotector than Propolice.
- On alligned instruction systems (ARM64), ALL gadgets can
- Small, but definite performance and size costs.