फ़ाइलों को लिखने से किसी प्रक्रिया को कैसे रोकें


13

मैं लिनक्स पर एक तरह से कमांड चलाना चाहता हूं ताकि वह लिखने के लिए कोई फाइल न बना सके और न ही खोल सके। यह अभी भी सामान्य के रूप में फ़ाइलों को पढ़ने में सक्षम होना चाहिए (इसलिए एक खाली चिरोट एक विकल्प नहीं है), और अभी भी पहले से खुली हुई फाइलों (विशेष रूप से स्टडआउट) को लिखने में सक्षम हो।

यदि कुछ निर्देशिकाओं (यानी वर्तमान निर्देशिका) के लिए फाइल लिखना अभी भी संभव है तो बोनस अंक।

मैं एक ऐसे समाधान की तलाश में हूं, जो प्रोसेस-लोकल हो, यानी पूरे सिस्टम के लिए AppArmor या SELinux जैसी चीजों को कॉन्फ़िगर करना शामिल नहीं है, न ही रूट विशेषाधिकार। इसमें उनके कर्नेल मॉड्यूल स्थापित करना शामिल हो सकता है, हालांकि।

मैं क्षमताओं को देख रहा था और ये अच्छा और आसान होता, अगर फाइलें बनाने की क्षमता होती। ulimit एक और दृष्टिकोण है जो सुविधाजनक होगा, यदि यह इस उपयोग के मामले को कवर करता है।


बहुत सारे कार्यक्रम यह मानते हैं कि वे निश्चित रूप से फ़ाइलों को लिखने में सक्षम हैं (और जब वे नहीं कर सकते तो अजीब तरीके से विफल हो जाते हैं)। straceआपको बताता है कि प्रोग्राम किस फाइल को खोल रहा है। तुम ऐसा क्यों करना चाहते हो? क्या यह एक विशिष्ट कार्यक्रम है, या आप परीक्षण के लिए ऐसा चाहते हैं या कुछ और? क्या आप प्रोग्राम को एक ऐसे उपयोगकर्ता / समूह के रूप में चला सकते हैं जिसके पास वर्तमान निर्देशिका को छोड़कर लगभग हर जगह लिखने की अनुमति नहीं है? आधुनिक लिनक्स डिस्टेंशिएशन प्रत्येक उपयोगकर्ता के लिए एक समूह के विचार का उपयोग करते हैं, इसलिए इसे स्थापित करना अपेक्षाकृत आसान होना चाहिए।
वॉनब्रांड

यह एक विशेष कार्यक्रम (इसाबेल) है जो कोड को कुछ हद तक पहले से ही सुरक्षित तरीके से व्याख्या करता है (कोई मनमाना कोड निष्पादन नहीं), लेकिन फिर भी कोड को मनमाने स्थानों में फाइलें बनाने की अनुमति देता है। जैसा कि कोड अविश्वसनीय है, मैं इसे (कार्यक्रम को समाप्त करके) होने से रोकना चाहता हूं। कार्यक्रम पहले से ही एक विशेष उपयोगकर्ता के रूप में चलता है, लेकिन मुझे लगता है कि यदि कोड क्लोबर, / tmp या इसी तरह के स्थानों को बंद नहीं कर सकता है, तो मैं अधिक सुरक्षित महसूस करूंगा।
जोआचिम ब्रेइटनर

आप ऐप को चलाने के लिए एक नया उपयोगकर्ता जोड़ सकते हैं।
ctrl-alt-delor-

जवाबों:


9

कैसे एक खाली चिरोट बनाने के बारे में, फिर मुख्य फाइलसिस्टम को केवल चेरोट के अंदर पढ़ने के लिए बाँध दें?

पढ़ने के लिए केवल बाइंड-माउंट बनाने के लिए ऐसा कुछ होना चाहिए:

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

आप अन्य निर्देशिकाओं को बांध सकते हैं जिन्हें आप चाहते हैं कि जेल में भी लिखने की सुविधा हो। यदि आपको विशेष निर्देशिकाओं (/ dev /, / proc /, / sys /) को बांधने की आवश्यकता है तो सावधान रहें, जैसा कि वे असुरक्षित हैं।


फिर से, रूट विशेषाधिकार और अन्य "वैश्विक सेटअप" की आवश्यकता है। लेकिन एक विकल्प, हाँ।
जोकिम ब्रेटनर

है /foo/मुख्य फाइल सिस्टम के लिए पथ?
वेन कॉनराड

5

ऐसा लगता है कि इस नौकरी के लिए सही उपकरण बास्टियन ब्लैंक द्वारा एफ कोड fseccompपर आधारित है sync-ignoring, मैं इस अपेक्षाकृत छोटी फ़ाइल के साथ आया था जिसके कारण इसके सभी बच्चे लेखन के लिए एक फ़ाइल खोलने में सक्षम नहीं हो सकते हैं:

