Як запобігти запису файлів


13

Я хочу запустити команду в Linux таким чином, щоб він не міг створювати або відкривати жодні файли для запису. Він все ще повинен мати можливість читати файли як звичайні (тому порожній chroot - це не варіант), а також мати можливість записувати у вже відкриті файли (особливо stdout).

Бонусні бали, якщо запис файлів у певні каталоги (тобто в поточний каталог) все ще можливий.

Я шукаю рішення, яке є локальним процесом, тобто не передбачає налаштування таких речей, як AppArmor або SELinux для всієї системи, а також привілеїв root. Однак це може включати встановлення їх модулів ядра.

Я дивився на можливості, і це було б добре і просто, якби була можливість створення файлів. ulimit - це ще один підхід, який був би зручним, якби він охоплював цей випадок використання.


Занадто багато програм передбачають, що вони здатні записувати файли як слід (і виходять з ладу дивними способами, коли не можуть). straceрозповідає, які файли відкриває програма. Чому ти хочеш це робити? Це конкретна програма, чи ви хочете цього для тестування чи чогось іншого? Чи можете ви запустити програму як користувач / група, яка не має дозволу писати майже скрізь, крім поточного каталогу? Сучасні дистрибуції Linux використовують ідею групи для кожного користувача, тому налаштувати це слід досить просто.
vonbrand

Це спеціальна програма (Ізабел), яка інтерпретує код вже дещо безпечним способом (без довільного виконання коду), але все ж дозволяє коду створювати файли у довільних місцях. Оскільки код не є довіреним, я хочу запобігти цьому (скасовуючи програму). Програма вже працює як особливий користувач, але я б почувався безпечнішим, якби код не зміг перекрутити, скажімо, / tmp чи подібні місця.
Йоахім Брейтнер

Ви можете додати нового користувача, запустити додаток.
ctrl-alt-delor

Відповіді:


9

Як щодо створення порожнього chroot, а потім прив’язати-змонтувати основну файлову систему як лише для читання всередині chroot?

Напевно, має бути щось подібне, щоб створити прив'язування лише для читання:

mount --bind /foo/ /path/to/chroot/
mount -o remount,ro /path/to/chroot/

Ви можете прив’язати до монтажу інші каталоги, до яких ви хочете, щоб в'язниця також мала доступ до запису. Будьте обережні, якщо вам потрібно прив’язати спеціальні каталоги (/ dev /, / proc /, / sys /), встановлення їх як є може бути небезпечним.


Знову ж, потрібні привілеї root та інші "глобальні установки". Але варіант, так.
Йоахім Брейтнер

Чи /foo/шлях до основної файлової системи?
Уейн Конрад

5

Схоже, що правильний інструмент для цієї роботи fseccompзаснований на sync-ignoringкоді f Bastian Blank, я створив цей відносно невеликий файл, який змушує всіх його дітей не в змозі відкрити файл для запису:

