¿Encuentra archivos que un usuario no puede leer?

12

Quiero encontrar archivos que un usuario en particular no podrá leer.

Suponga que el nombre de usuario es "user123" y están en un grupo llamado "user123". Quiero encontrar archivos que, si son propiedad del usuario123, tienen activado u + r; en caso de que, si el archivo es el usuario del grupo 123, debería tener activado g + r; si no puede tener o + r encendido.

Como GNU find tiene "legible", podría hacer esto:

sudo -u user123 find /start ! -readable -ls

Sin embargo, el proceso debe ser ejecutado por un usuario que no tiene acceso a sudo. Por lo tanto, intenté esto: (no marca o + r pero eso no es importante en este punto)

find /start \( -user user123 ! -perm -u=r  \) -o \( -group user123 ! -perm -g=r  \) -ls

pero enumera este archivo:

272118    4 -rw-------   1 user123   user123       3243 Jul  3 19:50 /start/blah/blah/file.txt

Este archivo es el único archivo /startque pertenece al usuario123 con g=rdesactivado. Es como si find está interpretando el -u=ras -g=r.

Decidí intentar invertir la lógica y probar not ( truth )en su lugar:

find /etc/puppet ! \( \( -user puppet -perm -u=r  \) -o \( -group puppet -perm -g=r \) -o \( -perm -o=r \) \)  -ls

¡Eso funciona!

¿Por qué findfalló el original ? ¿Es un error en find(poco probable) o la lógica es incorrecta?

Actualización: me equivoqué de lógica. Como se señala a continuación, ya que! (A || B || C) == (! A &&! B &&! C) estas son las dos declaraciones equivalentes:

find /start ! \( \( -user user123 -perm -u=r \) -o \( -group user123 -perm -g=r \) -o \( ! \( -user user123 -o -group user123 \) -perm -o=r \) \) -ls
find /start ! \( -user user123 -perm -u=r \) ! \( -group user123 -perm -g=r \) ! \( ! \( -user user123 -o -group user123 \) -perm -o=r \) -ls

Mi objetivo no era tener que probar el usuario / grupo dos veces. Lo que realmente necesito es una estructura if-then-else más complicada, que probablemente solo sería posible si hubiera un operador -xor. Podría construir un xor a partir de y / o / no, pero sería más complejo que las dos soluciones anteriores.

TomOnTime
fuente
1
Incluso la segunda lógica es incorrecta, porque diría que puppettiene acceso a un archivo con --wxrwxrwx puppet puppet.
Stéphane Chazelas

Respuestas:

7

La lógica está mal. Está pensando que este archivo no debería haberse incluido en la lista porque es propiedad user123y tiene el rconjunto de bits del usuario . Sin embargo, aparece en la lista porque coincide con el segundo criterio (es propiedad del grupo user123y tiene el rbit unset no establecido).

Su segunda versión funciona debido a una de las leyes de De Morgan : negar el OR lógico de un grupo de declaraciones es lógicamente equivalente a AND la negación de las declaraciones individuales. En otras palabras:

 ! ( A || B || C ) == ( !A && !B && !C )

Entonces, el trabajo findestá buscando un archivo que

  • No es (propiedad del usuario user123y legible por dicho usuario) Y
  • No es (propiedad del grupo user123y legible por dicho grupo) Y
  • No es legible en el mundo.

mientras que el primero findbusca un archivo que

  • Es propiedad del usuario user123y no puede ser leído por dicho usuario O
  • Es propiedad del grupo user123y no es legible por dicho grupo O (si lo ha completado)
  • No es legible por el mundo

Por lo tanto, un archivo que coincida con CUALQUIERA de los 3 criterios anteriores (y no necesariamente todos) aparecería como lo ha visto.

Editar

Por cierto (después de ver su perfil), soy un gran admirador de su libro O'Reilly :)

Joseph R.
fuente
Gracias por el analisis. Sí, fue una aplicación errónea de la ley de Morgan. Estaba tratando de hacerlo, ( !A && !B && !C )pero me mudé !al interior de cada parte, lo que no es válido. ¡Gracias!
TomOnTime
PD: ¡Me alegra que seas fanático de mi libro! Tengo curiosidad por saber en qué idioma lo lees.
TomOnTime
@TomOnTime English, por supuesto. Intento leer cualquier libro en su idioma original si puedo evitarlo.
Joseph R.
8

Hay muchas más cosas a tener en cuenta para verificar si un usuario tiene acceso a un archivo a través de una ruta determinada:

  • El dueño del archivo
  • el grupo del archivo
  • las ACL en el archivo
  • los uid, gid y gids suplementarios del usuario
  • buscar acceso a cualquier componente de ruta que conduzca a ese archivo.
  • si el archivo es un enlace simbólico
  • los permisos se aplican de manera diferente para los usuarios de id 0.
  • posiblemente más funciones de seguridad como SELinux ...

A menos que realmente cambie todos los uids y gids a los del usuario y compruebe, es muy difícil implementar la misma lógica que lo que hace el sistema.

Con zsh, podría hacer (como root):

readable() (
  USERNAME=$u
  [ -r "$REPLY" ]
)
u=some-user
print -rl -- **/*(DoN^+readable)

O con perl:

find . -print0 | sudo -u some-user perl -Mfiletest=access -l -0ne '
  print unless -r'

Es decir, en ambos casos, descienda el árbol de directorios rootpero pruebe el acceso a los archivos como el usuario correspondiente.

Ejecutar find -readablecomo some-userno lo hará en los casos ya que no podrá pasar los directorios para los que el usuario no tiene acceso o no tiene permiso de lectura (pero posiblemente acceso).

Incluso cuando solo considera el permiso y la propiedad del archivo en sí (y no las ACL o los componentes de la ruta ...), necesita al menos (aquí la sintaxis de GNU):

u=some-user; g=$(id -G "$u" | sed 's/ / -o -group /g'); IFS=" "
find . ! \( -user "$u" -perm -u=r -o \
          ! -user "$u" \( -group $g \) -perm -g=r -o \
          ! -user "$u" ! \( -group $g \) -perm -o=r \)

La idea es que si el archivo es propiedad del usuario, todos los demás permisos son irrelevantes. Si no es así, si el archivo es propiedad de un grupo de cualquiera de los grupos de usuarios, entonces el permiso "otro" es irrelevante.

Stéphane Chazelas
fuente
1
Buen punto sobre ACL y otros factores. La única evaluación 100% correcta es access()porque usa el mismo código de kernel que open(). Por sudo -u user123 find /start -readablelo tanto, es la mejor solución si sudoes una opción.
TomOnTime
1
@TomOnTime. Bueno, no, si lo usa sudo -u user123 find -readable, no informará archivos en directorios que no puede ingresar, o en directorios que no puede leer (por lo que habrá falsos negativos y falsos positivos). Es por eso que se sugiere emplear zshpara descender el árbol de directorios como root y hacer access()( [ -r ... ]) como el usuario actual (ajuste $USERNAMEde zshcambios todos los UID y GID como sudolo haría).
Stéphane Chazelas