¿Cómo uso capsh? Estoy tratando de ejecutar un ping sin privilegios, con capacidades mínimas
On febrero 13, 2021 by adminEstoy experimentando con capacidades, en Debian Gnu / Linux.
He copiado / bin / ping en mi directorio de trabajo actual. Como se esperaba, no funciona, originalmente se estableció como root.
Luego le doy a mi ping las capacidades mínimas (no root) haciendo sudo /sbin/setcap cap_net_raw=ep ./ping
, y mi ping funciona, como se esperaba.
Luego sudo /sbin/setcap -r ./ping
para revocar esa capacidad. Ahora no está funcionando como se esperaba.
Ahora intento que el ping funcione usando capsh
.
capsh
no tiene privilegios, así que necesito ejecutarlo como root, pero luego eliminar root y por lo tanto todos los demás privilegios.
Creo que también necesito secure-keep-caps
, esto no está documentado en capsh
, pero está en la capacidad manual. Obtuve los números de bits de /usr/include/linux/securebits.h
. Parecen correctos, ya que la salida de --print
muestra que estos bits son correctos.
He estado jugando durante horas, hasta ahora tengo esto.
sudo /sbin/capsh --keep=1 --secbits=0x10 --caps="cap_net_raw+epi" == --secbits=0x10 --user=${USER} --print -- -c "./ping localhost"
Sin embargo, ping
errores con ping: icmp open socket: Operation not permitted
, esto es lo que sucede cuando no tiene la capacidad. Además, el --print
muestra Current: =p cap_net_raw+i
, esto no es suficiente, necesitamos e
.
sudo /sbin/capsh --caps="cap_net_raw+epi" --print -- -c "./ping localhost"
establecerá la capacidad en Current: = cap_net_raw+eip
esto es correcto, pero nos deja como root
.
Edit-1
Ahora probé sudo /sbin/capsh --keep=1 --secbits=0x11 --caps=cap_net_raw+epi --print -- -c "touch zz; ./ping -c1 localhost;"
Esto produce:
touch: cannot touch `zz": Permission denied ping: icmp open socket: Operation not permitted
El primer error se espera como secure-noroot: yes
Pero el segundo no es Current: = cap_net_raw+eip
Edit-2
Si pongo ==
antes de --print
, ahora muestra Current: = cap_net_raw+i
, de modo que eso explica el error anterior, pero no por qué estamos perdiendo capacidad al cambiar de root, pensé que secure-keep-caps
debería arregla eso.
Edit-3
Por lo que puedo ver, estoy perdiendo Efectivo (e) y Permitido (p), cuando se llama a exec. Se esperaba esto, pero pensé que asegurar-mantener-tapas, debería evitar que se pierdan. ¿Me estoy perdiendo algo?
Edit-4
He estado investigando más y leyendo el manual nuevamente. Parece que normalmente las capacidades de e
y p
se pierden cuando: cambia de usuario root
(o aplique secure-noroot
, convirtiendo así a root en un usuario normal), esto se puede anular con secure-keep-caps
; cuando llamas a exec
, por lo que puedo decir, esto es invariante.
Por lo que puedo decir, está funcionando de acuerdo con el manual. Por lo que puedo decir, no hay forma de hacer nada útil con capsh
. Por lo que puedo decir, para usar las capacidades es necesario: usar las capacidades de los archivos o tener un programa consciente de las capacidades, que no use exec
. Por lo tanto, no hay contenedor privilegiado.
Así que ahora mi pregunta es qué me estoy perdiendo, para qué sirve capsh
.
Edit-5
He agregado una respuesta sobre las capacidades ambientales. Quizás capsh
también se pueda usar con capacidades heredadas, pero para que sean útiles, estas deberían estar configuradas en el archivo ejecutable. No veo cómo capsh puede hacer algo útil sin capacidades ambientales, o permitir capacidades heredadas.
Versiones:
-
capsh
del paquetelibcap2-bin
versión1:2.22-1.2
- antes de edit-3 tomé el último
capsh
degit://git.debian.org/collab-maint/libcap2.git
y comencé a usarlo. -
uname -a
Linux richard-laptop 3.2.0-4-amd64 #1 SMP Debian 3.2.65-1+deb7u2 x86_64 GNU/Linux
User-land es de 32 bits.
Comentarios
Respuesta
Las capacidades son propiedades de los procesos. Tradicionalmente hay tres conjuntos:
- Capacidades permitidas ( p ): capacidades que pueden «activada» en el proceso actual.
- Capacidades efectivas ( e ): capacidades que se pueden utilizar actualmente en el proceso actual.
- Capacidades heredables ( i ): capacidades de archivo que pueden heredarse.
Los programas que se ejecutan como root siempre tienen todas las capacidades permitidas y efectivas, por lo que «agregar» más capacidades no tiene un efecto notable. (El conjunto de capacidades heredables normalmente está vacío.) Con setcap cap_net_raw+ep ping
, habilita estas capacidades de forma predeterminada para cualquier usuario que ejecute este programa.
Desafortunadamente, estas capacidades están vinculadas al archivo ejecutado y no se retienen después de ejecutar un nuevo proceso hijo. Linux 4.3 introdujo capacidades ambientales que permiten que las capacidades sean heredadas por procesos secundarios. (Consulte también Transformación de capacidades durante execve () en capacidades (7) .)
Mientras juega con capacidades, tenga en cuenta estos errores:
- Cuando se cambia el usuario de root a no root, las capacidades efectivas y permitidas se borran (consulte Efecto de los cambios de ID de usuario en las capacidades en capacidades (7) ). Puede utilizar la opción
--keep=1
decapsh
para evitar borrar los conjuntos. - El conjunto de capacidades ambientales se borra cuando cambiar los ID de usuario o grupo. Solución: agregue las capacidades ambientales después de cambiar la ID de usuario, pero antes de ejecutar un proceso secundario.
- Una capacidad solo se puede agregar a las capacidades ambientales establecer si ya está en el conjunto de capacidades permitidas y heredables.
Desde libcap 2.26, el programa capsh
ganó la capacidad de modificar las capacidades ambientales a través de opciones como --addamb
( confirmar ). Tenga en cuenta que el orden de las opciones es significativo. Ejemplo de uso:
sudo capsh --caps="cap_net_raw+eip cap_setpcap,cap_setuid,cap_setgid+ep" \ --keep=1 --user=nobody --addamb=cap_net_raw -- \ -c "./ping -c1 127.0.0.1"
Sugerencia: puede agregar la opción --print
en cualquier lugar de la capsh
línea de comandos y ver su estado de capacidades actual.
Nota: cap_setpcap
es necesario para --addamb
mientras que cap_setuid,cap_setgid
son necesarios para la opción --user
.
Comentarios
- ¿Qué número de versión específico de libcap tiene capsh –addamb? Las notas de la versión 2.32 mencionaban nuevas características de mayúsculas, pero las palabras eran vagas.
- @ 把 友情 留 在 无 盐 Cuando la respuesta se escribió originalmente, solo git master la admitía. Desde entonces, libcap 2.26 se ha lanzado con soporte para la opción
--addamb
. He actualizado la respuesta en consecuencia. - Desafortunadamente, estas capacidades están vinculadas al archivo ejecutado y no se retienen después de ejecutar un nuevo proceso hijo. – por proceso hijo Normalmente pienso en
fork(2)
, que hereda las capacidades. Soloexecve(2)
no ‘ t hereda las capacidades, pero no ‘ no crea un niño proceso. ¿Me equivoco? - Citando
man capabiltiies
: Un niño creado a través defork(2)
hereda copias de su padre ‘ conjuntos de capacidades.
Respuesta
La respuesta de Lekensteyn parece precisa y completa, pero intentaré proporcionar otra explicación desde un ángulo diferente que tratará de enfatizar el problema que resuelve el conjunto de capacidades ambientales.
Cuando ejecuta sudo capsh --user=<some_user> --
Hay 2 llamadas al sistema de interés que hacen que las capacidades se vuelvan a calcular (y posiblemente se eliminen):
-
setuid
: segúnman capabilities
:
SECBIT_KEEP_CAPS La configuración de esta bandera permite un hilo que tiene uno o más 0 UID para retener sus capacidades cuando cambia todos sus UID a un valor distinto de cero. Si este indicador no está establecido, entonces dicho interruptor de UID hace que el hilo pierda todas las capacidades.
En otras palabras, en nuestro capsh
comando anterior, debemos asegurarnos de que SECBIT_KEEP_CAPS esté configurado durante el setuid
llamada al sistema. De lo contrario, se perderán todas las capacidades. Esto es lo que hace --keep=1
. Así que ahora el comando se convierte en sudo capsh --user=<some_user> --keep=1 --
-
execve
: si use la opción--keep=1
, todos los conjuntos de capacidades (efectivos, permitidos, heredables) se conservan hasta laexecve
llamada al sistema, sin embargoexecve
hace que las capacidades se vuelvan a calcular (para usuarios no root) también, y en de una forma no tan obvia.En resumen, antes de la adición del conjunto de capacidades ambientales , para que la capacidad esté en un subproceso «s» permitido » establecido después de una llamadaexecve
, ya sea:- El archivo debe tener esa capacidad en su conjunto «permitido» . se puede hacer con
setcap cap_net_raw+p /bin/bash
. Hacer esto inutiliza todo el ejercicio ya que los conjuntos de capacidades del hilo (distintos del conjunto delimitador) ya no tienen ningún efecto. - Tanto el archivo como el hilo deben tener esa capacidad en sus conjuntos «heredables» . Puede pensar que
setcap cap_net_raw+i
funcionaría, pero resulta queexecve
hace que se eliminen los permisos inherentes de un hilo cuando lo llama un usuario sin privilegios (que actualmente somos gracias asetuid
). Por lo tanto, no hay forma de satisfacer esta condición como usuario sin privilegios.
- El archivo debe tener esa capacidad en su conjunto «permitido» . se puede hacer con
Las capacidades ambientales introducidas en Linux 4.3 hacen posible que un hilo retenga sus capacidades incluso después de un setuid
a un usuario sin privilegios seguido de un execve
, sin tener que depender de las capacidades del archivo.
Respuesta
Puede haber un error / característica en el kernel. Ha habido cierta discusión:
- https://bugzilla.altlinux.org/show_bug.cgi?id=16694
- http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-03/5224.html
No tengo ni idea, si se ha hecho algo uno, para solucionarlo.
No me malinterpretes, el comportamiento actual es seguro. Pero es tan seguro que interfiere con cosas que deberían parecer funcionar.
Editar: De acuerdo con http://man7.org/linux/man-pages/man7/capabilities.7.html hay un nuevo conjunto de capacidades Ambient (desde Linux 4.3). Parece que esto permitirá lo que se necesita.
Respuesta
Un ligero ajuste de la respuesta de Lekensteyn produce una invocación más corta para kernels recientes:
sudo /usr/sbin/capsh --keep=1 --user=$USER \ --inh=cap_net_raw --addamb=cap_net_raw -- \ -c "./ping -c1 localhost"
Nota: Dependiendo de su archivo sudoers, esto puede hacer un desastre en su entorno (por ejemplo, cambiar HOME). capsh cambiará su uid, pero no hará nada para revertir los cambios del entorno de sudo.
Entonces, ¿qué está pasando aquí? Echemos un vistazo:
-
sudo /usr/sbin/capsh
: comenzamos como root, que tiene todas las capacidades en sus conjuntos efectivo (puede hacer esto) y permitido (puede agregar esto a efectivo), pero nada en los otros conjuntos . Cubriremos esos otros conjuntos en un momento. -
--keep=1
: Por razones de seguridad (léase: heredado), las capacidades normalmente no se heredan a través de root- > interruptores de ID no root. Esta marca habilita una función, conocida comoSECBIT_KEEP_CAPS
, que permite esto. Vale la pena señalar que se borra automáticamente al ejecutar , lo cual es una buena idea. -
--user=$USER
: Ahora que no perderemos todas nuestras capacidades en el cambio de UID, salimos de root. Gracias aSECBIT_KEEP_CAPS
, retenemos privilegios similares a los de root, lo que nos permite alterar aún más nuestras capacidades. -
--inh=cap_net_raw
: Esto agrega nuestra capacidad de destino al conjunto heredable, porque «no puede crear un ambiente de capacidad (vea el siguiente elemento) si no es heredable. -
--addamb=cap_net_raw
: Aunque «hemos solicitadoSECBIT_KEEP_CAPS
,execve
de un binario sin privilegios (sin setuid / setgid / setcap) seguirá borrar nuestras capacidades, lo que resulta en ningún privilegio. Linux 4.3 agregó el conjunto ambiental, que se vuelve a agregar a los conjuntos efectivos y permitidos al ejecutar binarios sin privilegios. ¡Perfecto! -
-- -c ...
: Habiendo configurado todo, ejecutamos bash con estos argumentos. Los conjuntos de capacidades se borran (porque bash no tiene privilegios), el conjunto ambiental se vuelve a agregar y ¡voilá! Tenemos el permiso necesario para hacer open raw sockets.
Puede verificar esto usando el argumento a capsh, lo que hace que se ejecute con el resto de la línea de comando:
sudo /usr/sbin/capsh --keep=1 --user=$USER \ --inh=cap_net_raw --addamb=cap_net_raw == --print Current: = cap_net_raw+eip
Lo que significa que tenemos cap_net_raw como efectivo (puede hacerlo), heredable (puede pasarlo a procesos secundarios) y permitido (puede obtenerlo). Y ninguna otra capacidad en ninguno de esos.
Para obtener más información sobre las capacidades y cómo funcionan, su mejor opción es la página de manual de capacidades (7) . Específicamente el encabezado Transformation of capabilities during execve()
.
Comentarios
- ¿Qué quieres decir con Esto está hecho? temprano porque requiere una serie de capacidades adicionales que pueden ‘ t desaparecer hasta que ‘ se haya completado. ?En su caso, está ejecutando como » root «, por lo que incluso así
--user
wasn ‘ t cambiado, ¿’ todavía tendrá las capacidades necesarias más adelante? - ¡Gracias por señalar eso! Una versión anterior de esta línea de comando eliminó explícitamente los privs, por lo que fue necesario establecer un setuid antes de eso. Ahora que los privilegios se eliminan implícitamente como parte de exec, ‘ no es necesario.
capsh
del repositorio de collab-maint no le habría dado el «último»capsh
, el paquete Debian todavía no es compatible capacidades ambientales. Upstream 2.27 sí lo hace.capsh
, en ausencia de ambiente (como era originalmente). Qué me estoy perdiendo. Debe tener un uso.