Hacker News new | ask | show | jobs
by ordu 39 days ago
> The alternative they present is arguably less secure because the function pointer will remain writable for the life of the process

The article mentions this, and also points to mprotect which you can use to protect the pointer.

Why people jump to criticize without reading first? BTW, you can ask an LLM to check your critique, before posting, if you don't want to read the text.

1 comments

Yes but at best their "solution" is equally secure, not any better.
They argue, and I tend to agree, that their solution is more secure.

1. It impiles some function pointers to be writable temporarily, not all of them.

2. It doesn't hide writable pointers from a cursory glance not familiar with IFUNC.

The GOT has to be initially writable regardless of ifunc, even with relro, to apply relocations.
Would xz still have been able to alter opensshd without IFUNC?
Yes, liblzma could have used multiple routes to take over sshd. Once you're running inside the process it's game over. The exact details, like how they used ifunc and an audit hook, are very interesting, but ultimately not that important.
I've updated the post and am offering $500 if you can pull this attack off without ifunc.
$500 isn't worth my time and I don't trust you'd pay up. But for anyone who wants to attempt to get him to pay up, here are three simple approaches:

(A1) In a POSIX constructor function in liblzma, set an alarm(2) for a few seconds later (once sshd has fully loaded).

(A2) In the alarm callback locate the original function that was patched using dlfcn, and mmap a page of modified code over the top that calls the exploit.

Or:

(B1) POSIX constructor function, call clone(2) to start a background thread.

(B2) In the background thread, sleep for a little, then patch the code as in A2 above.

Or:

(C1) POSIX constructor function that completely replaces the sshd process with a workalike that contains the exploit.

In A & B, for OSes (not Linux) that deny mmap, you'll need to find a struct or stack frame used by the function and work out how to adjust the data it uses or find a function pointer and exploit that.

You may well be right about this! What I genuinely don't understand then, is why Jia Tan relied on ifunc rather than POSIX constructors. Seems like that would have been easier and more widely applicable, right?
It is weird to limit to "the same attack". Why does it even have to be the same attack? From the moment sshd loads your modified lib, you're literally running code with root privileges on the victim machine. You can literally run _any_ attack you wanted, with zero persistence. This is worse than a OpenSSH RCE.

Even in your own talk you basically admit this, so what are you doing here? If you think there's something here that everyone is missing but you don't, why not actually explain what it is?

I don't have any secret information! Folks were giving me a hard time about claiming that ifunc is central to this attack, and I would genuinely find it valuable to know that Jia Tan could have (for example) performed this attack against a musl-based distro.
You can always populate .init_array section with a hidden constructor. It would work just like ifunc and would always execute at shared library load time.
I think .init_array is too late in the game. ifunc lets you hijack the loader, because it is sort of like a plugin or dynamic config for the loader itself. Everything should be loaded and resolved by the point that .init_array stuff starts getting triggered, though ELF is dark and full of terrors so who knows really.