-
Notifications
You must be signed in to change notification settings - Fork 72
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
LKRG immunity module & kernel vaccination #150
base: main
Are you sure you want to change the base?
Conversation
Thank you, @milabs! This is a welcome contribution. A related task in my LKRG notes was summarized as "protect /proc/kallsyms, /boot/System.map*". This PR takes care of Just to give some context, IIRC Adam and I debated briefly via private e-mail about whether restrictions on filesystem permissions should be in LKRG itself or maybe in its startup script. The latter would be less invasive, but then the restrictions wouldn't be put in place when LKRG is loaded by different means, and wouldn't be consistently undone on LKRG unload. Another question that came up was about Also in my notes is this subtly related task: "hide=1 should hide sysctl's from non-root" (no, I don't suggest adding that to this same PR - it should be separate). I guess @a13xp0p0v might also have comments on this. I have mixed feelings about the vaccine/immunization naming used here. On one hand, it's fine pun on the current covid situation. On the other hand, LKRG should outlive covid, so the pun would be obsolete (hopefully soon). Perhaps more importantly, LKRG's other features and LKRG as a whole could also fit this naming - so it could be illogical to use it for this specific feature only. Anyway, the separation into modules might be reconsidered or even gone in our planned code cleanups - by the way, something we'd appreciate all contributors' input on. An issue to fix, CentOS 7:
|
@solardiz maybe it's a good time to have a list what else do we want to protect. Additionally, maybe we want to make this feature configurable where user can add specific file / directory which wants to protect (e.g., log file directory)? |
Isn't this directory access restriction overmuch? This should be done by proper file permissions, should LKRG try to solve all issues and possible misconfigurations (and I think that permissive access to sensitive directories is a misconfiguration)? |
Yes, but not necessarily before merging this PR.
No, I think that's a different feature. At least as currently implemented in this PR, the protection here is only against non-root. If a sysadmin wants to explicitly protect e.g. a log file directory from non-root, they can just |
@wladmis I think it's reasonable for LKRG itself to restrict access to the most obvious and generic places that would provide information on attacking the kernel and bypassing LKRG. We can't expect most systems/sysadmins to manually harden permissions in addition to loading LKRG. Conversely, we can expect canned exploits to automatically look into those obvious and generic places to bypass LKRG. |
Hey, thanks for replying. I should have started with the description, so let me clarify the idea. Most of kernel exploits start with information gathering phase which consists of steps to get target system kernel version which is used to align various offsets (for example, to build a ROP chain). Here is what comes to my mind when it comes to target's information collection:
So, I thought that it might be easy yet extremely useful in terms of exploitation prevention to alter system's behavior to protect listed (and similar) information and/or even fake it. For example, altering UPD: Few words about naming of such a feature as "immunity". For me altering kernel's behavior in a way that it becomes resistant to exploits is a kind of vaccination resulting in kernel's immunity. |
Hi!
What do you think about filtering of reading of |
@wladmis Seriously? It takes 1% of LKRG complexity to implement that and it gives 99% of LKRG's protection level agains known exploits and probably most of yet unknown (except things like dirtycow, though LKRG doesn't fit it either). |
Sorry, that notice about complexity was about my proposal of reading filtering, not about your. Sorry for the ambiguous reply. |
@wsandin Got it, sorry. |
Adam and I briefly discussed this PR yesterday. While we like it in principle, we're unsure about merging it as-is because:
This makes sense, but most LKRG features contribute to that vaccination and (partial) immunity, so it's weird to single out this one feature for that naming. Also, to someone who doesn't yet know what this feature does and how it differs from other LKRG features, the "vaccination" setting name would not tell anything additional. I think this new feature is most closely related to LKRG's "hide", so maybe we can enhance "hide" to cover it or maybe we can come up with consistent new naming for both. Suggestions are welcome. |
@solardiz I'm going to make other implementation with more features added so closing this PR which acted as initial discussion. |
@milabs OK, and looking forward to that, although it'd be easier for us to review and merge a PR that doesn't yet have "more features added" (they can be added with separate PRs later). This now-closed PR of yours was very close to what's needed from a first PR adding this set of features - like I wrote, only the naming and portability issues needed to be addressed before merging. |
Please, review feature prototype based on KHOOK: |
@milabs Thank you! Since this is a prototype, I assume it's for us to discuss its feature set rather than code, so here are some observations (for others reading this who might not have looked at the code yet) and thoughts. Please correct me if I got anything wrong, which I very well may have.
Using
Overall, this prototype is helpful in bringing up so many little questions and design decisions for us to make. It's quite concentrated in terms of those per line of code. Good stuff. I might also make some nitpicks on code in GitHub inline comments over the referenced link. Those are not essential to the discussion here. |
Also, we need to discuss the bigger picture to decide on most suitable naming and ways to control these and related features. Here are some related categories of potential features, off the top of my head:
Maybe these are separate, or a bitmask in one or several settings, or protection levels in several settings (like two - one for LKRG itself, the other for the kernel). |
Or the grouping could be different: one setting for protection set (what to hide from non-root) and the other for policy (against root, so whether to disallow unhiding/chmod, unloading, loading/patching). |
I would also consider some of the /sys interfaces (e.g., |
We can definitely consider more, but I think our priority is to get some basic functionality into a form that can be merged without breaking things (e.g., not even RHEL7) and preferably without us ending up introducing incompatible changes to the new sysadmin knobs soon thereafter. We can then add more with separate PRs. |
BTW, the breakage of RHEL7 here was in code forging |
@solardiz I've found recently that hooking |
@milabs As I recall, glibc cares (or at least used to care) about kernel version, but I don't know by what means it obtains that - we need to check. Some system info is available to glibc via AUXV at program startup, but apparently not kernel version. |
Have a look at v2 version of the feature prototype: Implemented:
Note on |
Thanks for your work @milabs. Some of my notes:
|
Have a look at v3 version of the feature prototype: Implemented:
Looks for me as a semi-final prototype version. Going to start working on making the change LKRG. |
I'm sorry I didn't review/comment for a while. I just took a close enough look to comment. As I understand, the I think there's still a race condition, though: if the syscall is made by 2+ non-root tasks concurrently, then unforged or partially-forged data may leak: when one invocation proceeds to @Adam-pi3 Regarding supporting namespaces, I assume that was about @milabs You hook two of the Regarding changes in v2, I wonder if using For the knobs, while we could logically make Thank you! |
No, I'm wrong. Somehow I thought |
@solardiz @milabs when we deploy direct hook on the syscall, we must take into account potential COMPAT and X32 support. Each syscall is potential 3 hooks, 3 syscalls is 9 hooks. That's one of the reason that I tried to avoid direct syscall hooks. However, sometimes that's the only viable option. About the name, what about |
If we go for more than one word, then I'd prefer We could then also have |
Thanks @milabs - this is cool stuff, looking forward to more standoff in public builds. FS restrictions are kind of fraught in that its very hard to predict what actually depends on the real data being obfuscated to work properly and whether that something is even in the userspace intended to run atop the kernel or some container of another userspace hatefully thrown into the mix to make the kernel's life that much worse. EDIT: we sometimes use RSBAC to provide the policy-based MAC functionality when a target environment can't use real RBAC (therefore in environments where LKRG plays), so it might be worth looking into compatibility with them as well since hardened kernels are often built out of various pieces, and that's another good public source of defensive functionality. |
It's been a while since the idea was suggested and recently I had some time to implement what was discussed more or less nicely. Please, guys have a look to the module I've posted: |
Description
The idea behind the immunity module is the following: make it difficult for the attacker to identify target system's kernel version so it would be hard or even not possible to find proper offsets and even determine the vulnerability presence.
There are 2 things implemented in the commit:
/boot
,/lib/modules
folders access restriction (root only access allowed)/proc/cmdline
data forgedFew more things to do:
utsname()
How Has This Been Tested?
Tested on Ubuntu 20.04 (5.11.0-25-generic)