Bisakah saya mencegah folder dengan nama tertentu dibuat?

16

Saya sedang mengerjakan aplikasi web LAMP dan ada proses terjadwal di suatu tempat yang terus membuat folder bernama shopdi root situs. Setiap kali ini muncul itu menyebabkan konflik dengan aturan penulisan ulang di app, tidak bagus.

Sampai saya menemukan skrip yang menyinggung, apakah ada cara untuk mencegah folder yang disebut shopdibuat di root? Saya tahu bahwa saya dapat mengubah izin pada folder untuk mencegah isinya diubah, tetapi saya belum menemukan cara untuk mencegah folder dengan nama tertentu dibuat.

Andrew
sumber
4
Untuk mengetahui apa yang dilakukan pembuatan, Anda dapat mengaktifkan audit .
Andrew Henle

Jawaban:

30

Anda tidak bisa, mengingat pengguna yang membuat direktori memiliki izin yang cukup untuk menulis di direktori induk.

Sebagai gantinya, Anda dapat memanfaatkan kumpulan inotifypanggilan sistem yang disediakan oleh kernel Linux, untuk mengawasi pembuatan (dan opsional mv-ing) direktori shopdalam direktori yang diberikan, jika dibuat (atau secara opsional mv-ed), rmdirektori.

Program userspace yang Anda butuhkan dalam hal ini adalah inotifywait(datang dengan inotify-tools, instal dulu jika diperlukan).


Dengan asumsi direktori shopakan berada di /foo/bardirektori, mari kita atur pemantauan untuk /foo/bar/shoppembuatan, dan rmlangsung jika dibuat:

inotifywait -qme create /foo/bar | \
             awk '/,ISDIR shop$/ { system("rm -r -- /foo/bar/shop") }'
  • inotifywait -qme create /foo/bar/foo/bardirektori jam tangan untuk file / direktori apa pun yang mungkin dibuat, misalnya pantau createacara apa pun

  • Jika dibuat, awk '/,ISDIR shop$/ { system("rm -r -- /foo/bar/shop") }'periksa apakah file tersebut merupakan direktori dan namanya adalah shop( /,ISDIR shop$/), jika demikian rmdirektori ( system("rm -r -- /foo/bar/shop"))

Anda perlu menjalankan perintah sebagai pengguna yang memiliki izin menulis pada direktori /foo/baruntuk dihapus dari shopdirektori.


Jika Anda ingin memantau mvoperasi juga, tambahkan tontonan untuk moved_toacara juga:

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

Sekadar diketahui, jika Anda mencari file, bukan direktori, bernama 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
sumber
2
Terlebih lagi jika Anda menggunakan inotifywaituntuk melakukan ini, juga mungkin bahwa pemicunya juga mungkin dapat menangkap proses denganps -ef
roaima
30

Untuk menjawab secara harfiah berdasarkan pertanyaan mencegah folder dari nama tertentu yang akan dibuat.

touch shop

Anda tidak dapat membuat direktori jika ada file dengan nama identik

mkdir: cannot create directory ‘shop’: File exists

Miati
sumber
6
Ini * mungkin * tidak cukup. mkdir mungkin tidak melakukannya, tetapi itu bisa dilakukan. Ini adalah percobaan pertama yang baik.
coteyr
9
Pada sistem Linux, gunakan chattr +i shopuntuk membuatnya tidak berubah. Sampai bendera yang tidak dapat diubah dihapus, itu bahkan tidak dapat diganti namanya / dihapus.
R .. GitHub BERHENTI MEMBANTU ICE
1
Ini adalah trik kecil yang cerdas, tidak tepat untuk situasi saya tetapi ide yang cerdas untuk keadaan tertentu 👍
Andrew
1
@R .. menarik. Saya berharap rename(2)masih berfungsi, karena nama bukan bagian dari inode, tetapi tidak. Pencarian internet cepat tidak mengungkapkan alasannya. Ada petunjuk?
domen
@domen: Karena itu adalah bagian dari tujuan atribut "tidak berubah". Saya menduga perlu kerja ekstra nontrivial di tingkat implementasi untuk mencegahnya renamebekerja.
R .. GitHub BERHENTI MEMBANTU ICE
4

Bagaimana dengan membajak mkdirsyscall dengan 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

Perhatikan bahwa di dalam handler ini Anda dapat mencatat PID proses yang ingin membuat direktori ini:

$ 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

Anda perlu menempatkan ini di ~/.bashrcroot (atau siapa pun yang menjalankan aplikasi Anda) untuk memastikan ini akan digunakan:

export LD_PRELOAD=/path/to/test.so
Nykakin
sumber
2
ini seharusnya tidak memiliki downvote, itu solusi dan yang bagus
kucing
4
Ini menggunakan nuklir koper untuk membuka kaleng kacang. Tapi hei setidaknya mereka akan dimasak ...
Lightness Races dengan Monica
2
@cat: Saya tidak setuju. LD_PRELOADhacks seperti ini pada dasarnya selalu salah, dan kecuali Anda tahu apa yang Anda lakukan, mereka bisa buruk mematahkan program yang memuat mereka ke dengan melanggar sifat seperti async-sinyal-keselamatan fungsi yang Anda mengganti.
R .. GitHub BERHENTI MEMBANTU ICE
1
Juga, saya pikir fopenseharusnya "a"bukan "w", sehingga dapat menyimpan log sebelumnya
cat
2
Ini juga tidak akan berfungsi jika kode buruk memanggil syscall secara langsung, bukan melalui libc. Atau jika kode yang buruk terhubung secara statis.
domen
3

(Akan mengomentari jawaban Miati tetapi tidak dapat mengingat akun lama saya dan tidak memiliki reputasi yang cukup untuk yang baru ini ...)

Anda dapat memblokir penciptaan dengan membuat file dan kemudian mengubah atribut file.

$ sudo touch shop
$ sudo chattr +i shop

Maka segala upaya untuk melakukan apa pun dengan file itu akan diblokir - bahkan jika pengguna menjadi 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
sumber
2
Jika Anda tahu nama / alamat email akun lama Anda, Anda dapat meminta penggabungan akun dari formulir kontak yang ditautkan di bagian bawah setiap halaman .
wizzwizz4
Juga, mengapa tidak memberi tahu kami bagaimana ini terkait dengan jawaban yang lain, daripada mengapa Anda memutuskan untuk mengirim?
jpaugh
2

Buat symlink yang menunjuk ke lokasi yang tidak ada di dalam direktori yang tidak ada. Ini memiliki beberapa implikasi menyenangkan:

$ 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, tautan, dan lainnya akan gagal dengan EEXIST(File ada).
  2. Mencoba membuka jalur untuk membaca, menulis atau menambahkan akan gagal dengan ENOENT(Tidak ada file atau direktori seperti itu)
  3. Menggunakan stat (2) (bukan lstat (2) atau stat (1)) di lokasi juga gagal ENOENT. lstat tentu saja akan mengembalikan informasi tentang symlink.

Ini memiliki dua keunggulan dibandingkan beberapa solusi lain yang diusulkan di sini: (a) Anda tidak perlu menjalankan layanan yang melacak pembuatan direktori dan (b) nama tersebut tampaknya tidak ada di sebagian besar perintah.

Anda harus mencobanya, tetapi saya curiga bahwa apa pun aturan penulisan ulang yang Anda miliki, mereka tidak menggunakan lstat atau perintah non-dereferensi lain, membuatnya gagal.

Jonas Schäfer
sumber