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


11

簡単な質問があります。
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

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

回答:


20

あなたのecho "$a"印刷物は、「こんにちは」、そしてバック(何行の先頭に戻り\rません)、「再び」印刷し、再び戻り、版画「ジョージ」、再び戻り、次の行(に行きます\n)。それはすべて完全に正常ですが、chepnerが指摘しているように、Bash \r\nは何の関係もありません。これは、Bashではなくターミナルによって解釈されます(そのため、コマンドをにパイプすると、完全な出力が得られますod)。

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

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

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

georgen,o

コマンドを非表示にするためにそれを実際に使用することはできませんが、表示evalどおりに使用しない限り、コマンドの出力のみ(および十分な文字で確実に上書きできる場合のみ)を使用します(ただし、eval一般に使用は推奨されません)。より危険なトリックは、CSSを使用して、Webサイトからコピーして貼り付けることを目的としたコマンドをマスクすることです。


ありがとうございます。前の2つの単語を完全に上書きできるテストで最後の単語を使用できたのは幸運/不運でした。
George Vasiliou 2017

2
ただし、これはとはまったく関係ありませんbash。キャリッジリターンを「表示」する方法、または上書きされた文字を表示する方法は、完全にターミナル次第です。たとえば、端末-\r|が単なるパイプではなく、プラス記号に似たものとして表示されることは完全に有効です。
chepner 2017

@chepner知っておきたい!共有いただきありがとうございます。これは単なるbashの振る舞いと思いました。
George Vasiliou 2017

@GeorgeVasiliouいいえ、bashバイトをファイルに書き込みます。それらを解釈するためにそれらのバイトを読み取る人次第です。
chepner 2017

Nitpick:printfは、bash組み込みコマンドです(スタンドアロンの実行可能ファイルとしても存在します)は、\r(2バイトのシーケンス:0x5cを解釈0x72し、キャリッジリターン(1バイト:)を生成し0x0dます。次に、はい、ターミナル解釈バイト0x0d特別な方法で、それは元の文字列を解釈することはありません\r
スザンヌDupéron

6

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

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

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

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

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


0

フォーマットprintf付きの関数を使用して、bash変数の改行を表示でき%qます。

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

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

出典および参考文献:

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