¿Puedo evitar que se cree una carpeta de cierto nombre?

16

Estoy trabajando en una aplicación web LAMP y hay un proceso programado en algún lugar que sigue creando una carpeta llamada shopen la raíz del sitio. Cada vez que esto aparece causa conflictos con las reglas de reescritura en la aplicación, no es bueno.

Hasta que encuentre el script ofensivo, ¿hay alguna manera de evitar que shopse cree una carpeta llamada en la raíz? Sé que puedo cambiar los permisos en una carpeta para evitar que se cambie su contenido, pero no he encontrado una manera de evitar que se cree una carpeta con un nombre determinado.

Andrés
fuente
44
Para saber qué está haciendo la creación, puede habilitar la auditoría .
Andrew Henle

Respuestas:

30

No puede, dado que el usuario que crea el directorio tiene permiso suficiente para escribir en el directorio principal.

En su lugar, puede aprovechar la inotifyfamilia de llamadas al sistema proporcionadas por el kernel de Linux, para observar la creación (y opcionalmente mv-ing) del directorio shopen el directorio dado, si se creó (u opcionalmente mv-ed), rmel directorio.

El programa de espacio de usuario que necesita en este caso es inotifywait(viene con inotify-tools, instálelo primero si es necesario).


Suponiendo que el directorio shopresidiría en el /foo/bardirectorio, configuremos un monitoreo para la /foo/bar/shopcreación, e rminstantáneamente si se crea:

inotifywait -qme create /foo/bar | \
             awk '/,ISDIR shop$/ { system("rm -r -- /foo/bar/shop") }'
  • inotifywait -qme create /foo/barvigila el /foo/bardirectorio para cualquier archivo / directorio que pueda crearse, es decir, observe cualquier createevento

  • Si se crea, awk '/,ISDIR shop$/ { system("rm -r -- /foo/bar/shop") }'comprueba si el archivo es un directorio y el nombre es shop( /,ISDIR shop$/), de ser así, rmel directorio ( system("rm -r -- /foo/bar/shop"))

Debe ejecutar el comando como un usuario que tiene permiso de escritura en el directorio /foo/barpara eliminarlo del shopdirectorio.


Si también desea monitorear las mvoperaciones de llamada, agregue también la observación de moved_toeventos:

inotifywait -qme create,moved_to /foo/bar | \
             awk '/,ISDIR shop$/ { system("rm -r -- /foo/bar/shop") }'

Solo para tener en cuenta, si está buscando un archivo, no un directorio, llamado shop:

inotifywait -qme create /foo/bar | \
                 awk '$NF == "shop" { system("rm -- /foo/bar/shop") }'

inotifywait -qme create,moved_to /foo/bar | \
                 awk '$NF == "shop" { system("rm -- /foo/bar/shop") }'
heemayl
fuente
2
Además, si está acostumbrado inotifywaita hacer esto, también es posible que el disparador también pueda atrapar el proceso conps -ef
roaima
30

Para responder literalmente en función de la cuestión de evitar que se cree una carpeta de cierto nombre.

touch shop

No puede crear un directorio si existe un archivo con un nombre idéntico

mkdir: cannot create directory ‘shop’: File exists

Miati
fuente
66
Esto * puede no * ser suficiente. mkdir puede no hacerlo, pero se puede hacer. Sin embargo, es un buen primer intento.
coteyr el
99
En sistemas Linux, utilícelo chattr +i shoppara hacerlo inmutable. Hasta que se elimine la bandera inmutable, ni siquiera se puede renombrar / eliminar.
R .. GitHub DEJA DE AYUDAR AL HIELO
1
Este es un pequeño truco inteligente, no del todo adecuado para mi situación, pero una idea inteligente para ciertas circunstancias 👍
Andrew
1
@R .. interesante. Esperaba rename(2)seguir funcionando, ya que el nombre no es parte del inodo, pero no lo es. La búsqueda rápida en Internet no revela por qué. ¿Alguna pista?
domen
@domen: Porque eso es parte del propósito del atributo "inmutable". Sospecho que se necesita un trabajo extra no trivial a nivel de implementación para evitar que renamefuncione.
R .. GitHub DEJA DE AYUDAR AL HIELO
4

¿Qué hay de secuestrar mkdirsyscall con LD_PRELOAD...?

$ ls
test.c
$ cat test.c 
#define _GNU_SOURCE

#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dlfcn.h>

typedef int (*orig_mkdir_func_type)(const char *path, mode_t mode);

