Puis-je empêcher la création d'un dossier d'un certain nom?

16

Je travaille sur une application Web LAMP et il y a un processus planifié quelque part qui continue de créer un dossier appelé shopà la racine du site. Chaque fois que cela apparaît, cela provoque des conflits avec les règles de réécriture dans l'application, ce n'est pas bon.

Jusqu'à ce que je trouve le script incriminé, existe-t-il un moyen d'empêcher la shopcréation d' un dossier appelé à la racine? Je sais que je peux modifier les autorisations sur un dossier pour empêcher la modification de son contenu, mais je n'ai pas trouvé de moyen d'empêcher la création d'un dossier d'un certain nom.

Andrew
la source
4
Pour savoir ce que fait la création, vous pouvez activer l'audit .
Andrew Henle

Réponses:

30

Vous ne pouvez pas, étant donné que l'utilisateur qui crée le répertoire dispose des autorisations suffisantes pour écrire sur le répertoire parent.

Vous pouvez à la place tirer parti de la inotifyfamille d'appels système fournis par le noyau Linux, pour surveiller la création (et éventuellement le mv-ing) du répertoire shopdans le répertoire donné, s'il est créé (ou éventuellement mv-ed), rmle répertoire.

Le programme d'espace utilisateur dont vous avez besoin dans ce cas est inotifywait(livré avec inotify-tools, installez-le d'abord si nécessaire).


En supposant que le répertoire shoprésiderait dans le /foo/barrépertoire, définissons une surveillance pour la /foo/bar/shopcréation et rminstantanément s'il est créé:

inotifywait -qme create /foo/bar | \
             awk '/,ISDIR shop$/ { system("rm -r -- /foo/bar/shop") }'
  • inotifywait -qme create /foo/barsurveille le /foo/barrépertoire pour tout fichier / répertoire qui pourrait être créé, c'est-à-dire surveillez tout createévénement

  • S'il est créé, awk '/,ISDIR shop$/ { system("rm -r -- /foo/bar/shop") }'vérifie si le fichier se trouve être un répertoire et que le nom est shop( /,ISDIR shop$/), si c'est rmle répertoire ( system("rm -r -- /foo/bar/shop"))

Vous devez exécuter la commande en tant qu'utilisateur disposant d'une autorisation d'écriture sur le répertoire /foo/barpour la suppression du shoprépertoire.


Si vous souhaitez également surveiller les mvopérations de contrôle , ajoutez également la fonction de surveillance des moved_toévénements:

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

Juste pour noter, si vous cherchez un fichier, pas un répertoire, nommé 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
la source
2
De plus, si vous utilisez inotifywaitpour ce faire, il est également possible que le déclencheur puisse également intercepter le processus avecps -ef
roaima
30

Répondre littéralement à la question d'empêcher la création d' un dossier d'un certain nom.

touch shop

Vous ne pouvez pas créer un répertoire si un fichier avec un nom identique existe

mkdir: cannot create directory ‘shop’: File exists

Miati
la source
6
Ce * n'est peut-être pas * suffisant. mkdir peut ne pas le faire, mais cela peut être fait. C'est un bon premier essai cependant.
coteyr du
9
Sur les systèmes Linux, utilisez chattr +i shoppour le rendre immuable. Tant que le drapeau immuable n'est pas supprimé, il ne peut même pas être renommé / supprimé.
R .. GitHub STOP HELPING ICE
1
C'est une petite astuce intelligente, pas tout à fait adaptée à ma situation, mais une idée intelligente dans certaines circonstances
Andrew
1
@R .. intéressant. Je m'attendais rename(2)à continuer à travailler, car le nom ne fait pas partie de l'inode, mais ce n'est pas le cas. Une recherche rapide sur Internet ne révèle pas pourquoi. Des indices?
domen
@domen: Parce que cela fait partie du but de l'attribut "immuable". Je soupçonne qu'il faut un travail supplémentaire non trivial au niveau de la mise en œuvre pour empêcher renamede travailler.
R .. GitHub STOP HELPING ICE
4

Qu'en est-il du détournement de mkdirsyscall avec 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

Notez qu'à l'intérieur de ce gestionnaire, vous pouvez enregistrer le PID du processus qui souhaite créer ce répertoire à la place:

$ 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

Vous devez le placer dans ~/.bashrcroot (ou celui qui exécute votre application) pour vous assurer qu'il sera utilisé:

export LD_PRELOAD=/path/to/test.so
Nykakin
la source
2
cela ne devrait pas avoir un downvote, c'est une solution et une bonne
cat
4
Il utilise une valise nucléaire pour ouvrir une boîte de haricots. Mais bon au moins ils seront cuisinés ...
Courses de légèreté avec Monica
2
@cat: Je ne suis pas d'accord. LD_PRELOADLes hacks comme celui-ci sont fondamentalement toujours faux, et à moins que vous ne sachiez ce que vous faites, ils peuvent gravement casser le programme dans lequel vous les chargez en cassant des propriétés comme la sécurité du signal asynchrone de la fonction que vous remplacez.
R .. GitHub STOP HELPING ICE
1
De plus, je pense que fopendevrait avoir à la "a"place de "w", afin qu'il puisse conserver les journaux précédents
cat
2
Cela ne fonctionnera pas non plus si un mauvais code appelle directement le syscall, pas via libc. Ou si le mauvais code est lié statiquement.
domen
3

(Aurait commenté la réponse de Miati mais ne se souvient pas de mon ancien compte et n'a pas assez de réputation sur ce nouveau ...)

Vous pouvez bloquer la création en créant un fichier, puis en modifiant les attributs du fichier.

$ sudo touch shop
$ sudo chattr +i shop

Ensuite, toute tentative de faire quoi que ce soit avec ce fichier sera bloquée - même si l'utilisateur devient 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
la source
2
Si vous connaissez le nom / l'adresse e-mail de votre ancien compte, vous pouvez demander une fusion de compte à partir du formulaire de contact lié en bas de chaque page .
wizzwizz4
Aussi, pourquoi ne pas nous dire en quoi cela est lié à l'autre réponse, plutôt que pourquoi vous avez décidé de poster?
jpaugh
2

Créez un lien symbolique pointant vers un emplacement inexistant dans un répertoire inexistant. Cela a des implications amusantes:

$ 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 et autres échoueront avec EEXIST(le fichier existe).
  2. Tenter d'ouvrir le chemin pour la lecture, l'écriture ou l'ajout échouera avec ENOENT(Aucun fichier ou répertoire de ce type)
  3. L'utilisation de stat (2) (pas lstat (2) ou stat (1)) sur l'emplacement échoue également avec ENOENT. lstat renverra bien sûr les informations sur le lien symbolique.

Cela présente deux avantages par rapport à certaines des autres solutions proposées ici: (a) vous n'avez pas besoin d'un service en cours d'exécution qui suit la création du répertoire et (b) le nom semble être inexistant pour la plupart des commandes.

Vous devrez essayer, mais je soupçonne que quelles que soient les règles de réécriture que vous avez, ils n'utilisent pas lstat ou d'autres commandes sans déréférencement, ce qui les fait échouer.

Jonas Schäfer
la source