gawkの-iオプションまたは@includeディレクティブを安全に使用する方法は?

gawkの-iオプションまたは@includeディレクティブを安全に使用する方法は?

gawk -i inplace some-awk-code some-file内部で(またはスクリプト@include "inplace"から)awkファイル(または他の拡張子)を編集します。セキュリティホールです

なぜ?

この問題をどのように解決できますか?

ベストアンサー1

awkGNUには、実行するコードを指定するという点で、標準に対するいくつかの拡張があります。

標準では、コードを読み取るファイルパスと見なされる1つ以上の最初の非オプション引数(gawkなど)でのみawkコードを渡すことができます。 gawkにはより多くのオプションがあります。-f filepathfilepathawk -- 'literal code here'

  • -e 'literal code'(または--source 'literal code')のように、sedコードを複数のパラメータに分割し、-f filepathそのパラメータをパラメータ間で分散できます。
  • -E filepath(または--exec filepath)、-f1つしか存在できないこと、およびそれ以降のすべての項目は、オプションまたは変数の割り当てを考慮せずにファイルパス(または-標準入力)のみを考慮することを除いて同じです。
  • --file filepath:エイリアス-f
  • -i filepath(または):--include filepath動作に似ていますが、若干の変更があります。-fマニュアルに記載されているように

今質問はgawkファイルパス上記のすべてが常にファイルパスと見なされるわけではありません。

  1. もしファイルパス存在しない場合は、gawk拡張子が追加された同じファイルを開こうとします.awk。つまり、意図しないコードを解釈する可能性がありますが、実行しようとしているファイルが存在しないため、実際に問題になる可能性はほとんどありません。--traditionalorではそうしませんが、-W traditionalほとんどのgawk拡張機能を使用することはできません。
  2. もしファイルパス/文字が含まれていない場合(およびそうでない場合-)、awkプログラムは$AWKPATHシェルと同様の方法で環境変数を検索するか、withおよびwithを含むすべての//(および説明されているように、またはwithでexecvp()スラッシュのないコマンドを検索します。の拡張子が追加された場合)。$PATH--posix--traditional-f-i-E.awk

2番目のポイントはここで問題の中心です。

以下では、デフォルトのAWKPATHを見つけることができます。

$ (unset -v AWKPATH && gawk 'BEGIN{print ENVIRON["AWKPATH"]}')
.:/usr/share/awk

(メンションにはそんな変数がないのにENVIRON!)

現在の作業ディレクトリから始めて、その後にいくつかの拡張機能または..NETに付属の他のawkサードパーティモジュールを含むシステムの場所が続きますgawk。このシステムでは:

$ls /usr/share/awk
Assert.awk getlong.awk intdiv0.awk ord.awk rewind.awk
bit2str.awk getopt.awk isnumeric.awk passwd.awk round.awk
Cliff_rand.awk gettime.awk Join.awk processarray.awk shellquote.awk
ctime.awk グループ.awk libintl.awk fastsort.awk strtonum.awk
dpkg-awk.awk have_mpfr.awk nosign.awk 読み取り可能.awk walkarray.awk
ftrans.awk      所定の位置に.awk    ns_passwd.awk ファイルの読み取り.awk ゼロファイル.awk

つまり、-f/の場合は現在の作業ディレクトリにロードし-Eたい場合に必要であり、現在の作業ディレクトリにない場合は他の場所からロードできます(または)。シェルで実行するには、現在の作業ディレクトリが必要なのと同じです(セキュリティ上の理由から通常は含まれておらず、上記のようにロードしようとしていることを除いて)。filegawk -f ./filegawk -f filefilefile.awkfile./cmdcmd$PATH.gawkfile.awk

これは一般的なものに加えて適用されます-i-i含むこの場合、ライブラリのgawk拡張するそれらがなければならないディレクトリにそれらを見つけることを期待し、する拡張を追加したいのですが.awk(ライブラリの拡張には通常これらの拡張があるため)。

(またはシステムにインストールされている場所)を探しgawk -i inplace 'some code' some-fileたいが、ここで問題はデフォルトのAWKPATHです。gawk/usr/share/awk/inplace.awkinplace.awkスタートand.なので、gawkandで最初に照会されます。./inplace./inplace.awk

/tmp書き込み可能であるか、すでに他の人が書き込んだり、通常は信頼できないディレクトリでこのファイルを実行すると、マルウェアが実行される可能性があります。

たとえば、次のようにします。

echo 'BEGIN{system("reboot")}' > /tmp/inplace

awk -i inplace現在の作業ディレクトリで実行されているすべてのスクリプトが/tmpシステムを再起動することがわかります。

この問題を解決するには:

  • inplace各システムまたはGawk展開に合わせてパスを調整する必要があるかもしれませんが、拡張awk -i /usr/share/awk/inplace.awkパスをハードコーディングする代わりに使用してください。awk -i inplace

  • または、.すべての相対パスコンポーネントを削除します$AWKPATH

    export AWKPATH="$(LC_ALL=C gawk 'BEGIN {
      n = split(ENVIRON["AWKPATH"], dirs, ":")
      for (i = 1; i <= n; i++)
        if (substr(dirs[i], 1, 1) == "/") {
          newawkpath = newawkpath sep dirs[i]
          sep = ":"
        }
      if (newawkpath == "") newawkpath = "/dev/null"
      print newawkpath}')"
    

    現在の作業ディレクトリでファイルを使用またはgawk -f ./fileロードする必要があることに注意してください(上記の変更を加えずにすでにこれを行っている可能性があります)。また、4.1.2より前のgawkバージョンがレビュー中であることに注意してください。awk -E ./file$AWKPATH$AWKPATH

    この方法は起動時に環境にすでに存在している必要があるため、#! /usr/bin/gawk -E使用するスクリプトでは使用できません。したがって、使用するスクリプトがある場合は、ユーザーに拡張パスを変更するか、上記のように拡張パスをハードコードするように指示する必要があります。@include$AWKPATHgawkgawk@include "some-extension"$AWKPATH

  • または、何十年もperl使用されていた-i内部編集オプションを使用して、すべての可能なタスクを実行し、awkよりスマートな構文²とより少ない移植性の問題でより多くのタスクを実行できます。しかし--inを忘れないでくださいperl -i -ne 'perl code' -- *.txt。そうしないと、コード注入の脆弱性が発生する可能性があります(またはを使用してください./*.txt。を参照)。perl -ne '...'実行のセキュリティリスク*)!


¹そうでない場合ファイルパス-この場合、ほとんどの実装はawkこれを標準入力からコードを読み取ると解釈します。

sと同じであると考えられる²perlオプションは、他の相対パスを含まず、含まないデフォルト検索パスを使用します(参照)ま​​たはでモジュールを検索する-Mgawk-iM$PERL5LIB$PERLLIB(unset -v PERL5LIB PERLLIB && perl -le 'print for @INC'.

おすすめ記事