ファイル名の引用は、 `xargs sudo rm -rf`を実行するのに十分なセキュリティですか?


10

フォルダー内の最後の2つのファイルを除くすべてを削除するスクリプトを作成しました。

#!/bin/bash
ls -1 --quoting-style=shell-always /path/to/some/folder \
    | head -n -2 \
    | xargs printf -- "'/path/to/some/folder/%s'\n" \
    | xargs sudo rm -rf

このスクリプトは、毎日cronジョブとして実行されます。

その理由は次のとおりです。

  1. を使用してすべてのファイルのリストを取得しますls -1(そのため、1行に1つのファイルを取得します)。

  2. を使用してリストから最後の2つを削除しhead -n -2ます。

  3. lsは相対パスを出力するので、を使用しxargs printfてフォルダーパスを先頭に追加し、絶対パスにします。

  4. それらを送るsudo rm -rf使用xargs

誰でもこのフォルダにアクセスできるため、誰でもこのフォルダ内のファイルを作成および削除できます。

問題は、 sudo rm -rf怖いです。xargs sudo rm -rf信じられないほど怖いです。

削除する巧妙なファイルを(誤ってまたは故意に)作成することで、他のフォルダやシステムに損傷を与えないようにしたいと思います。わからない、次のような賢いもの:

file with / spaces.txt

これは非常に怖い結果になる可能性がありsudo rm -rf /ます。

編集:私の間違い、ファイル名にを含めることはできない/ため、この特定の問題は発生しませんが、他のリスクがあるかどうかについての問題はまだ残っています。

これが私がを使用している理由--quoting-style=shell-alwaysです。これにより、スペースのあるファイルでのトリックが防止されます。しかし、私は誰かがファイル名にスペース引用符で余分に賢いのではないかと思っています。

スクリプトは安全ですか?


注:必要なのはsudo、(マップされたネットワークドライブからを使用してmount)リモートでフォルダーにアクセスしているためです。sudo がないと機能しません。


3
あなたは何かをすることを考えましたprintf -- '%s\0' /path/to/some/folder/* | head -zn -2 | xargs -0 rmか?
鋼の運転手2018

/名前に文字が含まれているファイルを作成できますか?ここでこれを達成しようとしています
ジョージウドセン

3
@Georgeいいえ、ファイル名にスラッシュを含めることはできません。
wjandrea 2018

OPが賢い人と言ったとき、私は不思議に思っていました...
ジョージウドセン

6
ls出力を解析しているという理由だけで、引用符を付けても、これはすでに不十分なコマンドです。ls私はの目的何が表示されないので、また、私が思うに、順番を並べ替えるためのロケールを使用してhead、あなたがしているのを取り除くしようとしない限り、(最後の2を除去する...IIRCの引数として許可されていないrmとにかく。ただ、使用をfind /path/to/folder -type f delete。そして、sudocronから実行する場合- いいえ、cronはすでにルートレベルにあります
Sergiy Kolodyazhnyy

回答:


10

Linuxでは、次の場合を除いて、任意の文字が有効なファイル名構成文字です。

  • \0 (ASCII NUL):Cでの文字列終了に使用
  • / (スラッシュ):パスの分離に使用

したがって、あなたが想像できるように、あなたのアプローチは多くの場合間違いなく機能しません。たとえば\n、ファイル名の改行()を処理しますか?(ヒント: いいえ)。

いくつかのメモ:

  • 解析しないでくださいls。専用ツールを使用する(ほとんどのユースケースに少なくとも1つあります)
  • ファイル名を扱うときは、そのようなデータを扱うほとんどすべてのGNUツールによって提供されるNUL分離出力を活用するようにしてください
  • 配管時には注意して、両方のプログラムがNUL分離を理解できることを確認してください
  • を呼び出すときはいつでもxargs、を使いこなせるかどうかを確認してくださいfind ... -exec。ほとんどの場合、あなたはfind一人で大丈夫です

これらは今のところあなたを動かしてくれると思います。steeldriverはすでにコメント(printf -- '%s\0' /path/to/some/folder/* | head -zn -2 | xargs -0 rm)でNUL分離のアイデアを提供しています。これを出発点として使用してください。


答えてくれてありがとう:)単に言及するのではなく、steeldriverのコメントを引用すべきだと思います(コメントは永続的ではないため)。私はに見てみましょうfind、同様の提案に感謝を。
ペドロA

しかし、私は1つの質問があります。「あなたのアプローチは、多くの場合、想像できるほど確実に機能しない」という意味がわかりません-「安全ではない」または「安全ではない」のように「機能しない」?「あなたのアプローチ」は悪意のあるユーザーではなく私を指しており、あなたの以前の発言は私の賛成なので、私は混乱しています。
ペドロA

@PedroAあなたはあなたです :)私が言ったように、前述の2つを除いてすべての文字が有効であるため、ls解析アプローチが失敗する多くのケースを想像できるはずです(たとえば、ファイル名の改行を考慮に入れましたか?)
heemayl 2018

ああ、ファイル名の改行...考えていませんでした。あなたの答えにそれを追加することも気にしない場合:)また、質問して申し訳ありませんが、何をしhead -zますか?ばかげて聞こえるかもしれませmaninfoが、CoreOSコンテナlinux もありません...インターネットでも見つかりませんでした。私が得るhead: invalid option 'z'
ペドロA

@PedroA改行は1つのケースにすぎず、ご想像のとおり多くあります。GNUが必要ですhead(GNUに付属coreutils)。これがオンラインバージョンです:manpages.ubuntu.com/manpages/xenial/man1/head.1.html
heemayl

3

xargs は、いくつかの引用をサポートしています。単一引用符、二重引用符、または任意の引数を受け入れることができるバックスラッシュを使用しますが、Bourneのようなシェルの引用構文とは異なる構文を使用します。

lsUbuntuで見つかったのGNU実装には、xargs入力形式と互換性のある引用モードがありません。

これls --quoting-style=shell-alwaysは、ksh93、bash、およびzshシェルの引用構文と互換性がありますが、の出力が、出力時lsと同じロケールのシェルによって解釈された場合のみlsです。また、BIG5、BIG5-HKSCS、GBK、GB18030を使用するロケールなど、一部のロケールは避けてください。

これらのシェルを使用すると、実際に次のことができます。

typeset -a files
eval "files=($(ls --quoting-style=shell-always))"
xargs -r0a <(printf '%s\0' "${files[@]:0:3}") ...

しかし、それには次の利点はほとんどありません。

files=(*(N))                 # zsh
files=(~(N)*)                # ksh93
shopt -s nullglob; files=(*) # bash

これが役立つ唯一のケースは、ファイルをmtime / atime / ctimeまたは/でソートする-tオプションを使用する場合です。しかし、それでも、を使用することもできます。ls-S-Vzsh

files=(*(Nom))

たとえば、ファイルをmtimeでソートする(oLfor -Snforを使用-V)。

最近変更された2つの通常ファイルを除くすべてを削除するには:

rm -f -- *(D.om[3,-1])

stillいくつかの長さの制限がまだあり(execve()一部の非GNU xargs実装では任意の値がはるかに低い)、一部の非GNU xargs実装では、有効な文字を形成しないバイトシーケンスを含む入力が制限されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.