জবাবদিহিত কোনও শেল স্ক্রিপ্টে 'rm -rf /' চালানো রোধ করবে?


23

এটি এখানে এই প্রতারণামূলক প্রশ্নের উপর ভিত্তি করে । বর্ণিত সমস্যাটি হ'ল বাশ স্ক্রিপ্ট রয়েছে যার মধ্যে কিছুটা প্রভাব রয়েছে:

rm -rf {pattern1}/{pattern2}

... যা উভয় নিদর্শনগুলিতে যদি এক বা একাধিক খালি উপাদান অন্তর্ভুক্ত থাকে তবে এটি কমপক্ষে একটি উদাহরণে প্রসারিত হবে rm -rf /, ধরেই নেওয়া হবে যে আসল কমান্ডটি সঠিকভাবে প্রতিলিপি করা হয়েছে এবং ওপি প্যারামিটারের প্রসারণের পরিবর্তে ব্রেস সম্প্রসারণ করছে ।

প্রতারণার ওপির ব্যাখ্যায় তিনি বলেছেন:

কমান্ডটি [...] নিরীহ তবে এটি সম্ভবত কারও নজরে আসেনি।

জবাবদিহিত সরঞ্জাম এই ত্রুটিগুলি রোধ করে, [...] তবে [...] কেউ তা জানত বলে মনে হয়নি, অন্যথায় তারা জানত যে আমি যা বর্ণনা করেছি তা ঘটতে পারে না।

সুতরাং ধরে নিলে আপনার কাছে একটি শেল স্ক্রিপ্ট রয়েছে যা rm -rf /ব্রেস সম্প্রসারণ বা প্যারামিটার সম্প্রসারণের মাধ্যমে কোনও কমান্ড নির্ধারণ করে, এটি কি সত্য যে আনসিবল ব্যবহার করলে সেই আদেশটি কার্যকর হতে বাধা দেওয়া হবে, এবং যদি তা হয় তবে এটি কীভাবে এটি করে?

rm -rf /যতক্ষণ আপনি এটির জন্য জবাবদিহি ব্যবহার করছেন ততক্ষেত্রে রুট সুবিধাগুলি সহ বাস্তবায়ন কি "নিরীহ"?


4
এই প্রশ্নটি দিয়ে কী করা উচিত তা নিয়ে আমি বিতর্ক করেছি, তবে শেষ পর্যন্ত আমি এটিকে উত্সাহিত করার এবং তার উত্তর দেওয়ার সিদ্ধান্ত নিয়েছি, যাতে শেষ পর্যন্ত এটির যেখানে এই পুরো দুঃখজনক হাস্যকর জগাখিচুড়িটি যেখানে রয়েছে তার দিকে রাখার দিকে এগিয়ে যেতে।
মাইকেল হ্যাম্পটন

আমি মনে করি উত্তরটি উত্সটিতে রয়েছে rmযা আমি নীচে বিশ্লেষণ করেছি।
অ্যারন হল

উত্তর:


54

আমার ভার্চুয়াল মেশিন রয়েছে, আসুন তাদের একটি গোছা উড়িয়ে দিন! বিজ্ঞানের জন্য.

[root@diaf ~]# ansible --version
ansible 2.0.1.0
  config file = /etc/ansible/ansible.cfg
  configured module search path = Default w/o overrides

প্রথম প্রচেষ্টা:

[root@diaf ~]# cat killme.yml 
---
- hosts: localhost
  gather_facts: False
  tasks:
    - name: Die in a fire
      command: "rm -rf {x}/{y}"
[root@diaf ~]# ansible-playbook -l localhost -vvv killme.yml
Using /etc/ansible/ansible.cfg as config file
1 plays in killme.yml

PLAY ***************************************************************************

TASK [Die in a fire] ***********************************************************
task path: /root/killme.yml:5
ESTABLISH LOCAL CONNECTION FOR USER: root
localhost EXEC /bin/sh -c '( umask 22 && mkdir -p "` echo $HOME/.ansible/tmp/ansible-tmp-1461128819.56-86533871334374 `" && echo "` echo $HOME/.ansible/tmp/ansible-tmp-1461128819.56-86533871334374 `" )'
localhost PUT /tmp/tmprogfhZ TO /root/.ansible/tmp/ansible-tmp-1461128819.56-86533871334374/command
localhost EXEC /bin/sh -c 'LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 /usr/bin/python /root/.ansible/tmp/ansible-tmp-1461128819.56-86533871334374/command; rm -rf "/root/.ansible/tmp/ansible-tmp-1461128819.56-86533871334374/" > /dev/null 2>&1'
changed: [localhost] => {"changed": true, "cmd": ["rm", "-rf", "{x}/{y}"], "delta": "0:00:00.001844", "end": "2016-04-20 05:06:59.601868", "invocation": {"module_args": {"_raw_params": "rm -rf {x}/{y}", "_uses_shell": false, "chdir": null, "creates": null, "executable": null, "removes": null, "warn": true}, "module_name": "command"}, "rc": 0, "start": "2016-04-20 05:06:59.600024", "stderr": "", "stdout": "", "stdout_lines": [], "warnings": ["Consider using file module with state=absent rather than running rm"]}
 [WARNING]: Consider using file module with state=absent rather than running rm


