web-dev-qa-db-ja.com

BASHとキャリッジリターンの動作

簡単な質問があります。
bash(私は4.4.11を使用しています)が、分離されている/プレーン\rで終わる行/テキストを表示しないのは正常ですか?

この動作を見て、私は少し驚きました:

$ a=$(printf "hello\ragain\rgeorge\r\n")
$ echo "$a"
george

しかし、「こんにちは」というテキストはまだ残っています。どういうわけか「隠されています」:

$ echo "$a" |od -w32 -t x1c
0000000  68  65  6c  6c  6f  0d  61  67  61  69  6e  0d  67  65  6f  72  67  65  0d  0a
          h   e   l   l   o  \r   a   g   a   i   n  \r   g   e   o   r   g   e  \r  \n

そして、bashで遊ぶだけでいいのですが...これは潜在的なセキュリティリスクですか?変数 "a"の内容が外部の世界からのものであり、helloだけでなく "bad commands"が含まれている場合はどうなりますか?

別のテスト、今回は少し安全ではありません:

$ a=$(printf "ls;\rGeorge\n")
$ echo "$a"
George
$ eval "$a"
0                   awkprof.out       event-tester.log  helloworld.c      oneshot.sh         rightclick-tester.py  tmp                    uinput-simple.py
<directory listing appears with an error message at the end for command George>

非表示のrmではなく、非表示のlsを想像してみてください。

Echo -eを使用する場合の同じ動作:

$ a=$(echo -e "ls;\rGeorge\r\n"); echo "$a"
George

何か間違ったことをするのは私ですか...?

11
George Vasiliou

君の echo "$a"は「hello」を出力してから、行の先頭に戻ります(これは\rは)、「もう一度」印刷し、再び戻り、「george」を印刷し、再び戻り、次の行に進みます(\n)。すべて完全に正常ですが、 chepner が指摘するように、Bashとは何の関係もありません:\rおよび\nは、Bashではなく端末によって解釈されます(コマンドをodにパイプすると、完全な出力が得られるのはこのためです)。

あなたはこれをよりよく見ることができます

$ a=$(printf "hellooooo\r  again,\rgeorge\r\n")
$ echo "$a"

それは上書きされたテキストの終わりを残すので:

georgen,o

ただし、実際にevalを使用して(ただしevalを使用して)、コマンドを非表示にすることはできません。通常は推奨されません)。より危険なトリックは CSSを使用してコマンドをマスクする Webサイトからコピーして貼り付けることです。

20
Stephen Kitt

Unixの世界では、 キャリッジリターン (プログラミング言語では一般に\rとしてエンコードされます)は目立たない制御文字です。行の終わりを示す改行( newline とも呼ばれます)を除く他の文字と同様に、テキスト行内に改行を入れることができます。

特に、bashスクリプトでは、キャリッジリターンは文字や数字のような通常のWord構成文字です。キャリッジリターンの特殊効果は、シェルからではなくターミナルから発生します。

復帰は 制御文字 です。 glyph を表示する代わりに、ターミナルに出力すると、ターミナルは特別な効果を発揮します。復帰の場合、特殊な効果として、カーソルが現在の行の先頭に移動します。したがって、途中に改行を含む行を印刷すると、前半部分の上に後半部分が上書きされるという効果があります。

他のいくつかの制御文字には特別な効果があります。バックスペース文字はカーソルを1ポジション左に移動します。ベル文字は、端末に音を鳴らしたり、ユーザーの注意を引き付けたりします。エスケープ文字は エスケープシーケンス で始まり、あらゆる種類の特殊効果を持つことができます。

信頼できない出力を表示する場合は、制御文字をスクラブまたはエスケープする必要があります。キャリッジリターンだけでなく、その他のいくつか、特にエスケープ文字もさまざまな悪影響を引き起こす可能性があります。このトピックの詳細については、 ファイルを「キャッティング」することは潜在的なセキュリティリスクになる可能性がありますか? および 端末でのエスケープシーケンス攻撃を回避する方法? を参照してください。

%q形式でprintf関数を使用すると、bash変数の改行を表示できます。

$ TESTVAR="$(printf ' Version: 1 \r Build: 20180712 \r Test: 1324')"

$ printf %q $TESTVAR
Version:1$'\r'Build:20180712$'\r'Test:1324

出典および参考文献:

0
nuwandame