Czy mogę zapobiec tworzeniu folderu o określonej nazwie?

16

Pracuję nad aplikacją internetową LAMP i gdzieś jest zaplanowany proces, który ciągle tworzy folder o nazwie shopw katalogu głównym witryny. Za każdym razem, gdy się pojawia, powoduje konflikt z regułami przepisywania w aplikacji, co nie jest dobre.

Dopóki nie znajdę urażliwego skryptu, czy istnieje sposób, aby zapobiec shoputworzeniu folderu o nazwie root w katalogu głównym? Wiem, że mogę zmienić uprawnienia do folderu, aby zapobiec zmianie jego zawartości, ale nie znalazłem sposobu, aby zapobiec tworzeniu folderu o określonej nazwie.

Andrzej
źródło
4
Aby dowiedzieć się, co robi tworzenie, możesz włączyć inspekcję .
Andrew Henle,

Odpowiedzi:

30

Nie możesz, ponieważ użytkownik tworzący katalog ma wystarczające uprawnienia do zapisu w katalogu nadrzędnym.

Zamiast tego możesz wykorzystać inotifyrodzinę wywołań systemowych dostarczanych przez jądro Linuksa, aby obserwować tworzenie (i opcjonalnie mv-ing) katalogu shopw danym katalogu, jeśli został utworzony (lub opcjonalnie mv-ed), rmkatalog.

Program przestrzeni użytkownika, którego potrzebujesz w tym przypadku to inotifywait(pochodzi z inotify-tools, zainstaluj go najpierw, jeśli to konieczne).


Zakładając, że katalog shopbędzie znajdować się w /foo/barkatalogu, ustawmy monitorowanie /foo/bar/shoptworzenia i rmnatychmiast, jeśli zostanie utworzone:

inotifywait -qme create /foo/bar | \
             awk '/,ISDIR shop$/ { system("rm -r -- /foo/bar/shop") }'
  • inotifywait -qme create /foo/bar/foo/barkatalog zegarki dla każdego pliku / katalogu, który może zostać utworzony, tj. obserwuj każde createzdarzenie

  • Jeśli utworzony, awk '/,ISDIR shop$/ { system("rm -r -- /foo/bar/shop") }'sprawdza, czy plik jest katalogiem, a nazwa to shop( /,ISDIR shop$/), jeśli tak, rmto katalog ( system("rm -r -- /foo/bar/shop"))

Musisz uruchomić polecenie jako użytkownik, który ma uprawnienia do zapisu w katalogu w /foo/barcelu usunięcia go shopz katalogu.


Jeśli chcesz też monitorować mvoperacje-dodawania, dodaj też obserwację moved_tozdarzenia:

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

Uwaga: jeśli szukasz pliku, a nie katalogu o nazwie 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
źródło
2
Co więcej, jeśli używasz inotifywaitdo tego celu, możliwe jest również, że wyzwalacz może być w stanie złapać proces za pomocąps -ef
roaima
30

Aby odpowiedzieć dosłownie w oparciu o pytanie, czy nie można utworzyć folderu o określonej nazwie.

touch shop

Nie można utworzyć katalogu, jeśli istnieje plik o identycznej nazwie

mkdir: cannot create directory ‘shop’: File exists

Miati
źródło
6
To * może * nie wystarczyć. mkdir może tego nie zrobić, ale można to zrobić. Jest to jednak dobra pierwsza próba.
coteyr
9
W systemach Linux użyj, chattr +i shopaby był niezmienny. Dopóki niezmienna flaga nie zostanie usunięta, nie można nawet zmienić jej nazwy / usunąć.
R .. GitHub ZATRZYMAJ LOD
1
To sprytna sztuczka, nie do końca odpowiednia w mojej sytuacji, ale sprytny pomysł na pewne okoliczności 👍
Andrew
1
@R .. ciekawe. Spodziewałem rename(2)się, że nadal będę działać, ponieważ nazwa nie jest częścią i-węzła, ale tak nie jest. Szybkie wyszukiwanie w Internecie nie ujawnia przyczyny. Jakieś wskazówki?
domen
@ domena: Ponieważ jest to część celu atrybutu „niezmienny”. Podejrzewam, że potrzeba dodatkowej pracy na poziomie implementacji, aby uniemożliwić jej renamedziałanie.
R .. GitHub ZATRZYMAJ LÓD
4

A co z przejęciem mkdirsyscall z 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

Zauważ, że w tym module obsługi możesz zarejestrować PID procesu, który zamiast tego chce utworzyć ten katalog:

$ 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

Musisz umieścić to w ~/.bashrckatalogu głównym (lub ktokolwiek uruchamia twoją aplikację), aby mieć pewność, że zostanie to wykorzystane:

export LD_PRELOAD=/path/to/test.so
Nykakin
źródło
2
to nie powinno mieć negatywnej opinii, jest to dobre rozwiązanie
kot
4
Używa walizki nuklearnej, by otworzyć puszkę fasoli. Ale hej, przynajmniej zostaną ugotowane ...
Lekkość ściga się z Moniką
2
@cat: Nie zgadzam się. LD_PRELOADtakie hacki są w zasadzie zawsze błędne i jeśli nie wiesz, co robisz, mogą poważnie zepsuć program, do którego je ładujesz, niszcząc właściwości takie jak bezpieczeństwo sygnału asynchronicznego zastępowanej funkcji.
R .. GitHub ZATRZYMAJ LOD
1
Ponadto myślę, że fopenpowinienem "a"zamiast "w", aby mógł zachować poprzednie dzienniki
cat
2
To również nie zadziała, jeśli zły kod wywoła syscall bezpośrednio, a nie przez libc. Lub jeśli zły kod jest statycznie powiązany.
domen
3

(Skomentowałbym odpowiedź Miati, ale nie pamiętam mojego starego konta i nie mam wystarczającej reputacji na tym nowym ...)

Możesz zablokować tworzenie, tworząc plik, a następnie zmieniając atrybuty pliku.

$ sudo touch shop
$ sudo chattr +i shop

Wtedy każda próba zrobienia czegokolwiek z tym plikiem zostanie zablokowana - nawet jeśli użytkownik zostanie rootem.

$ 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
źródło
2
Jeśli znasz nazwę / adres e-mail swojego starego konta, możesz poprosić o połączenie konta z formularza kontaktowego połączonego na dole każdej strony .
wizzwizz4
A może powiedz nam, jak to się wiąże z drugą odpowiedzią, a nie dlaczego zdecydowałeś się opublikować?
jpaugh
2

Utwórz dowiązanie symboliczne wskazujące na nieistniejącą lokalizację w nieistniejącym katalogu. Ma to pewne zabawne implikacje:

$ 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 i inne zakończą się niepowodzeniem EEXIST(plik istnieje).
  2. Próba otwarcia ścieżki do odczytu, zapisu lub dołączania zakończy się niepowodzeniem ENOENT(Brak takiego pliku lub katalogu)
  3. Używanie stat (2) (nie lstat (2) lub stat (1)) w lokalizacji również kończy się niepowodzeniem ENOENT. lstat oczywiście zwróci informacje o dowiązaniu symbolicznym.

Ma to dwie zalety w porównaniu z innymi proponowanymi tutaj rozwiązaniami: (a) nie potrzebujesz uruchomionej usługi, która śledzi tworzenie katalogu, i (b) nazwa wydaje się nie istnieć w przypadku większości poleceń.

Będziesz musiał spróbować, ale podejrzewam, że bez względu na to, jakie przepisy przepisujesz, nie używają lstat ani innych poleceń nie dereferencyjnych, co powoduje, że zawodzą.

Jonas Schäfer
źródło