/*
 * 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


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
हां, ऐसा लगता है कि आपको रूट होने की जरूरत है, कम से कम 3.7 कर्नेल के साथ।
टॉम

मैं इस समाधान को आगे देख रहा था। पुनरावर्ती -माउंट / एक नए / के लिए संभव है , लेकिन नहीं और पुनरावृत्ति इसे केवल-पढ़ने के रूप में चिह्नित करता है।
जोआचिम ब्रेइटनर

2

आप इसे चेरोट में चला सकते हैं, /tmp और इसके अंदर के विशेष संस्करण बढ़ते जा सकते हैं । शायद systemd मदद का है, और विशेष रूप से systemd-nspawn (1) , जो जैसा चाहता है वैसा ही दिखता है।


2

एक वर्चुअल मशीन स्क्रिप्ट को होस्ट सिस्टम को प्रभावित किए बिना कहीं भी लिखने के लिए संभव बनाती है, और निरीक्षण करने के लिए कि वह वास्तव में लिखने की कोशिश कर रही है, जो कि लक्ष्य प्रतीत होते हैं।

उदाहरण के लिए, आप आसानी से आर्क लिनक्स शुरू कर सकते हैं

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

1
मैं अभी भी एक नई प्रणाली, नए वातावरण आदि को स्थापित करने से बचने के लिए वर्तमान मशीन में कार्यक्रम चलाना चाहता हूं। एक आभासी मशीन मेरे उपयोग के मामले के लिए बहुत भारी है।
जोआचिम ब्रेटनर

2

रूट के रूप में कुछ प्रारंभिक सेटअप करना वास्तव में सबसे आसान तरीका है। विशेष रूप से, एक रीड-ओनली बाइंड माउंट में चुरोट कम से कम प्रतिरोध का मार्ग है।

आप रूट होने की आवश्यकता के बिना केवल-पढ़ने के लिए दृश्य बनाने के बजाय bindfs का उपयोग कर सकते हैं mount --bind। हालांकि, आपको अन्य फ़ाइलों तक पहुंच को रोकने के लिए रूट के रूप में कुछ करने की आवश्यकता है, जैसे कि चेरोट।

एक अन्य दृष्टिकोण LD_PRELOADएक पुस्तकालय के लिए है जो फ़ाइल खोलने में हुक करता है और लिखने की अनुमति देने से इनकार करता है। इसके लिए किसी विशेष विशेषाधिकार की आवश्यकता नहीं है। सुरक्षा के नजरिए से, इसे दरकिनार किया जा सकता है, लेकिन यह आपके उपयोग के मामले के लिए ठीक है, जहां आपको केवल एक विशिष्ट विशेषता को शामिल करने की आवश्यकता होती है, न कि मनमाने ढंग से देशी कोड। हालाँकि मुझे इसके लिए किसी मौजूदा लाइब्रेरी का पता नहीं है। LD_PRELOADकार्यक्रम को केवल पढ़ने के लिए mount --bindया के साथ बनाए गए दृश्य तक सीमित करने के लिए भी इस्तेमाल किया जा सकता है bindfs; फिर से, मुझे मौजूदा लाइब्रेरी का पता नहीं है।

डेबियन और डेरिवेटिव पर, आप एक schroot वातावरण सेट कर सकते हैं। श्रोत सेटुइड रूट है और इसे रूट के रूप में कॉन्फ़िगर करने की आवश्यकता है, लेकिन किसी भी अधिकृत उपयोगकर्ता द्वारा निष्पादित किया जा सकता है।

एक विधि जिसे रूट से किसी भी सहयोग की आवश्यकता नहीं है, एक आभासी मशीन में प्रक्रिया को चलाना है। आप KVM या VirtualBox या उपयोगकर्ता-मोड लिनक्स सेट कर सकते हैं । यह थोड़ा भारी है, और इसका मतलब अतिरिक्त मेमोरी खपत होगा, लेकिन कच्चे प्रतीकात्मक गणना की गति को महत्वपूर्ण रूप से प्रभावित नहीं करना चाहिए।

जड़ के बिना एक प्रक्रिया को "जेल" कैसे करें? कुछ प्रेरणा प्रदान कर सकते हैं।


1

कम से कम फ़ाइलों को लिखने से प्रक्रिया को रोकने का एक तरीका है (लेकिन उन्हें बनाने से नहीं) ulimit -f 0पहले कॉल करना है । यह प्रक्रिया को समाप्त कर देगा जैसे ही यह किसी फ़ाइल में लिखने की कोशिश करता है, लेकिन खाली फ़ाइलों को बनाना अभी भी संभव है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.