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!
- Code audit
- High Quality/high quantity/high utilization randomization
- Safer C library functions
- Peer review of all code committed
yeah, it's dull. But it's Really Important.
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.
- #ITisTerrible
If you can't prevent exploits, mitigate 'em!
- Fail fast, early
- Fail closed
- Stabilty and "robustness" is not a virtue!
"If memory has been overwritten, how does one continue?"
Mitigations
"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"
-- Theo de Raadt
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!
More
- 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.
- pipelining
- Jump Prediction
Complexity is the enemy of quality, poor quality leads to security
problems.
(...and security was probably never even thought
about)
This ain't gonna be good.
Problem with pipelines
inst1
if SSN = B goto GG
inst2
inst3
inst4
GG: inst5
inst6
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.
Yet.
but for now... it looks like hyperthreading is a baaad idea. Just don't
use it.
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
RETGUARD
- 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
be removed!
- Small, but definite performance and size costs.
/