Tôi có thể ngăn thư mục của một tên nào đó được tạo không?


16

Tôi đang làm việc trên một ứng dụng web LAMP và có một quy trình được lên lịch ở đâu đó để tiếp tục tạo một thư mục được gọi shoptrong thư mục gốc của trang web. Mỗi khi điều này xuất hiện, nó gây ra xung đột với các quy tắc viết lại trong ứng dụng, không tốt.

Cho đến khi tôi tìm thấy tập lệnh vi phạm, có cách nào để ngăn chặn bất kỳ thư mục nào được gọi là shopđược tạo trong thư mục gốc không? Tôi biết rằng tôi có thể thay đổi quyền trên một thư mục để ngăn nội dung của nó bị thay đổi, nhưng tôi chưa tìm được cách ngăn thư mục của một tên nào đó được tạo.


4
Để tìm hiểu những gì đang tạo, bạn có thể kích hoạt kiểm toán .
Andrew Henle

Câu trả lời:


30

Bạn không thể, cho người dùng tạo thư mục có đủ quyền để viết trên thư mục mẹ.

Thay vào đó, bạn có thể tận dụng nhóm inotifycác cuộc gọi hệ thống do hạt nhân Linux cung cấp, để theo dõi việc tạo (và tùy chọn mv-ing) của thư mục shoptrong thư mục đã cho, nếu được tạo (hoặc tùy chọn mv-ed), rmthư mục.

Chương trình không gian người dùng bạn cần trong trường hợp này là inotifywait(đi kèm inotify-tools, cài đặt nó trước nếu cần).


Giả sử thư mục shopsẽ nằm trong /foo/barthư mục, hãy thiết lập giám sát để /foo/bar/shoptạo và rmngay lập tức nếu được tạo:

inotifywait -qme create /foo/bar | \
             awk '/,ISDIR shop$/ { system("rm -r -- /foo/bar/shop") }'
  • inotifywait -qme create /foo/bar/foo/barthư mục đồng hồ cho bất kỳ tập tin / thư mục có thể được tạo, tức là xem cho bất kỳ createsự kiện

  • Nếu được tạo, hãy awk '/,ISDIR shop$/ { system("rm -r -- /foo/bar/shop") }'kiểm tra xem tệp có phải là thư mục không và tên là shop( /,ISDIR shop$/), nếu vậy rmthư mục ( system("rm -r -- /foo/bar/shop"))

Bạn cần chạy lệnh với tư cách là người dùng có quyền ghi trên thư /foo/barmục để xóa shopkhỏi thư mục.


Nếu bạn cũng muốn theo dõi các mvhoạt động -ing, hãy thêm đồng hồ cho moved_tosự kiện:

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

Chỉ cần lưu ý, nếu bạn đang tìm kiếm một tập tin, không phải thư mục, được đặt tên 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") }'

2
Ngoài ra, nếu bạn đang sử dụng inotifywaitđể làm điều này thì cũng có khả năng trình kích hoạt cũng có thể bắt được quy trình vớips -ef
roaima

30

Để trả lời theo nghĩa đen dựa trên câu hỏi ngăn chặn một thư mục của một tên nào đó được tạo.

touch shop

Bạn không thể tạo một thư mục nếu một tệp có cùng tên

mkdir: cannot create directory ‘shop’: File exists


6
Điều này * có thể không * là đủ. mkdir có thể không làm điều đó, nhưng nó có thể được thực hiện. Đó là một thử đầu tiên tốt mặc dù.
coteyr

9
Trên các hệ thống Linux, sử dụng chattr +i shopđể làm cho nó bất biến. Cho đến khi cờ bất biến bị xóa, nó thậm chí không thể đổi tên / xóa.
R ..

1
Đây là một mẹo nhỏ thông minh, không hoàn toàn đúng với hoàn cảnh của tôi nhưng là một ý tưởng thông minh cho một số trường hợp nhất định 👍
Andrew

