Closed spbnick closed 7 years ago
You might want to drop supplementary groups with "setgroups()". It is especially useful for increasing privileges. We already have some code in sssd. You might inspire. https://github.com/SSSD/sssd/blob/master/src/util/become_user.c
It would be good to to clear/reduce environment variables "clearenv()" as a first think in binaries with SUID adn SGID. It is also good to use restrictive umask for such binaries.
I am not sure how much time do you have but it would be good to use linux capabilities as a hardening. For changing UID/GID it should be enough to have (CAP_SETGID and CAP_SETUID). I can be achieved with libcap/libcap-ng or it can be done in distribution specific packaging. The same as ping on fedora. BTW *BSD or platforms can still relay on SUID and SGID;
sh$ getcap /usr/bin/ping
/usr/bin/ping = cap_net_admin,cap_net_raw+ep
It's possible to find more info in man 7 capabilities
Thanks a lot for review, Lukas!
Yes, we can drop the supplementary groups in the original (recording) process after forking the child, good idea.
We cannot clear the environment variables as the first thing, because we need to pass them to the child, recorded shell. However, we can remove any tlog-specific variables in the fork, before executing the child, and we can remove everything unnecessary in the parent after forking the child. We also have issue #3 tracking that.
Since we're started in place of the user shell, we're started with the target user's credentials and we cannot set any capabilities in general. That's why tlog-rec must be SUID/SGID to a special user to access special resources and be protected from the recorded user. So, if I understand it correctly, we don't need to change capabilities, as we don't need, and don't get any. Also, tlog-rec shouldn't ever run as a superuser, unless it is set SUID/SGID root, or the logging-in user is root, but that's an exception and shouldn't happen.
However, thanks for the mention of the capabilities, I used that opportunity to learn more about them :)
Ah, right, tlog can't drop the supplementary groups with setgroups
, because it doesn't run as root.
Ah, right, tlog can't drop the supplementary groups with
setgroups
, because it doesn't run as root.
hmm, I'm confused. It can call setresgid
and setresuid
but it cannot call setgroups
. That looks suspicious.
Ah, yeah, setresgid/uid can do that. From their manpage:
An unprivileged process may change its real UID, effective UID, and saved set-user-ID, each to one of: the current real UID, the current effective UID or the current saved set-user-ID.
The man page for setresuid/gid
says that it require capabilities CAP_SETGID and CAP_SETUID.
The man page for setgroups
says that it requires capability CAP_SETGID,
And with suid/sgid bit you are roll with all calabilities
Hmm, sorry, I'm not sure what you mean. Could you please elaborate? Thank you.
I confused as well. As I already eplained tlog has enough rights to run setgroups
.
So could you explain where is the problem?
Hmm, perhaps I ran setgroups
with EUID/EGID set to RUID/RGID and that's why setgroups
returned EPERM. I'll check if it works with original EUID/EGID.
On (19/01/17 07:55), Nikolai Kondrashov wrote:
Hmm, perhaps I ran
setgroups
with EUID/EGID set to RUID/RGID and that's whysetgroups
returned EPERM. I'll check if it works with original EUID/EGID.Yes, it should be called before setresuid/gid
LS
Nope, EPERM, even if called right at the start of main(), no matter SUID/SGID, or not.
Oh, and yeah, I'm calling setgroups(0, NULL)
.
On (19/01/17 08:20), Nikolai Kondrashov wrote:
Oh, and yeah, I'm calling
setgroups(0, NULL)
.That's weird. We call
setgroups(0, NULL)
in sssd in setuid process.
/usr/libexec/sssd/krb5_child
(via become_user) and it does not cause
any problem.
https://git.fedorahosted.org/cgit/sssd.git/tree/src/providers/krb5/krb5_become_user.c?id=bdf63b2c329f12b4cdfcc04122f4547aad6bfa35#n43
I am out of ideas.
Which UIDs/GIDs krb5_child has when it invokes setgroups?
On (19/01/17 10:24), Nikolai Kondrashov wrote:
Which UIDs/GIDs krb5_child has when it invokes setgroups?
sssd_be is running as non-privileged user "sssd". It spawns the krb5_child which has suid bit %attr(4750,root,sssd)
Does it answer your question?
LS
Right, so it's suid-root, which is different from suid to a regular user, and that's why I assume setgroups works there and not in tlog. Yeah, you answered my question, thank you :)
Once I change the owner of tlog-rec to root, setgroups works fine.
Make
tlog-rec
executable SUID/SGID to a dedicated user/group. Drop back to the original user/group before exec'ing the shell in the fork. This will keeptlog-rec
safe from the modification by the recorded user and would also allow authenticated filtering of the log messages.Upon RPM installation, a special user and group both named
tlog
should be created, andtlog-rec
should be owned by them and marked SUID and SGID.After forking the shell process,
tlog-rec
should drop to the real UID/GID withsetuid(getuid())
andsetgid(getgid())
.For additional security, consider retreiving the effective user/group IDs and setting them to the real IDs with
seteuid
/setegid
right after starting, passing them around (say aseuid
/egid
) and only setting them back withseteuid
/setegid
when necessary. I.e. when reading the configuration and when opening the logging socket/file.Also consider calling
setreuid(euid, euid)
/setregid(egid, egid)
in the parent process after forking the shell, so the parent (recording) process would not be able to regain the user's real IDs. However, ignore EPERM, perhaps producing a warning, as POSIX says that might not be permitted, even though it works on Linux and some BSDs.To verify:
setreuid
/setregid
use is implemented, check that all user/group IDs in /proc/PID/status of the parent recording process are the tlog's IDs. Otherwise, check that real IDs are user's IDs and others are tlog IDs.file
writer.syslog
writer.