Cómo ejecutar un LaunchAgent que ejecuta un script que causa fallos debido a la protección de integridad del sistema

3

Después de actualizar a Mojave, mi script de copia de seguridad basado en rsync ejecutado a través de un agente de inicio en ~ / Library / LaunchAgents, ya no podía leer algunos directorios en ~ / Library.

    
pregunta Channing Walton 01.10.2018 - 10:56

4 respuestas

1

He pasado algunas semanas tratando de resolver esto. Estoy de acuerdo en que la respuesta actualmente aceptada no es realmente una solución, no es mucho mejor que simplemente deshabilitar el SIP por completo.

Mi solución es una solución totalmente intrincada, pero no requiere la inclusión de bash en la lista blanca por completo. Actualización: Una solución un poco menos complicada a continuación.

Descripción general

  1. Empaquete una aplicación MacOS estándar que ejecute un script (un script bash en mi caso, que a su vez configura un entorno y ejecuta un binario separado que requiere FDA)
  2. Agregar esa aplicación a la FDA
  3. Ejecute la aplicación abriendo el archivo .app (ya sea haciendo doble clic a través de GUI o open /path/to/MyApp.app , pero no utilizando directamente el ejecutable almacenado en, por ejemplo, MyApp.app/Contents/Resources/ )

Para el Paso 1, puede empaquetar fácilmente su script como una aplicación utilizando herramientas integradas en MacOS como Automator.app o Script Editor, o Platypus también funciona.

El contenido de ejemplo de una aplicación de este tipo podría ser un AppleScript simple (en el Editor de secuencias de comandos) como:

on run
    do shell script "/usr/local/bin/bash /path/to/myscript.sh"
end run

Desde el Editor de secuencias de comandos, use el menú desplegable en el menú de guardar para guardar como una aplicación, luego CERRAR EDITOR DE ESCRITURA .

Agregue esta aplicación a Full Disk Access a través de System Preferences - > Security & Privacy .

NB: Si no guardó y cerró el Editor de secuencias de comandos antes de agregarlo a la FDA como se le indicó, parece que algún tipo de proceso invisible (¿salvado de fondo automatizado?) cambiará algo (algún tipo de la marca de tiempo o hash?) que se requiere para el acceso completo al disco, que puede resolver algunos errores intermitentes que fueron un gran dolor de cabeza. Entonces, si no hizo esto, elimine su aplicación de la FDA, guarde y cierre el Editor de secuencias de comandos, luego agregue de nuevo a la FDA.

Para su LaunchAgent, use algo como:

<string>/usr/bin/open</string>
<string>/path/to/MyApp.app</string>

Acceso raíz