int mkdir(const char *path, mode_t mode) {
    if(!strcmp(path, "shop")) return 1;

    orig_mkdir_func_type orig_func;
    orig_func = (orig_mkdir_func_type)dlsym(RTLD_NEXT, "mkdir");
    return orig_func(path, mode);
}
$ gcc -shared -fPIC test.c -o test.so
$ LD_PRELOAD='./test.so' mkdir test
$ LD_PRELOAD='./test.so' mkdir shop
mkdir: cannot create directory ‘shop’: No such file or directory
$ ls
test  test.c  test.so

Tenga en cuenta que dentro de este controlador puede registrar el PID del proceso que desea crear este directorio:

$ cat test.c 
#define _GNU_SOURCE

#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dlfcn.h>

typedef int (*orig_mkdir_func_type)(const char *path, mode_t mode);

int mkdir(const char *path, mode_t mode) {
    if(!strcmp(path, "shop")) {
        FILE* fp = fopen("/tmp/log.txt", "w");
        fprintf(fp, "PID of evil script: %d\n", (int)getpid());
        fclose(fp);
    }

    orig_mkdir_func_type orig_func;
    orig_func = (orig_mkdir_func_type)dlsym(RTLD_NEXT, "mkdir");
    return orig_func(path, mode);
}
$ gcc -shared -fPIC test.c -o test.so
$ LD_PRELOAD='./test.so' mkdir shop
$ cat /tmp/log.txt 
PID of evil script: 8706

Debe colocar esto en la ~/.bashrcraíz (o quien esté ejecutando su aplicación) para asegurarse de que se utilizará:

export LD_PRELOAD=/path/to/test.so
Nykakin
fuente
2
esto no debería tener un voto negativo, es una solución y una buena
cat
44
Está usando una maleta nuclear para abrir una lata de frijoles. Pero bueno, al menos se cocinarán ...
Lightness compite con Monica el
2
@cat: no estoy de acuerdo. LD_PRELOADLos trucos como este son básicamente incorrectos, y a menos que sepas lo que estás haciendo, pueden dañar el programa en el que los cargas rompiendo propiedades como la seguridad de la señal asíncrona de la función que estás reemplazando.
R .. GitHub DEJA DE AYUDAR AL HIELO
1
Además, creo que fopendebería tener en "a"lugar de "w", por lo que puede preservar los registros anteriores
cat
2
Esto tampoco funcionará si un código incorrecto llama a syscall directamente, no a través de libc. O si el código incorrecto está vinculado estáticamente.
domen
3

(Hubiera comentado la respuesta de Miati pero no recuerdo mi cuenta anterior y no tengo suficiente reputación en esta nueva ...)

Puede bloquear la creación creando un archivo y luego cambiando los atributos del archivo.

$ sudo touch shop
$ sudo chattr +i shop

Entonces, cualquier intento de hacer algo con ese archivo se bloqueará, incluso si el usuario se convierte en root.

$ rm shop
rm: remove write-protected regular empty file ‘shop’? y
rm: cannot remove ‘shop’: Operation not permitted
$ sudo rm shop
rm: cannot remove ‘shop’: Operation not permitted
N. Clements
fuente
2
Si conoce el nombre / dirección de correo electrónico de su cuenta anterior, puede solicitar una fusión de cuenta desde el formulario de contacto vinculado en la parte inferior de cada página .
wizzwizz4
Además, ¿por qué no nos dice cómo se relaciona esto con la otra respuesta, en lugar de por qué decidió publicar?
jpaugh
2

Cree un enlace simbólico que apunte a una ubicación no existente dentro de un directorio no existente. Esto tiene algunas implicaciones divertidas:

$ ln -s non-existent/foobar foo
$ ls -ln
total 0
lrwxrwxrwx 1 1000 1000 19 Okt  4 17:17 foo -> non-existent/foobar
$ mkdir foo
mkdir: cannot create directory ‘foo’: File exists
$ cat foo
cat: foo: No such file or directory
$ echo foo > foo
zsh: no such file or directory: foo
  1. mkdir, link y otros fallarán con EEXIST(El archivo existe).
  2. Intentar abrir la ruta para leer, escribir o anexar fallará ENOENT(No existe tal archivo o directorio)
  3. El uso de stat (2) (no lstat (2) o stat (1)) en la ubicación también falla ENOENT. Por supuesto, lstat devolverá la información sobre el enlace simbólico.

Esto tiene dos ventajas sobre algunas de las otras soluciones propuestas aquí: (a) no necesita un servicio en ejecución que rastrea la creación del directorio y (b) el nombre parece no existir para la mayoría de los comandos.

Tendrá que intentarlo, pero sospecho que, independientemente de las reglas de reescritura que tenga, no usan lstat u otros comandos sin referencia, lo que hace que fallen.

Jonas Schäfer
fuente