Dear kind people,

I hope you're fine and healthy. The reason I am writing this mail is to share
a few of my experiments and research I've done to come up with a reasonable
stack pivot detection for the Syd kernel. TL;DR I have failed and I have learned
a lot. I have also learned everyone is doing various levels of wrong and I have
yet to come up with a "correct" solution. Are we doing it wrong or are we 
attacking
the wrong link? Please discuss.

The obvious idea is to check if stack pointer points to a valid stack region at
various boundaries. This solution is so obvious you'd imagine even a 4-year-old
can come up with it, yet G**gle has a patent[1] on it. Curious (mis)use of 
software
patents where an entity patents the equation "foo < bar < baz". What do we do if
they go one step ahead and patent "<"? Use emoji for maths? Move to Mars?

Anyhow, this is not what I am here to discuss. OpenBSD does something similar
with MAP_STACK[2] and Windows 8 had a similar mitigation until someone 
demonstrated
a trivial bypass[3]. Finding out this bypass was an important step forward for 
me so
I went ahead and rewrote it[4] for UNIX and verified it bypasses what Syd had
at the time and what OpenBSD has. This bypass is a simple improvement of what
OpenBSD regression tests have and involves a quick jumpback to the stack. 
Funnily
if you remove the printf in the intermediate stage of the bypass OpenBSD's SP 
check
at write(2) boundary will catch and kill you so keep it quiet as you bypass this
delicate mitigation ;).

Another roadblock for the SP points to a stack region detection is in userspace
there's no clear definition of "stack". The stack of the main thread is handled 
by
the kernel where everything is fine but thread stacks are typically your 
language
runtime's business. As an example if you check the stack of a Go thread on 
Linux,
you'll most probably find the VMA is named " Go: heap". It may be the stack for 
now,
but maybe it was not a bit ago or won't be a bit later. Asking Go devs to use
MAP_STACK would probably be rejected because it breaks the whole model of how 
they
do multithreading...

I digged a bit deeper and found what I thought was an improvement at the time.
Why not check the frame pointer instead of the stack pointer? Why not both?
It was fairly easy to patch Syd for this so I got to testing. This way of 
detection
is imho more reliable and less prone to bypassing however there's a big issue.
Both gcc and clang imply -fomit-frame-pointer with -O2 so you'll have a hard 
time
finding a binary in the wild these days that has frame pointers. If I were 
OpenBSD,
I'd compile the world with -fno-omit-frame-pointer and move on with my life and 
I'd
humbly and kindly recommend them to do that in short of any better ideas.

Now, my tests showed me another problem. Stack pivotting is not as unusual and 
as
malicious as you think. In fact, various programs make use of it in arguably 
weird
ways to achieve their goals. One example is Firefox's crashhelper, bash, gawk, 
ceph,
... I can easily come up with dozens more if I enable this mitigation and build 
Exherbo
packages under Syd as we proudly enable package testing by default. So even if 
you'd come
up with a reliable, efficient way to detect stack pivot, you're gonna have 
loads of false
positives to manage. Good luck.

Finally, after I ended my experiments and reverted[5] Syd's stack pivot 
detection. I
came across LKRG's README[6] incidentally which mentions validating the stack 
pointer
with "pCFI", their version of coarse-grained CFI, which also seems to check the
frame pointer[7] against the stack. I'd be curious to know whether there's any 
added
mechanism to detect stack pivot when the binary is compiled without frame 
pointers when
the frame pointer is reused by compiler for different purposes.

Best regards,
Ali Polatel

[1]: https://patents.google.com/patent/US10853480B2/en
[2]: https://isopenbsdsecu.re/mitigations/map_stack/
[3]: https://archive.ph/xS2Fl#selection-13.0-243.52
[4]: 
https://gitlab.exherbo.org/sydbox/sydbox/-/blob/main/dev/stackpivot-jumpback-bypass.c
[5]: 
https://gitlab.exherbo.org/sydbox/sydbox/-/commit/f03db6c677ddf5dbf87adeb6bd5efb0677869104
[6]: 
https://github.com/lkrg-org/lkrg/blob/b8b1418a6c1e7229cdf3dfa020fcc4945e108d83/README#L505
[7]: 
https://github.com/lkrg-org/lkrg/blob/b8b1418a6c1e7229cdf3dfa020fcc4945e108d83/src/modules/exploit_detection/p_exploit_detection.c#L1585-L1591

Attachment: publickey - [email protected] - 0xC22DA9DE.asc
Description: application/pgp-keys

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to