>"IEEE Spectrum: So you can detect an attack just by looking at what’s being looked at? Todd Austin: Yeah. Let me give you a classic example—the return stack. [When a program “calls” a subroutine into action, it stores the address the program should return to when the subroutine is over in the return stack.] This is a real popular place for attackers to manipulate to do what’s called a buffer overflow or a code injec…
Most of these already exist Rings are code privilege levels, they don't "protect" memory, page tables do that, and the implementation to protect the stack has been around for over a decade - DEP call/return stack detection is very new, afaik only current generation intel processors have it under the name CET (control-flow enforcement technology). This works by a processor-level "shadow stack," which is pushed to on c…
On a general level, I agree.
But, if we get really specific, "The Devil Is In The Details"... let me elaborate...
>Rings are code privilege levels, they don't "protect" memory, page tables do that,
Page tables describe aspects of blocks of memory, if I recall correctly, they describe such things as the physical memory a page is mapped to, if the page is swapped in or out, and possibly the privilege level of code that supposed to be executing there.
But the idea that they "protect" memory is, well, an abstraction at best...
First off, OS, running at ring level 0 has access to all memory. That is because even if there is a page-based protection scheme in place via CPU data structures, the OS is typically privileged enough to modify those data structures such that the memory in question can be accessed.
Second, it's an abstraction.
At the CPU level, the CPU knows the privilege level of the code it is running at any time, and is supposed to, is supposed to (and it's a big if, given all of the complexity, the microcode, etc.) under the hood, that it actually protects that memory.
For example, there was an old AMD "bug" (and it may have applied to Intel too) where if one of the "string" registers (ESI or EDI, I forgot) -- was set to a specific "magic" value -- then any memory could be accessed regardless of protection level!... so much for "page tables protecting memory"... (https://www.joelonsoftware.com/2002/11/11/the-law-of-leaky-a...)
Oh, I'm sure it's fixed now... but as the old expression goes, "fool me once, shame on you, fool me twice, shame on me..."
>and the implementation to protect the stack has been around for over a decade - DEP
DEP is basically marking a page in memory as "Non-Execute" (that is, as "Data" as opposed to "Code"). When this is done to the memory where a program's stack is located, then the CPU's instruction pointer (EIP, RIP, etc.) -- cannot be changed to an address there without triggering an exception. In other words, code, should it exist there, cannot be executed.
But... can data there, as data, be changed?
In other words, we're not debating if DEP prevents a control-flow violation, by allowing a CPU's instruction pointer to be changed to a memory address which is on a program's stack.
We agree that DEP prevents that.
But, you see, the way x86 programs typically work, they need to be written with CALL and RET instructions, because that's how higher-level languages compile procedure/function/method calls. CALL pushes the current executing address (the CPU's instruction pointer, EIP/RIP) on the stack and changes it to the address of the procedure/function/method being called. Control resumes at the address in memory representing that called procedure/function/method. When it's time to return from it, RET does the opposite -- it pops the previous address (well, plus a few bytes to skip the CALL instruction!) back into EIP/RIP -- and control resumes where it had left off, that is, in the earlier function that CALL'ed the later one.
Now, what's wrong with that?
Well, on the one hand, nothing, because that's the way x86 programs typically work.
On the other hand, everything (and this is where we have our debate!) -- because
CALL and RET instructions are permitted to change and modify the stack!
Other x86 instructions -- any x86 instruction that accesses memory (as long as it's running in a process) -- is also permitted to change and modify the stack (of that process!)!
That's because the stack -- is memory!
Now, it may very well be that later iterations (and if so, we're talking very late!) of Intel/AMD/? x86 processors spotted this, and restricted by whatever means the use of some of those instructions (but then, I'm not really sure what a program is supposed to do when passing local variables from one function to another, because in order to do so, modifying the memory of the stack is required, because how else do you pass those values?)
You see, it's possible for a buffer overflow attack, one which gains the ability to execute code locally, in a local process (aka "program"), to easily modify the stack of that process (because it appears as legitimate code to the CPU!) -- whether or not DEP is enabled or not !!!
What I proposed in my comment, above, is a radically different departure from using stacks in the normal sense -- my proposal requires separating the control flow portion (CALL/RET) of the stack from the data (local variables) portion, moving that into OS memory.
That requires an OS specially written for that purpose, and a compiler also specially written for that purpose (basically CALL/RET or anything stack-control-flow oriented is replaced with OS calls. These make the code slower, but you gain an increase (although not perfect) in security from worms and buffer overflows...
>call/return stack detection is very new, afaik only current generation intel processors have it under the name CET (control-flow enforcement technology).
But, this could be enabled on older processors if the stack is moved to OS control...
>This works by a processor-level "shadow stack," which is pushed to on calls and popped from on returns, and throws a fault if the actual stack is returning to a different location
A "shadow stack" is a good idea. While not perfect, it is a step in the right direction...
>Pointer encryption is available on ARM as PAC (pointer authentication). Afaik there's no equivalent on x86 processors.
I know I said that this was a good idea, and it is, it's another step in the right direction, but that being said, I wouldn't trust this (at least, not 100%) simply because hardware does not have the same transparency as easily readable source code... On an FPGA Soft CPU with no hidden cores, maybe (again, if the user has the the HDL VHDL/Verilog code for the Soft CPU)...
>Hardware mitigations are gaining more and more traction, so hopefully all of them will be available across all major architectures within the next decade or so.
I assume zero-trust for anything I can't see, I can't modify, that I don't know the full workings of...
>EDIT: another huge mitigation that's starting to gain traction is process-level virtualization. Qubes is most known for it, but Windows has been building more support for it (currently only edge and office support it, under the name "Application Guard").
I do not trust Windows. Or Linux either for that matter. Or Qubes, or Virtual Machines... or any so-called "secure" OS.
I trust the vendor who says: "This is the worst written OS from a security perspective, and your best bet is not trusting us" -- because at least if they say that, they are being honest...
And that "vendor" -- is usually a simple, hobbyist-level, not-overly complex, well documented open source OS, which still might (and probably does!) have any number of security issues!
With respect to Qubes:
As soon as you are running on a CPU that supports nested page tables (nested virtualization) -- all bets are off, because your OS, running inside of your VM -- might be running on another VM, which might be running on another VM, which might be running on another VM, practically ad-infinitum...
You sure there isn't another VM -- a VM that you don't control -- a VM that you don't know about -- that your highest-level VM is running in?
Because I'm not...
The distinction between "VM" and "bare metal" and "VM that you don't know about appearing as bare metal" -- is starting to blur these days... read all you can about Rootkits -- they are the entry-level understanding to this...
Oh yes, anything that you or I have said about page tables or OS control or protection -- goes right out the window when a higher-level VM is present and operating... that's because higher-level VM's have control over everything,
including the page tables of lower-level VM's and and OS's that they run...
What's the old expression?
"Eternal vigilance is the price of liberty?"
>The idea is that if a malicious actor is able to exploit a program, they would also have to break out of the vm the app is in to gain access to the full system, which can be a much more difficult task.
Do me a favor... Google "VM Escapes" -- and then spend about a year and a half reading academic papers about them...
In fact, don't Google it... go to Millionshort and search for it there (also, for future readers 3+ years in the future, don't go to Millionshort -- find your own not-yet-superpopular up and coming search engine, and search on it -- since all of them seem to get censored after a certain number of years -- but you can go to Millionshort on or around the date of this message, 2021/04/17)
Don't forget to remove the first, oh, hundred thousand or so search results!
Also, if any of this offends you, well, that wasn't the intention...
I only pass what I believe to be truthful information that is coalesced from many sources, edited into an easily readable format...
If you dislike anything, you dislike the information, not the conduit...