PLAY RECAP *********************************************************************
localhost                  : ok=1    changed=1    unreachable=0    failed=0

ঠিক আছে, তাই commandকেবল আক্ষরিক পাশ দিয়ে যায়, এবং কিছুই ঘটে না।

আমাদের প্রিয় সুরক্ষা বাইপাস সম্পর্কে কীভাবে raw,?

[root@diaf ~]# cat killme.yml
---
- hosts: localhost
  gather_facts: False
  tasks:
    - name: Die in a fire
      raw: "rm -rf {x}/{y}"
[root@diaf ~]# ansible-playbook -l localhost -vvv killme.yml
Using /etc/ansible/ansible.cfg as config file
1 plays in killme.yml

PLAY ***************************************************************************

TASK [Die in a fire] ***********************************************************
task path: /root/killme.yml:5
ESTABLISH LOCAL CONNECTION FOR USER: root
localhost EXEC rm -rf {x}/{y}
ok: [localhost] => {"changed": false, "invocation": {"module_args": {"_raw_params": "rm -rf {x}/{y}"}, "module_name": "raw"}, "rc": 0, "stderr": "", "stdout": "", "stdout_lines": []}

PLAY RECAP *********************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0

আর না যাও! আপনার সমস্ত ফাইল মুছে ফেলা সম্ভব কতটা কঠিন হতে পারে?

ওহ, তবে তারা যদি অপরিবর্তিত ভেরিয়েবল বা অন্য কিছু হত?

[root@diaf ~]# cat killme.yml
---
- hosts: localhost
  gather_facts: False
  tasks:
    - name: Die in a fire
      command: "rm -rf {{x}}/{{y}}"
[root@diaf ~]# ansible-playbook -l localhost -vvv killme.yml
Using /etc/ansible/ansible.cfg as config file
1 plays in killme.yml

PLAY ***************************************************************************

TASK [Die in a fire] ***********************************************************
task path: /root/killme.yml:5
fatal: [localhost]: FAILED! => {"failed": true, "msg": "'x' is undefined"}

NO MORE HOSTS LEFT *************************************************************
        to retry, use: --limit @killme.retry

PLAY RECAP *********************************************************************
localhost                  : ok=0    changed=0    unreachable=0    failed=1

ভাল, এটি কাজ করে না।

তবে ভেরিয়েবল সংজ্ঞায়িত হলেও খালি?

[root@diaf ~]# cat killme.yml 
---
- hosts: localhost
  gather_facts: False
  tasks:
    - name: Die in a fire
      command: "rm -rf {{x}}/{{y}}"
  vars:
    x: ""
    y: ""
[root@diaf ~]# ansible-playbook -l localhost -vvv killme.yml
Using /etc/ansible/ansible.cfg as config file
1 plays in killme.yml

PLAY ***************************************************************************

TASK [Die in a fire] ***********************************************************
task path: /root/killme.yml:5
ESTABLISH LOCAL CONNECTION FOR USER: root
localhost EXEC /bin/sh -c '( umask 22 && mkdir -p "` echo $HOME/.ansible/tmp/ansible-tmp-1461129132.63-211170666238105 `" && echo "` echo $HOME/.ansible/tmp/ansible-tmp-1461129132.63-211170666238105 `" )'
localhost PUT /tmp/tmp78m3WM TO /root/.ansible/tmp/ansible-tmp-1461129132.63-211170666238105/command
localhost EXEC /bin/sh -c 'LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 /usr/bin/python /root/.ansible/tmp/ansible-tmp-1461129132.63-211170666238105/command; rm -rf "/root/.ansible/tmp/ansible-tmp-1461129132.63-211170666238105/" > /dev/null 2>&1'
fatal: [localhost]: FAILED! => {"changed": true, "cmd": ["rm", "-rf", "/"], "delta": "0:00:00.001740", "end": "2016-04-20 05:12:12.668616", "failed": true, "invocation": {"module_args": {"_raw_params": "rm -rf /", "_uses_shell": false, "chdir": null, "creates": null, "executable": null, "removes": null, "warn": true}, "module_name": "command"}, "rc": 1, "start": "2016-04-20 05:12:12.666876", "stderr": "rm: it is dangerous to operate recursively on ‘/’\nrm: use --no-preserve-root to override this failsafe", "stdout": "", "stdout_lines": [], "warnings": ["Consider using file module with state=absent rather than running rm"]}

NO MORE HOSTS LEFT *************************************************************
        to retry, use: --limit @killme.retry

PLAY RECAP *********************************************************************
localhost                  : ok=0    changed=0    unreachable=0    failed=1

শেষ পর্যন্ত কিছুটা অগ্রগতি! তবে এটি এখনও অভিযোগ করে যে আমি ব্যবহার করিনি --no-preserve-root

অবশ্যই, এটি আমাকে সতর্কও করেছে যে আমার মডিউলটি ব্যবহার করারfile চেষ্টা করা উচিত এবং state=absent। দেখা যাক এটি কাজ করে কিনা।

[root@diaf ~]# cat killme.yml 
---
- hosts: localhost
  gather_facts: False
  tasks:
    - name: Die in a fire
      file: path="{{x}}/{{y}}" state=absent
  vars:
    x: ""
    y: ""
[root@diaf ~]# ansible-playbook -l localhost -vvv killme.yml    
Using /etc/ansible/ansible.cfg as config file
1 plays in killme.yml

PLAY ***************************************************************************

TASK [Die in a fire] ***********************************************************
task path: /root/killme.yml:5
ESTABLISH LOCAL CONNECTION FOR USER: root
localhost EXEC /bin/sh -c '( umask 22 && mkdir -p "` echo $HOME/.ansible/tmp/ansible-tmp-1461129394.62-191828952911388 `" && echo "` echo $HOME/.ansible/tmp/ansible-tmp-1461129394.62-191828952911388 `" )'
localhost PUT /tmp/tmpUqLzyd TO /root/.ansible/tmp/ansible-tmp-1461129394.62-191828952911388/file
localhost EXEC /bin/sh -c 'LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 /usr/bin/python /root/.ansible/tmp/ansible-tmp-1461129394.62-191828952911388/file; rm -rf "/root/.ansible/tmp/ansible-tmp-1461129394.62-191828952911388/" > /dev/null 2>&1'
fatal: [localhost]: FAILED! => {"changed": false, "failed": true, "invocation": {"module_args": {"backup": null, "content": null, "delimiter": null, "diff_peek": null, "directory_mode": null, "follow": false, "force": false, "group": null, "mode": null, "original_basename": null, "owner": null, "path": "/", "recurse": false, "regexp": null, "remote_src": null, "selevel": null, "serole": null, "setype": null, "seuser": null, "src": null, "state": "absent", "validate": null}, "module_name": "file"}, "msg": "rmtree failed: [Errno 16] Device or resource busy: '/boot'"}

NO MORE HOSTS LEFT *************************************************************
        to retry, use: --limit @killme.retry

PLAY RECAP *********************************************************************
localhost                  : ok=0    changed=0    unreachable=0    failed=1

সুখবর, সবাই! এটি আমার সমস্ত ফাইল মুছে ফেলার চেষ্টা শুরু করে! তবে দুর্ভাগ্যক্রমে এটি একটি ত্রুটির মধ্যে পড়েছে। আমি এটি ঠিক করে fileএবং পাঠককে অনুশীলন হিসাবে মডিউলটি ব্যবহার করে সমস্ত কিছু ধ্বংস করার জন্য প্লেবুকটি ছেড়ে যাব ।


আপনি এই পয়েন্টের বাইরে যে কোনও প্লেবুক দেখতে পাচ্ছেন না! এক মুহুর্তে আপনি দেখতে পাবেন।

অবশেষে, অভ্যুত্থানের জন্য ...

[root@diaf ~]# cat killme.yml
---
- hosts: localhost
  gather_facts: False
  tasks:
    - name: Die in a fire
      raw: "rm -rf {{x}}/{{y}}"
  vars:
    x: ""
    y: "*"
[root@diaf ~]# ansible-playbook -l localhost -vvv killme.yml
Using /etc/ansible/ansible.cfg as config file
1 plays in killme.yml

PLAY ***************************************************************************

TASK [Die in a fire] ***********************************************************
task path: /root/killme.yml:5
ESTABLISH LOCAL CONNECTION FOR USER: root
localhost EXEC rm -rf /*
Traceback (most recent call last):
  File "/usr/lib/python2.7/site-packages/ansible/executor/process/result.py", line 102, in run
  File "/usr/lib/python2.7/site-packages/ansible/executor/process/result.py", line 76, in _read_worker_result
  File "/usr/lib64/python2.7/multiprocessing/queues.py", line 117, in get
ImportError: No module named task_result

এই ভিএম প্রাক্তন তোতা !

মজার বিষয় হচ্ছে উপরেরগুলি commandপরিবর্তে কিছু করতে ব্যর্থ হয়েছিল raw। এটা ঠিক ব্যবহার সম্পর্কে একই সাবধানবাণী মুদ্রিত fileসঙ্গে state=absent

আমি এটি বলতে যাচ্ছি যে এটি প্রদর্শিত হচ্ছে যদি আপনি এটি ব্যবহার না rawকরেন তবে rmঅ্যামোক থেকে কিছুটা সুরক্ষা পাওয়া যায় । যদিও আপনার এটির উপর নির্ভর করা উচিত নয়। আমি আনসিবলের কোডটি দিয়ে একটি তাত্ক্ষণিকভাবে নজর রেখেছি এবং আমি সতর্কবার্তাটি পেয়েছি, এমন rmকমান্ড আমি পাইনি যা আসলে কমান্ডটি চালাচ্ছিল would


10
বিজ্ঞানের জন্য +1। আমি হোস্টের নামের জন্য আরও +1 করতাম, তবে এটি প্রতারণা হবে; পি /
জার্নম্যান গিক

দেখে মনে হচ্ছে আপনার কাছে একটি ফাইল সিস্টেম মাউন্ট করা আছে /boot
84104

1
@ 84104 মজার, এটি। নিখুঁত কাকতালীয়ভাবে, bootএটি প্রথম ডিরেক্টরি এন্ট্রি /। সুতরাং কোনও ফাইল হারিয়ে যায় নি।
মাইকেল হ্যাম্পটন

5
@ আরোথ হুবহু! তবে, বিজ্ঞানের জন্য, rm -rf {{x}}/{{y}}কখন yসেট করা আছে তা চেষ্টা করুন "*"--no-preserve-rootচেক এটা কি জন্য দরকারী, কিন্তু এটা প্রতি সম্ভব পরিস্থিতির আপনি খুঁজে পাবেন না; বাইপাস করা যথেষ্ট সহজ। যে কারণে তত্ক্ষণাত্ এই প্রশ্নটি ফাঁকিবাজি হিসাবে ধরা পড়েনি: খারাপ ইংরাজী এবং আপাত সিনট্যাক্স ত্রুটিগুলি বিবেচনায় নেওয়া, এটি প্রশংসনীয়
মাইকেল হ্যাম্পটন

1
তদ্ব্যতীত raw, cronকোনও সিস্টেম বিধ্বস্ত করার একটি খারাপ উপায় হতে পারে।
84104

3

উত্তরসূরী কি rm -rf /শেল স্ক্রিপ্টে মৃত্যুদন্ড কার্যকর করবে ?

আমি কোর্টিলস আরএম উত্সটি পরিদর্শন করেছি , যার মধ্যে নিম্নলিখিত রয়েছে:

  if (x.recursive && preserve_root)
    {
      static struct dev_ino dev_ino_buf;
      x.root_dev_ino = get_root_dev_ino (&dev_ino_buf);
      if (x.root_dev_ino == NULL)
        error (EXIT_FAILURE, errno, _("failed to get attributes of %s"),
               quoteaf ("/"));
    }

রুট থেকে মুছার একমাত্র উপায় হ'ল এই কোড ব্লকটি পেরিয়ে যাওয়া। এই উত্স থেকে :

struct dev_ino *
get_root_dev_ino (struct dev_ino *root_d_i)
{
  struct stat statbuf;
  if (lstat ("/", &statbuf))
    return NULL;
  root_d_i->st_ino = statbuf.st_ino;
  root_d_i->st_dev = statbuf.st_dev;
  return root_d_i;
}

আমি এর অর্থ এটি ব্যাখ্যা করি যে ফাংশনটি get_root_dev_inoবাতিল হয়ে যায় /এবং এভাবে আরএম ব্যর্থ হয়।

প্রথম কোড ব্লক (পুনরাবৃত্তির সাথে) বাইপাস করার একমাত্র উপায় হ'ল --no-preserve-rootওভাররাইড করার জন্য এটি কোনও পরিবেশের পরিবর্তনশীল ব্যবহার করে না, সুতরাং এটি স্পষ্টভাবে আরএম এ পাস করতে হবে।

আমি বিশ্বাস করি এটি প্রমাণ করে যে যতক্ষণ না উত্তরযোগ্য স্পষ্টভাবে পাস --no-preserve-rootনা করে rm, এটি এটি করবে না।

উপসংহার

আমি বিশ্বাস করি না যে উত্তরযোগ্য স্পষ্টভাবে বাধা দেয় rm -rf /কারণ rmনিজেই এটি প্রতিরোধ করে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.