6 ms·
Retguard: OpenBSD/Clang
- brynet 9y agoHere's a better mail archive link: https://marc.info/?l=openbsd-tech&m=150317547021396&w=2 https://marc.info/?l=openbsd-tech&m=150317547021396&w=2 EDIT: Thanks mods? :-)
- sctb 9y agoThanks, we've updated the link from https://marc.ttias.be/openbsd-tech/2017-08/msg00349.php https://marc.ttias.be/openbsd-tech/2017-08/msg00349.php to the original archive site.
- protomyth 9y agoI love the line: I spoke a lot with Todd Mortimer. Apparently I told him that I felt return-address protection was impossible, so a few weeks later he sent a clang diff to address that issue...
- nstott 9y agoI know right Strong opinions, loosely held
- jacquesgt 9y agoI feel like I’m missing something here. An infoleak is required to successfully ROP against ASLR (otherwise the attacker doesn’t know what to overwrite the return address with). Once an infoleak is available, the address of the stack can be leaked. I’m not really sure this does much beyond requiring attackers to modify their existing exploits.
- brynet 9y ago"ROP attack methods are impacted because existing gadgets are transformed to consist of '<gadget artifacts> <mangle ret address> RET'. That pivots the return sequence off the ROP chain in a highly unpredictable and inconvenient fashion."
- jacquesgt 9y agoI'm not seeing how it's unpredictable and inconvenient. It's predictable if the stack address can be leaked (via a frame pointer leak, for example). It doesn't seem that inconvenient. Instead of including the address of a gadget in the chain, include the gadget xor the leaked stack address. What's the unpredictable and inconvenient part that I'm not seeing?
- Mordak 9y agoYou have it - if a stack address can be leaked, and you can follow the control flow to figure out the difference between the address you leaked and the address you're going to be dumping your ROP chain into, then you can just xor the gadget address with the stack address, and then do the math to xor any down-chain gadgets with the calculated stack address if the gadgets you want to use happen to have this xor instruction injected into them. But you don't always have stack address leaks. Presently, in order to ROP you need (a) a leaked address to the space where your gadgets live and (b) the ability to write your ROP chain somewhere where the program will return into it. With this scheme, you now also need (c) the exact address where you are writing your ROP chain. Not all info leak vulnerabilities leak arbitrary memory of the attacker's choosing. If they did, stack canaries would be pretty useless. So for those cases where a stack address leak is unavailable, this raises the bar against ROP.
- syncopate 9y agoIt increases the complexity of the attack. Usually, stack cookies make ROP harder these days but guessing the cookie only has a complexity of 8*256 (on OpenBSD), but xor'ing the return address with another value does increase the complexity even more. And that might be good news for programs that use fork a lot (like nginx) and hence don't get a refresh for ASLR/stack cookies for every request (like e.g. sshd on OpenBSD does [which does does fork/exec to ensure ASLR/cookies are refreshed]).
- hexadecimated 9y agoPerhaps OpenBSD should consider randomizing the per-process stack canary value upon fork().
- syncopate 9y agoHow does that work? Should the kernel walk the stack to change all the saved cookie values of the forked copy? I doubt the kernel even knows where the saved cookie values are stored on the stack. Also, that would make fork quite slow, depending on how the deep the stack was when the fork happened.
- hexadecimated 9y agoThe post-fork canary value could be paired with the stack pointer at which it became valid. If not valid, the process could walk a linked list of pre-fork canary and stack pointer pairs, to find the correct value to use. Would be interesting to see the performance hit on such an approach.
- tedunangst 9y agoOr not. The stack canary is not the only random value reset upon exec.
- brynet 9y agoOpenBSD has been expanding the fork+exec model throughout its source tree, since the OpenSSH preauth work done by Damien Miller, many more followed. The list includes bgpd/ldpd/eigrpd/smtpd/relayd/ntpd/httpd/snmpd/ldapd and most recently slaacd & vmd. A few remain but are being converted as they are discovered.
- jnwatson 9y agoMicrosoft has a much more sophisticated control flow integrity mechanism called control flow guard https://msdn.microsoft.com/en-us/library/windows/desktop/mt637065(v=vs.85).aspx https://msdn.microsoft.com/en-us/library/windows/desktop/mt6.... LLVM also has an impressive set of CFI capabilities: https://clang.llvm.org/docs/ControlFlowIntegrity.html https://clang.llvm.org/docs/ControlFlowIntegrity.html. The proposal just sounds like higher entropy stack cookies.
- Mordak 9y agoI think the LLVM CFI options only apply to C++ programs? Microsoft's CFG is cool, but works on the other end to this - by protecting CALL instructions instead of RET. Stack cookies are similar, yes. This mechanism combines two ASLR-randomized values (the caller address and the stack address) to control program flow. Stack canaries use a constant random cookie per object file to detect stack smashing. Retguard raises the bar for successful ROP attacks, just as CFG raises the bar for function pointer corruption attacks. Full disclosure, I am the author of the clang diff that kicked this off. The appeal of this mechanism is that it is cheap enough to apply in every function, pollutes the ROP gadget space with instructions that permute the next return address, and requires attackers to have more information in order to kick off ROP chains (the address where they are writing their ROP chain). I know about some of the other stuff people are working on (CPI seems promising), and look forward to turning those things on when possible. Meanwhile, this mitigation is cheap, localized inside every function, and doesn't require any program modification in the vast majority of situations (programs that inspect stack frames without consulting the unwind info may have problems), so is fairly easy to turn on everywhere.
- busterarm 9y agoThe volume and quality of tools coming out of the OpenBSD community in recent years has been absolutely awe-inspiring. I'm presently able to do the entirety of my personal project work on the OS and I'm only a couple of tools from being able to do the same professionally. Keep it up, y'all.
- miaklesp 9y agoThis dude should choose a better font for his blog.
- busterarm 9y agoI hope you're kidding, but for the uninitiated: MARC, or marc.info, is the Mailinglist ARCive. You're reading email.
- RolfRolles 9y agoI also must be missing something. XORing the return address on the stack with the stack pointer is similar to other stack protection mechanisms. I forget the precise name of it, but I'm pretty sure one of the existing stack protection tools does exactly this? MSVC's /GS feature is similar but slightly different in that it XORs the return address with a random value initialized on module load. However, the claim that ROP is impacted seems a bit flimsy to me. After all, ROP only requires that the C3 (RET) or C2 xx yy (RETN YYXX) byte sequence be present at the end of it; these sequences do occur at the end of a function, but they also occur in other places (such as anywhere the byte C3 arises in compiled machine code). ROP tools are programmed to look for the C3/C2 XX YY sequences and do not know or care whether these sequences are at the end of a function. The post is claiming that by transforming the ends of functions, ROP will be affected; but given that it seems to makes no attempt to remove C3 and C2 bytes from elsewhere in the machine code, that ROP tools will in fact continue to work just fine. Basically the whole thesis of this patch seems to be that "existing stack protection methods will change function epilogues and therefore break ROP". I don't think it will have much of an effect on existing ROP tools. What am I missing?
- sebcat 9y agoYou need to hit the first ret in the vulnerable function to enter the ROP chain, and before that ret the value at the top of stack will be (de-)mangled. If the return address on the stack is overwritten by an attacker, it needs to be overwritten with a ROP gadget adjusted for the mangling.
- RolfRolles 9y agoYour comments only apply to exploitation of stack buffer overflows, which have largely been rendered extinct due to compiler-based strategies like this one. Exploiting, say, a use-after-free vulnerability still may require ROP but does not require corruption of a return address on the stack. Given that the proposed defense supposedly targets ROP in general and not exploitation of stack buffer overflows specifically, my points still stand.
- 9y ago
- hungryimitator 9y agoMaybe we seen this before? :) http://i.imgur.com/DW1dqnV.png http://i.imgur.com/DW1dqnV.png http://i.imgur.com/vZnpKwL.png http://i.imgur.com/vZnpKwL.png Seriously.. these projects should talk more about each others stuff..