Given that essentially no CPUs today support CET and given that CPUs remain deployed for perhaps 10 years, even more considering that CPU performance has plateaued, isn't there a moral imperative to mitigate ROP attacks using approaches other than just CET? The two I mentioned would help in the short term; no need to wait many years.
> Sent: Monday, May 13, 2019 at 6:20 AM > From: "Jeff Law" <l...@redhat.com> > To: "Frank Tetzel" <s1445...@mail.zih.tu-dresden.de>, gcc@gcc.gnu.org > Subject: Re: ROP attack mitigation > > On 5/13/19 2:43 AM, Frank Tetzel wrote: > >>> Every year there are new vulnerabilities, and some of them are > >>> possible because of ROP attacks. > >>> There are a couple things that come to mind to thwart ROP attacks > >>> that would rely on compiler changes in particular, instead of a > >>> kernel change or hardware change. > >>> > >>> I was wondering if anyone in the GCC project might be willing to > >>> consider these in order to improve computer security? > >>> > >>> Idea 1. > >>> Use separate stacks for local variables and stack data. > >>> - Use RSP for return addresses, as usual. > >>> - Use RBP for functions' local storage i.e. to point to a second > >>> downward-growing stack that is in the heap, far from the return > >>> stack. This way, a buffer overflow (stack smashing attack) would > >>> wipe out functions' data but not return addresses, therefore no ROP. > >>> I realize that use of two stacks is an old idea, but now that we > >>> have many more general purpose registers, using RBP in this way > >>> should be economical. > >>> > >>> Idea 2. > >>> ROP depends on gadgets, which are short segments of code ending in > >>> RET. The tricky thing about mitigating ROP is that gadgets are in > >>> unexpected places i.e. not the end of the function where the main > >>> RET instruction is. Wherever a RET opcode byte is found, even if it > >>> is inside of an immediate value, it can be used to form a gadget. > >>> Therefore to reduce the number of available ROP gadgets, first make > >>> sure that all immediate values in the program lack bytes that > >>> include RET opcodes, so simply replace 0xCB and 0xCA bytes (on x86) > >>> with other values. For example: add RAX, 0xCB01 > >>> becomes > >>> add RAX, 0xC001 > >>> add RAX, 0x0B00 > >>> Similarly if a branch instruction's relative offset contains a 0xCB > >>> or 0xCA in the low offset byte, put a few NOPs in front of it to > >>> ensure that byte will not be a RET. It might be tricky to avoid the > >>> ModRM byte 0xCB (as in ADD BL, CL) but it can be done. > >>> > >>> My 2 cents. > >> Bernd and others within Red Hat looked at ROP mitigation a while back. > >> We ultimately stopped development of gadget spoilage due to the > >> emergence of CET and instead we've put our focus there. > >> > >> While CET won't help older processors, it's my belief it's the right > >> first major step in ROP mitigation. At this point we believe RHEL 8 > >> is fully ready to use CET when processors hit the streets. I haven't > >> tracked Fedora as closely, but if it's not ready it shouldn't be hard > >> to make it ready. I suspect other distros have similar plans around > >> CET. > >> > >> I'm not aware of anyone seriously looking at separate stacks for GCC > >> right now. To some degree the stack protector serves the same purpose > >> without separating stacks. > > > > > > Are you talking about Intel CET[1]? It includes a shadow stack for > > return addresses. CALL pushes to both stacks, normal and shadow, and > > RET pops from both and does a comparison before jumping. > > > > The other feature of CET is Indirect Branch Tracking which enforces > > that every legal target of an indirect call/jump starts with an > > 'endbranch' instruction. This should limit the number of useful gadgets. > > > > I'm not a security expert. I just came across the 'endbr64' instruction > > when disassemblying the other day and was curious. > Yes. endbr64 is part of the new CET instructions. It marks valid > indirect branch/call targets. > > jeff > >