/*
 * Copyright (C) 2013 Joachim Breitner <mail@joachim-breitner.de>
 *
 * Based on code Copyright (C) 2013 Bastian Blank <waldi@debian.org>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#define _GNU_SOURCE 1
#include <errno.h>
#include <fcntl.h>
#include <seccomp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define filter_rule_add(action, syscall, count, ...) \
  if (seccomp_rule_add(filter, action, syscall, count, ##__VA_ARGS__)) abort();

static int filter_init(void)
{
  scmp_filter_ctx filter;

  if (!(filter = seccomp_init(SCMP_ACT_ALLOW))) abort();
  if (seccomp_attr_set(filter, SCMP_FLTATR_CTL_NNP, 1)) abort();
  filter_rule_add(SCMP_ACT_ERRNO(EACCES), SCMP_SYS(open), 1, SCMP_A1(SCMP_CMP_MASKED_EQ, O_WRONLY, O_WRONLY));
  filter_rule_add(SCMP_ACT_ERRNO(EACCES), SCMP_SYS(open), 1, SCMP_A1(SCMP_CMP_MASKED_EQ, O_RDWR, O_RDWR));
  return seccomp_load(filter);
}

int main(__attribute__((unused)) int argc, char *argv[])
{
  if (argc <= 1)
  {
    fprintf(stderr, "usage: %s COMMAND [ARG]...\n", argv[0]);
    return 2;
  }

  if (filter_init())
  {
    fprintf(stderr, "%s: can't initialize seccomp filter\n", argv[0]);
    return 1;
  }

  execvp(argv[1], &argv[1]);

  if (errno == ENOENT)
  {
    fprintf(stderr, "%s: command not found: %s\n", argv[0], argv[1]);
    return 127;
  }

  fprintf(stderr, "%s: failed to execute: %s: %s\n", argv[0], argv[1], strerror(errno));
  return 1;
}

Тут ви бачите, що читати файли все ще можливо:

[jojo@kirk:1] Wed, der 06.03.2013 um 12:58 Uhr Keep Smiling :-)
> ls test
ls: cannot access test: No such file or directory
> echo foo > test
bash: test: Permission denied
> ls test
ls: cannot access test: No such file or directory
> touch test
touch: cannot touch 'test': Permission denied
> head -n 1 no-writes.c # reading still works
/*

Це не перешкоджає видаленню файлів, їх переміщенню або іншим операціям з файлами, крім відкриття, але це може бути додано.

Інструмент, що дозволяє це без запису коду С, - syscall_limiter .


4
Зауважте, що безпечний підхід полягає у випуску білих списків, а не в чорному списку. Якщо занадто багато заперечують, для допомоги в програмі можуть використовуватися зовнішні несанкціоновані помічники. За допомогою LD_PRELOAD такі помічники можуть бути прозорі для програми, яку ми виконуємо.
Ві.

4

Чи можете ви розглянути можливість заміни open(…)функції та завантаження її за допомогою LD_PRELOAD?


2
Ви, мабуть, маєте на увазі open... Ну, я б подумав про використання існуючого рішення, яке використовує такий підхід, так.
Йоахім Брейтнер

2
Існує щось подібне на github.com/certik/restrict , але воно конфігурується шляхом компіляції і, схоже, не користується широким застосуванням.
Йоахім Брейтнер

Так, вибачте, моя помилка, оновлення відповіді… Але мені здається, вам доведеться також замінити один на той write(…).
Леонід

Що стосується github.com/certik/restrict , так, ви абсолютно праві.
Леонід

3

Найпростішим рішенням є, мабуть, програма-обгортка, яка створює нову область імен файлової системи з відповідними файловими системами, встановленими лише для читання, а потім виконує програму, яку ви намагаєтесь обмежити.

Це те, systemdщо ви використовуєте ReadOnlyDirectories=для позначення певних каталогів для послуги лише для читання. Також є unshareкоманда, util-linuxяка може виконати роботу зі створення нового простору імен, тож ви можете зробити щось на кшталт:

unshare -m <wrapper>

де wrapperтоді просто доведеться перезавантажувати файлові системи, як потрібно, перед запуском реальної цільової програми.

Єдина проблема полягає в тому, що вам потрібно rootстворити новий простір імен ...


Я думав про це. Але чи можливо це без кореня? Чи є готовий сценарій / програма для цього?
Йоахім Брейтнер

1
Так, здається, що вам потрібно мати root, принаймні, з ядром 3.7.
TomH

Я дивився далі на це рішення. Можна рекурсивно прив’язувати-монтувати / до нового /, але ні і рекурсивно позначати його як лише для читання.
Йоахім Брейтнер

2

Ви можете запустити його в chroot, монтуючи спеціальні версії /tmp та ін. Можливо, systemd допомагає, і особливо systemd-nspawn (1) , який виглядає так, як ви хочете.


2

Віртуальна машина дозволила б сценарію писати в будь-якому місці, не впливаючи на хост-систему, і перевіряти, куди він насправді намагається написати, які, здається, є цілями.

Наприклад, ви можете легко запустити Arch Linux за допомогою

kvm -boot d -m 512 -cdrom archlinux-*.iso

1
Я все ще хочу запустити програму на поточній машині, щоб уникнути необхідності налаштування нової системи, нового середовища тощо. Віртуальна машина занадто важка для мого використання.
Йоахім Брейтнер

2

Зробити деякі початкові налаштування як root - це справді найпростіший спосіб. Зокрема, chroot в кріплення, призначене лише для читання, - це шлях найменшого опору.

Ви можете використовувати bindfs замість того, mount --bindщоб створити представлення лише для читання, не потребуючи root. Однак вам потрібно зробити щось як root, щоб запобігти доступ до інших файлів, наприклад chroot.

Інший підхід - LD_PRELOADце бібліотека, яка залучає до відкриття файлів і відмовляється дозволити запис. Це не вимагає особливих пільг. З точки зору безпеки це можна обійти, але це нормально для вашого випадку використання, коли вам потрібно містити лише певну особливість, а не довільний нативний код. Я не знаю про існуючу бібліотеку для цього. LD_PRELOADможе також використовуватися для обмеження програми на представлення лише для читання, створене за допомогою mount --bindабо bindfs; знову ж, я не знаю про існуючу бібліотеку.

На Debian та похідних можна встановити середовище schroot . Schroot - це встановлений корінь і його потрібно налаштувати як root, але його може виконувати будь-який уповноважений користувач.

Метод, який не вимагає ніякої співпраці від root, - це запустити процес у віртуальній машині. Ви можете налаштувати KVM або VirtualBox, або користувальницький режим Linux . Він трохи важкий, і означатиме додаткове споживання пам’яті, але не повинен суттєво впливати на швидкість символічних обчислень.

Як "ув’язнити" процес, не будучи корінним? може дати деяке натхнення.


1

Один із способів хоча б запобігти запису файлів (але не створювати їх) - зателефонувати ulimit -f 0спочатку. Це припинить процес, як тільки він спробує записати у файл, але створити порожні файли все ще можливо.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.