Open evrim opened 2 years ago
This tool is pretty cool, but declaring a service "safe" because it uses a bunch of hardening options is quite a stretch. The nix-daemon needs root access for setting up build sandboxes, running builds as separate users and write access to /nix/store. Enabling some of these options and running it as an unprivileged user with capabilitiess is probably feasible, but it won't make it safer, imho. For example, if the nix-daemon is compromised, it can just hijack any binary, shell script or service inside the /nix/store and regain whatever level of privilege it lost due to the hardening
SystemD Documentation: https://www.freedesktop.org/software/systemd/man/systemd.exec.html
Currently, most of the services on NixOS are UNSAFE or EXPOSED. Safe in this context means score <4.0 (OK). (I couldn't find any doc on that, man doesn't say which score is OK, just says scores between 0 and 10, my system has a services with 4.0-OK). Anyway, nix-daemon is a single point of failure for all deployed instances, drawing a perimeter is a wise action. I believe its better to start hardening mostly used services.
Anyway, nix-daemon is a single point of failure for all deployed instances, drawing a perimeter is a wise action. I believe its better to start hardening mostly used services.
What is the threat model here? The report doesn't even seem to care to distinguish protect-the-service and protect-against-the service, and a significant compromise of Nix daemon is a game over because of store access. Even if we fool naïve audit by tricks, Nix daemon can alter the installed glibc package. And data leaks from daemon do not mean that much as long as paths built are world-readable. Nix daemon launches things that should indeed be sandboxed (builds), but it sandboxes them itself.
@7c6f434c Raskin, you are right. In a normal distro, users wont be able install packages. Maybe it is possible start with implying those kind of restrictions. Another idea is restricting the packages that users can install. More, separating system packages from users, deploying user packages as separate. Nevertheless, these are for nix.
For NixOS, I believe, defining which Capabilities nix-daemon requires, which Socket Families it uses, what kind of Namespace functions it utilizes will carry us to the next step.
For NixOS, I believe, defining which Capabilities nix-daemon requires, which Socket Families it uses, what kind of Namespace functions it utilizes will carry us to next step.
Next step towards what? What is the threat model? Nix bugs with direct consequences? Insufficient builder sandboxing that you propose to improve? Something else?
Note that service-level restrictions are also restricting all the builds Nix can ever run.
@7c6f434c Honestly, I am not sure, never met such an omnipotent daemon. Nevertheless, I believe it is possible to start with an adversary with rw access to nix-daemon.socket similar to docker.
I have doubts, is that true? I mean the capabilities of nix-daemon should be separate, no?
@.*** Honestly, I am not sure, never met such an omnipotent daemon.
Doesn't any distribution have an option to install some updates automatically? Whatever daemon manages this, has the same issue of effective omnipotence. Which is indeed often abused in supply chain security attacks…
Nevertheless, I believe it is possible to start with an adversary with rw access to nix-daemon.socket similar to docker.
Presumably, if the attacker manages to create a socket of type Nix should not create, i.e. make a syscall with parameters that cannot be passed by simply taking a wrong branch, we have a code injection of some kind (which is most likely a game over), what am I missing here? But sure, taking wrong branch / opening file in a wrong way / something like that could happen, measures that protect about that could be of some use.
I have doubts, is that true? I mean the capabilities of nix-daemon should be separate, no?
Separate from what? It surely restricts what is available to builds, but as it spawns them they cannot have more than the daemon has. I guess you could fork Nix and make a daemon that writes to the store and the daemon that starts the builds separate processes with different sandboxing, but this is a lot of work and not on the level of the service file. Protocol audit and fuzzing could surely be useful in any case, no question there.
@7c6f434c
Doesn't any distribution have an option to install some updates automatically?
My prev experiences with auto-update daemons were terrible since config files are left intact, services being disrupted by updates. With nix, the experience is awesome. My point is, if you say because auto-update needs omnipotence, than it should be a separate service without any attack surfaces.
Presumably, if the attacker manages to create a socket of type Nix should not create, ...
I was thinking of someone fuzzing nix finding a type confusing etc doing ROP over nix-daemon.socket.
Separate from what? It surely restricts what is available to builds, but as it spawns them they cannot have more than the daemon has. I guess you could fork Nix and make a daemon that writes to the store and the daemon that starts the builds separate processes with different sandboxing, but this is a lot of work and not on the level of the service file. Protocol audit and fuzzing could surely be useful in any case, no question there.
This mite be interesting though it should be evident what we would gain if builder and system manager are separate entities.
Another point I am curious about is what are the proper auditd rules? It would be wonderful if we can build up a default auditd ruleset for nixos so that we can track whats going on on the system overall.
Doesn't any distribution have an option to install some updates automatically?
My prev experiences with the auto-update daemons were terrible since config files are left intact, services being disrupted by updates. With nix, the experience is awesome. My point is, if you say because auto-update need omnipotence, than it should be a separate service without any attack surfaces.
Auto-update without any network attack surface sounds not very useful.
Nix is more than auto-update because it is a general package manager daemon allowing some user control. Which might have non-sudo implementations in other distributions, but I am not sure how they would be called. Something that would include PolicyKit and DBus, I guess, making sandboxing even more complicated.
Presumably, if the attacker manages to create a socket of type Nix should not create, ...
I was thinking of someone fuzzing nix finding a type confusing etc doing ROP over nix-daemon.socket.
Given how few sockets and how many files Nix opens, I would still expect some more file-based attack to be more likely to be found. Although I guess only a succesful fuzzing will tell…
Separate from what? It surely restricts what is available to builds, but as it spawns them they cannot have more than the daemon has. I guess you could fork Nix and make a daemon that writes to the store and the daemon that starts the builds separate processes with different sandboxing, but this is a lot of work and not on the level of the service file. Protocol audit and fuzzing could surely be useful in any case, no question there. This mite be interesting though it should be evident what we would gain if builder and system manager are separate entities.
Well, if you want systemd service sandboxing, then you want components with different activity and risk profile to be different services so they can be sandboxed according to the least authority sufficient to perform the duties…
Another point I am curious about is what are proper auditd rules? It would be wonderful if we can build up a default auditd ruleset for nixos so that we can track whats going on on the overall system.
I guess you could fork Nix and make a daemon that writes to the store and the daemon that starts the builds separate processes with different sandboxing
I don't even know if this would help much as attacking the build daemon itself probably could lead to full compromise and attacking the daemon that writes to the store would probably also lead to a full compromise.
Maybe it would reduce the attack surface minimally but I don't really know. Also as you said it would increase the complexity.
Actually I think this is a pretty hard problem as the attack surface seems comparably large. Fuzzing / security audits would probably be really worth it.
I don't even know if this would help much as attacking the build daemon itself probably could lead to full compromise and attacking the daemon that writes to the store would probably also lead to a full compromise.
Well, if you split things, there is protocol handling daemon (exposed to untrusted input, needs version negotiation for upgrade path reasons, can do nothing on its own), store writing daemon (can in principle damage preexisting paths, has quite restricted protocol and no longer needs version negotiation, sandboxed from network stuff and such), build spawning daemon (at least no more version negotiation, can only write temporary things and not alter the past, maybe hashing the entire input of build-spawning daemon could be done by yet another very simple daemon to exclude wrongly-building-critical-paths without changing hash).
You probably gain something by sufficient amount of work. But it's quite a lot of work.
Maybe it would reduce the attack surface minimally but I don't really know. Also as you said it would increase the complexity.
Actually I think this is a pretty hard problem as the attack surface seems comparably large.
Hello,
Are there any plans for 21.11 to secure nix-daemon unit? Current situation is as follows:
nix-info: