gawk -i inplace some-awk-code some-file
内部で(またはスクリプト@include "inplace"
から)awk
ファイル(または他の拡張子)を編集します。セキュリティホールです。
なぜ?
この問題をどのように解決できますか?
ベストアンサー1
awk
GNUには、実行するコードを指定するという点で、標準に対するいくつかの拡張があります。
標準では、コードを読み取るファイルパスと見なされる1つ以上の最初の非オプション引数(gawkなど)でのみawk
コードを渡すことができます。 gawkにはより多くのオプションがあります。-f filepath
filepath
awk -- 'literal code here'
-e 'literal code'
(または--source 'literal code'
)のように、sed
コードを複数のパラメータに分割し、-f filepath
そのパラメータをパラメータ間で分散できます。-E filepath
(または--exec filepath
)、-f
1つしか存在できないこと、およびそれ以降のすべての項目は、オプションまたは変数の割り当てを考慮せずにファイルパス(または-
標準入力)のみを考慮することを除いて同じです。--file filepath
:エイリアス-f
。-i filepath
(または):--include filepath
動作に似ていますが、若干の変更があります。-f
マニュアルに記載されているように。
今質問はgawk
、ファイルパス上記のすべてが常にファイルパスと見なされるわけではありません。
- もしファイルパス存在しない場合は、
gawk
拡張子が追加された同じファイルを開こうとします.awk
。つまり、意図しないコードを解釈する可能性がありますが、実行しようとしているファイルが存在しないため、実際に問題になる可能性はほとんどありません。--traditional
orではそうしませんが、-W traditional
ほとんどのgawk拡張機能を使用することはできません。 - もしファイルパス
/
文字が含まれていない場合(およびそうでない場合-
)、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
たい場合に必要であり、現在の作業ディレクトリにない場合は他の場所からロードできます(または)。シェルで実行するには、現在の作業ディレクトリが必要なのと同じです(セキュリティ上の理由から通常は含まれておらず、上記のようにロードしようとしていることを除いて)。file
gawk -f ./file
gawk -f file
file
file.awk
file
./cmd
cmd
$PATH
.
gawk
file.awk
これは一般的なものに加えて適用されます-i
。-i
含むこの場合、ライブラリのgawk拡張するそれらがなければならないディレクトリにそれらを見つけることを期待し、する拡張を追加したいのですが.awk
(ライブラリの拡張には通常これらの拡張があるため)。
(またはシステムにインストールされている場所)を探しgawk -i inplace 'some code' some-file
たいが、ここで問題はデフォルトのAWKPATHです。gawk
/usr/share/awk/inplace.awk
inplace.awk
スタートand.
なので、gawk
andで最初に照会されます。./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
$AWKPATH
gawk
gawk
@include "some-extension"
$AWKPATH
または、何十年も
perl
使用されていた-i
内部編集オプションを使用して、すべての可能なタスクを実行し、awk
よりスマートな構文²とより少ない移植性の問題でより多くのタスクを実行できます。しかし--
inを忘れないでくださいperl -i -ne 'perl code' -- *.txt
。そうしないと、コード注入の脆弱性が発生する可能性があります(またはを使用してください./*.txt
。を参照)。perl -ne '...'実行のセキュリティリスク*)!
¹そうでない場合ファイルパス-
この場合、ほとんどの実装はawk
これを標準入力からコードを読み取ると解釈します。
sと同じであると考えられる²perl
オプションは、他の相対パスを含まず、含まないデフォルト検索パスを使用します(参照)またはでモジュールを検索する-M
gawk
-i
M
$PERL5LIB
$PERLLIB
(unset -v PERL5LIB PERLLIB && perl -le 'print for @INC'
.