Si su script de copia de seguridad necesita acceso a la raíz (por ejemplo, para realizar una copia de seguridad de los archivos 0600 de propiedad de la raíz), se encontrará con otro conjunto de soluciones piratas, ya que /usr/bin/open no ejecutará nada como raíz (incluso si especifique la clave UserName en una propiedad raíz de /Library/LaunchDaemons/ plist. (Me complacería abrir esta como una pregunta separada si corresponde, ya que creo que la solución a continuación deja mucho que desear).

Una opción para esto es agregar with administrator privileges en su AppleScript, pero esto requiere ingresar manualmente su contraseña, anulando el propósito de la copia de seguridad automática. Mi solución actual es:

  1. sudo visudo y le doy a mi usuario sin privilegios la capacidad de ejecutar mi script de copia de seguridad como sudo con NOPASSWD: (También especifico el hash del script para mejorar la seguridad, por ejemplo, myuser ALL=(ALL) NOPASSWD: sha256:hashgoeshere /path/to/myscript.sh )
  2. sudo chown root myscript.sh
  3. sudo chmod 0740 myscript.sh (4 por lo que aún se puede agregar a VCS)
  4. Cambie el AppleScript a do shell script "sudo -n /path/to/myscript.sh" y vuelva a guardarlo como MyApp.app
  5. Agregar MyApp.app a la FDA
  6. Cambiar mi script de launchd para abrir /path/to/MyApp.app
  7. Vuelva a cargar el script de launchd con launchctl y pruebe para asegurarse de que parece estar funcionando

Lecturas / detalles adicionales:

ACTUALIZACIÓN:

Después de algunas pruebas preliminares, parece que una solución un poco menos compleja es compilar un binario (que usa un lenguaje compilado) que llama a su script de bash. Agregue ese binario a la FDA y parece funcionar. Agrega a /Library/LaunchDaemons plist, que es propiedad de la raíz, y tienes una manera de llamarlo desde root sin toda la locura que se muestra arriba.

Ejemplo de script en Go:

// Runrestic provides a binary to run my restic backup script in MacOS Mojave with Full Disk Access
package main

import (
    "log"
    "os"
    "os/exec"
    "path/filepath"
)

func main() {
    ex, err := os.Executable()
    if err != nil {
        log.Fatal(err)
    }
    dir := filepath.Dir(ex)
    script := filepath.Join(dir, "restic-backup.sh")
    cmd := exec.Command("/usr/local/bin/bash", script)
    if err := cmd.Run(); err != nil {
        log.Fatal(err)
    }
}

Para seguridad, yo sudo chown root y sudo chmod 0700 el binario resultante antes de agregar a Full Disk Access (aunque es cierto que un atacante podría simplemente cambiar el script de bash que esto llama si se dejara sin protección).

    
respondido por el n8henrie 20.11.2018 - 17:06
3

Resolví esto de la siguiente manera:

Permitir que Bash tenga acceso completo al disco

  1. Abrir preferencias
  2. Ir a Seguridad & Preferencias
  3. Seleccione Acceso completo al disco en la lista de la izquierda
  4. Haz clic en el bloqueo para realizar cambios
  5. Haz clic en el botón + en la lista a la derecha
  6. Navega a la raíz de tu HD
  7. Presiona CMD + Shift +. para mostrar todos los elementos ocultos
  8. Selecciona / bin / bash
  9. Salir de las preferencias
  10. Reinicie el mac (no estoy seguro de si esto es realmente necesario)

Ejecuta tu script correctamente

El error que cometí fue que el agente de inicio ejecutó el script de esta forma:

<key>ProgramArguments</key>
<array>
    <string>/Users/channing/bin/backup.sh</string>
</array>

Haz esto en su lugar

<key>ProgramArguments</key>
<array>
    <string>/bin/bash</string>
    <string>/Users/channing/bin/backup.sh</string>
</array>

Reinicia tu agente:

launchctl unload ~/Library/LaunchAgents/backup.plist
launchctl load ~/Library/LaunchAgents/backup.plist

Alégrate.

    
respondido por el Channing Walton 01.10.2018 - 10:56
2

Editar:

Hice algunas pruebas más y parece que ya no puedo dar acceso completo al disco a ningún normal †. Escribí un script de shell mínimo [1], un binario mínimo que llama a ese script de shell [2] y un binario que intenta acceder a una ubicación segura [3]. Luego di todos estos scripts / ejecutables Full Disk Access , y también a /bin/sh por si acaso. Llamar a cualquiera de estos directamente a través del shell me da un error.

Luego me topé con una discusión en los foros de desarrolladores de Apple sobre Reglas para el acceso completo al disco . Parece que necesita un paquete de aplicaciones para otorgar los permisos de Acceso total al disco , lo que explica por qué otorgar acceso completo al disco a una aplicación de terminal permite que esa aplicación llame al ls ~/Library/Mail con éxito.
Sin embargo, no explica por qué puede otorgar acceso a /bin/bash y luego usarlo en su archivo launchd.plist para tener acceso completo al disco en su script de shell.

† binario simple, no un App Bundle que vive en /Applications

[1] /Users/me/access-test.sh :

#!/bin/sh
ls /Users/me/Library/Mail

[2] /Users/me/access-test.c :

#include <unistd.h>

int main(int argc, char *const argv[]) {
    const char *file = "/Users/me/access-test.sh";
    return execvp(file, argv);
}

[3] /Users/me/access-test-2.c :

#include <stdio.h>
#include <dirent.h>

int main(void) {
    DIR *dp;
    struct dirent *ep;

    dp = opendir("/Users/me/Library/Mail");
    if (dp == NULL) {
        perror("Couldn't open directory");
        return 1;
    } else {
        while ((ep = readdir(dp))) {
            puts(ep->d_name);
        }
        closedir (dp);
    }
}

Mi respuesta inicial, que resultó ser incorrecta:

Permita que su script de copia de seguridad tenga acceso completo al disco.

Vaya a Preferencias del sistema Seguridad & Privacidad Privacidad Acceso total al disco . Luego haga clic en el candado para realizar cambios, haga clic en el botón + y agregue su script.

La próxima vez que launchd inicie su script, tendrá acceso total al disco y pasará estos permisos a cualquier subproceso que genere, como rsync en su caso.

Esto funciona para cualquier ejecutable que desee iniciar utilizando un agente de inicio. Solo agregue el ejecutable (dado como valor para <key>Program</key> o el primer valor de <key>ProgramArguments</key> en su archivo plist ) a la lista de programas que tienen acceso total al disco .

    
respondido por el pyrrrat 30.10.2018 - 21:47
0

Tengo el mismo problema con algunas copias que activé a través de launchd que usan ídem. También estoy probando algunas pruebas para ver qué puedo agregar mínimamente en Full Disk Access para que funcione. Para los scripts de bash, me pregunto si es posible que pueda crear una aplicación AppleScript y usarla para otorgar el acceso y llamar al script. Puede darle una manera de otorgar acceso a esa aplicación específica y evitar el acceso a todas las cosas que podría ejecutar a través de bash

    
respondido por el mlp 12.10.2018 - 17:43

Lea otras preguntas en las etiquetas