Hay dos casos,
- Desea eliminar temporalmente el privilegio de root mientras ejecuta el programa setuid
- Desea eliminar permanentemente el privilegio de root mientras ejecuta el programa setuid...
- Puede hacerlo temporalmente configurando el euid a la identificación de usuario real y luego cambiando el uid a lo que desee. Y más tarde, cuando necesite recuperar el privilegio de root, puede configurarlo como root y el ID de usuario efectivo volverá a cambiar a root . Esto se debe a que la identificación de usuario guardada no se cambia.
- Puede eliminar los privilegios de forma permanente cambiando el uid directamente a un ID de usuario con menos privilegios. Después de esto, pase lo que pase, no podrá recuperar el privilegio de root.
Caso 1:
Después de que un programa setuid comienza a ejecutarse
1.seteuid(600);
2.setuid(1000);
3.setuid(0);
Para este caso, el privilegio de root se puede recuperar de nuevo.
+----+------+------------+
| uid|euid |saved-uid |
|----|------|------------|
1.|1000| 0 | 0 |
2.|1000| 600 | 0 |
3.|1000| 1000 | 0 |
4.|1000| 0 | 0 |
| | | |
+------------------------+
Caso 2:
Después de que un programa setuid comienza a ejecutarse ,
1.setuid(1000);
2.setuid(0);
+----+------+------------+
| uid|euid |saved-uid |
|----|------|------------|
1.|1000|0 | 0 |
2.|1000|1000 | 1000 |
| | | |
+------------------------+
En este caso, no puede recuperar el privilegio de root. Esto se puede verificar con el siguiente comando,
cat /proc/PROCID/tarea/PROCID/estado | menos
Uid: 1000 0 0 0
Gid: 1000 0 0 0
Este comando mostrará un Uid y Gid y tendrá 4 campos (los primeros tres campos son los que nos preocupan). Algo como lo anterior
Los tres campos representan uid, eid e ID de usuario guardado. Puede introducir una pausa (una entrada del usuario) en su programa setuid y verificar para cada paso el cat /proc/PROCID/task/PROCID/status | less
dominio. Durante cada paso, puede verificar que el uid guardado se modifique como se menciona.
Si su euid es root y cambia el uid, los privilegios se eliminan de forma permanente. Si la identificación de usuario efectiva no es root, la identificación de usuario guardada nunca se toca y puede recuperar el privilegio de root en cualquier momento que desee en tu programa
DESCRIPCIÓN setuid() establece el ID de usuario efectivo del proceso de llamada. Si el UID efectivo de la persona que llama es root, también se establecen el UID real y el ID de usuario establecido guardado.
En Linux, setuid() se implementa como la versión POSIX con la función _POSIX_SAVED_IDS. Esto permite que un programa de configuración de ID de usuario (que no sea raíz) elimine todos sus privilegios de usuario, realice un trabajo sin privilegios y luego vuelva a activar la ID de usuario efectiva original de una manera segura.
Si el usuario es root o el programa es set-user-ID-root, se debe tener especial cuidado. La función setuid() comprueba el ID de usuario efectivo de la persona que llama y, si es el superusuario, todos los ID de usuario relacionados con el proceso se establecen en uid. Después de que esto haya ocurrido, es imposible que el programa recupere los privilegios de root.
Por lo tanto, un programa set-user-ID-root que desee eliminar temporalmente los privilegios de root, asumir la identidad de un usuario sin privilegios y luego recuperar los privilegios de root no puede usar setuid(). Puede lograr esto con seteuid(2).
(del Manual de programadores de Linux, 2014-09-21, página setuid.2
)
¡Oh! Estas funciones son difíciles de usar correctamente.
La página de manual indica que setuid cambiará el uid real, guardado y efectivo. Entonces, después de llamar a setuid(1000), los tres cambian a 1000.
Ese es el caso si y solo si eres euid 0. En el momento en que llamas setuid(0)
, sin embargo, eres euid 1000 y salvado uid 0 (marque getresuid(2)
, por ejemplo). Es por eso que puedes recuperar privilegios.