Как препятствовать тому, чтобы процесс писал файлы

g/iPXE определенно сделает это по (медленному) TFTP или HTTP (по крайней мере дважды с такой скоростью, как TFTP в моих собственных экспериментах).

Из моих примечаний (таким образом, я не 100%, что это будет работать, но это должно):

KERNEL ipxe.lkrn dhcp && chain http://1.0.0.1/pmagic_http.php

и затем содержание pmagic_tftp.php, находясь на http сервере на 1.0.0.1:

#!ipxe

kernel pmagic/bzImage edd=off load_ramdisk=1 prompt_ramdisk=0 rw loglevel=9 max_loop=16

initrd pmagic/initrd.img 
boot

Я отправлю позже точные детали, должен закончить работать :(

13
13.02.2013, 13:31
8 ответов

Кажется, что правильный инструмент для этого задания fseccomp На основе sync-ignoringf кодируют 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
/*

Это не предотвращает файлы удаления или перемещение их или других операций файла помимо открытия, но это могло быть добавлено.

Инструмент, который включает это, не имея необходимость писать код C, является syscall_limiter.

5
27.01.2020, 19:52
  • 1
    Обратите внимание, что безопасный подход должен добавить syscalls в белый список, для не помещения в черный список их. Если слишком много отклонено, внешние unsanboxed помощники могут использоваться для помощи программе. С LD_PRELOAD такие помощники могут быть сделаны очевидными для программы мы выполнение. –  Vi. 06.03.2013, 20:08

Как насчет того, чтобы создать пустой chroot, затем свяжите - монтируют основную файловую систему как только для чтения в chroot?

Должен, вероятно, быть что-то вроде этого для создания только для чтения связывает - смонтируйтесь:

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

Можно связать - монтируют другие каталоги, к которым Вы хотите, чтобы тюрьма имела доступ для записи также. Будьте осторожны, если необходимо связать - монтируют, что специальные каталоги (/dev/,/proc/,/sys/), монтируя их как есть могут быть небезопасными.

9
27.01.2020, 19:52
  • 1
    Снова, полномочия пользователя root потребностей и другая” глобальная установка”. Но опция, да. –  Joachim Breitner 13.02.2013, 19:07
  • 2
    /foo/ путь к основной файловой системе? –  Wayne Conrad 09.07.2017, 17:47

Вы рассмотрели бы запись замены к open(…) функция и загрузка его с помощью LD_PRELOAD?

4
27.01.2020, 19:52
  • 1
    Вы, вероятно, имеете в виду open... Ну, я рассмотрел бы использование существующего решения, которое использует этот подход, да. –  Joachim Breitner 13.02.2013, 14:18
  • 2
    Существует что-то вроде этого по github.com/certik/restrict, но это настроено путем компиляции и, кажется, не в широком употреблении. –  Joachim Breitner 13.02.2013, 14:27
  • 3
    Да, извините, моя ошибка, обновляя ответ …, Но это кажется мне, необходимо будет занять место один write(…) также. –  Leonid 13.02.2013, 15:34
  • 4
    Что касается github.com/certik/restrict, да, Вы абсолютно правы. –  Leonid 13.02.2013, 15:37

Простое решение является, вероятно, программой обертки, которая создает новое пространство имен файловой системы с соответствующими файловыми системами, смонтированными только для чтения и затем должностные лица программа, которую Вы пытаетесь ограничить.

Это что systemd делает, когда Вы используете ReadOnlyDirectories= отметить определенные каталоги как только для чтения для сервиса. Существует также unshare команда в util-linux это может сделать работу создания нового пространства имен, таким образом, можно сделать что-то как:

unshare -m <wrapper>

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

Единственная проблема состоит в том, что необходимо быть root создать новое пространство имен...

3
27.01.2020, 19:52
  • 1
    , я думал об этом. Но действительно ли это возможно, не будучи корнем? Существует ли готовый сценарий/программа для этого доступного? –  Joachim Breitner 13.02.2013, 14:13
  • 2
    Да, кажется, что действительно необходимо быть корнем, по крайней мере, с 3,7 ядрами. –  TomH 13.02.2013, 14:27
  • 3
    я далее смотрел на это решение. Возможно рекурсивно связать - монтируют / к новому/, но не и рекурсивно отмечают его как только для чтения. –  Joachim Breitner 13.02.2013, 21:28

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

2
27.01.2020, 19:52

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

Например, можно легко запустить Дугу Linux с

kvm -boot d -m 512 -cdrom archlinux-*.iso
2
27.01.2020, 19:52
  • 1
    я все еще хочу запустить программу в текущей машине, чтобы избежать необходимости настраивать новую систему, новая среда и т.д. Виртуальная машина слишком тяжела для моего варианта использования. –  Joachim Breitner 13.02.2013, 14:33

При выполнении некоторой начальной настройки, поскольку корень является действительно самым легким путем. А именно, chroot в только для чтения связывают монтирование, путь наименьшего сопротивления.

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

Другой подход к LD_PRELOAD библиотека, которая сцепляется в открытие файла и отказывается позволять писать. Это не требует никаких специальных полномочий. С точки зрения безопасности это может быть обойдено, но для Вашего варианта использования хорошо, где только необходимо содержать определенную функцию и не произвольный собственный код. Я не знаю о существующей библиотеке для этого, как бы то ни было. LD_PRELOAD мог также использоваться для ограничения программы представлением только для чтения, созданным с mount --bind или bindfs; снова, я не знаю о существующей библиотеке.

На Debian и производных, можно настроить schroot среду. Schroot является корнем setuid и должен быть настроен как корень, но может быть выполнен любым авторизованным пользователем.

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

Как "заключить в тюрьму" процесс, не будучи корнем? мог бы обеспечить некоторое вдохновение.

2
27.01.2020, 19:52

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

1
27.01.2020, 19:52

Теги

Похожие вопросы