Just like Linux, the modern Solaris install doesn’t simply rely on UID/GID to determine privilege. Instead there are roles and profiles to contend with. The following is a loose explanation of how they work:
- User = user + group + user_attr + /etc/security/auth_attr + /etc/security/auth_attr.d/*
- user = Raw privileges (PRIV_DEFAULT + !PRIV_LIMIT)
- user_attr = List of profiles (/etc/security/prof_attr + /etc/security/prof_attr.d/*)
- prof_attr = List of authorisations (/etc/security/auth_attr + /etc/security/auth_attr.d)
Additionally, /etc/security/exec_attr specifies what privs a particular command will execute under a given profile.
The first user added will get root by virtue of this scheme. Having said that, for Solaris 11, Oracle pretty much canned this and moved to sudo instead. It’s still there though, if you look.
So today, we were looking at a Solaris 11 box which was mostly being managed via sudo. I say mostly because we found this (isolated) gem in user_attr:
bob::::profiles=Service Management,Service Operator
It’s likely not a backdoor but it is rather odd given the beautiful /etc/sudoers.d hirearchy that also existed on the same system. This authorised them to use the solaris.smf.manage and solaris.smf.modify privileges.
This could be bad. To quote the man page, users authorised with the solaris.smf.modify privilege are:
Authorized to add, delete, or modify services, service instances, or their properties, and to read protected property values.
whilst solaris.smf.manage is:
The service management profile is the minimum required to use the pkg(1) command to add or remove software packages that contain an inventory of services in its service manifest.
So is it exploitable? Well, it turns out that users with those particular authorised privileges can run the following:
bob@localhost:~ $ svccfg -s <service> setenv -m start LD_PRELOAD /tmp/libdoor.so; svcadm refresh <service>; svcadm restart <service>
This, when executed, will cause the named service to have a new environment variable defined (LD_PRELOAD) which points at our malicious code (/tmp/libdoor.so) which will be loaded by the service when it is restarted. As a result, our malicious code will be run as the same user as the victim user, giving us persistent privileged access to the victim machine.
Without these privileges, the same command will result in an error:
bob@localhost:~ $ svccfg -s <service> setenv -m start LD_PRELOAD /tmp/libdoor.so; svcadm refresh <service>; svcadm restart <service> svccfg: Permission denied.
Bottom line, if you compromise a modern Solaris box, try running auths (and roles) to check what privileges may have been left behind, it may be more than you think.