1
@R .. thú vị. Tôi dự kiến rename(2)vẫn hoạt động, vì tên không phải là một phần của inode, nhưng nó không. Tìm kiếm nhanh trên internet không tiết lộ lý do tại sao. Có gợi ý nào không?
Domen

@domen: Bởi vì đó là một phần mục đích của thuộc tính "bất biến". Tôi nghi ngờ phải mất thêm công việc không cần thiết ở cấp độ thực hiện để ngăn chặn hoạt renameđộng.
R ..

4

Điều gì về việc chiếm quyền điều khiển mkdirtòa nhà với 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

Lưu ý rằng bên trong trình xử lý này, bạn có thể đăng nhập PID của quá trình muốn tạo thư mục này thay thế:

$ 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

Bạn cần đặt ứng dụng này vào ~/.bashrcroot (hoặc bất cứ ai đang chạy ứng dụng của bạn) để đảm bảo điều này sẽ được sử dụng:

export LD_PRELOAD=/path/to/test.so

2
điều này không nên có một downvote, đó là một giải pháp và một giải pháp tốt
con mèo

4
Đó là sử dụng một chiếc vali nuke để mở một hộp đậu. Nhưng ít nhất, chúng sẽ được nấu chín ...
Cuộc đua nhẹ nhàng với Monica

2
@cat: Tôi không đồng ý. LD_PRELOADhacks như thế này là cơ bản luôn luôn sai lầm, và trừ khi bạn biết những gì bạn đang làm, họ có thể tồi tệ phá vỡ các chương trình mà bạn tải chúng vào bằng cách phá vỡ tính như async-tín hiệu an toàn của hàm bạn đang thay thế.
R ..

1
Ngoài ra, tôi nghĩ fopennên có "a"thay vì "w", vì vậy nó có thể lưu giữ các bản ghi trước đó
con mèo

2
Điều này cũng sẽ không hoạt động nếu mã xấu gọi trực tiếp tòa nhà, không thông qua libc. Hoặc nếu mã xấu được liên kết tĩnh.
Domen

3

(Sẽ nhận xét về câu trả lời của Miati nhưng không thể nhớ tài khoản cũ của tôi và không có đủ danh tiếng về tài khoản mới này ...)

Bạn có thể chặn tạo bằng cách tạo một tệp và sau đó thay đổi các thuộc tính tệp.

$ sudo touch shop
$ sudo chattr +i shop

Sau đó, mọi nỗ lực làm bất cứ điều gì với tệp đó sẽ bị chặn - ngay cả khi người dùng đã 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

2
Nếu bạn biết tên / địa chỉ email của tài khoản cũ của mình, bạn có thể yêu cầu hợp nhất tài khoản từ biểu mẫu liên hệ được liên kết ở cuối mỗi trang .
wizzwizz4

Ngoài ra, tại sao không cho chúng tôi biết làm thế nào điều này có liên quan đến câu trả lời khác, thay vì lý do tại sao bạn quyết định đăng?
jpaugh

2

Tạo một liên kết tượng trưng chỉ đến một vị trí không tồn tại trong một thư mục không tồn tại. Điều này có một số ý nghĩa thú vị:

$ 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, liên kết và những người khác sẽ thất bại với EEXIST(Tệp tồn tại).
  2. Cố gắng mở đường dẫn để đọc, viết hoặc nối thêm sẽ thất bại với ENOENT(Không có tệp hoặc thư mục như vậy)
  3. Sử dụng stat (2) (không phải lstat (2) hoặc stat (1)) trên vị trí cũng thất bại với ENOENT. lstat tất nhiên sẽ trả về thông tin về symlink.

Điều này có hai ưu điểm so với một số giải pháp khác được đề xuất ở đây: (a) bạn không cần một dịch vụ đang chạy theo dõi việc tạo thư mục và (b) tên dường như không tồn tại đối với hầu hết các lệnh.

Bạn sẽ phải cho nó một phát súng, nhưng tôi nghi ngờ rằng bất kỳ quy tắc viết lại nào bạn có, họ không sử dụng lstat hoặc các lệnh không tham gia hội nghị khác, khiến chúng thất bại.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.