BASH和回车行为


11

我有一个简单的问题。
bash(我使用的是4.4.11)显示的行/文本以纯文本分隔/结尾是否正常\r

我对这种行为感到有些惊讶:

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

但是“ hello again”文本仍然存在,以某种方式“隐藏”:

$ 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”的内容来自外部并且包含“错误命令”而不是仅仅打招呼怎么办?

另一个测试,这次有点不安全:

$ 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

是我做错事了吗...?

Answers:


20

您的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掩盖要从网站复制和粘贴的命令


很清楚,谢谢。我很幸运/很不幸在测试中使用了一个能够完全覆盖前两个单词的单词。
乔治·瓦西里乌

2
注意,这实际上与无关bash。如何“显示”回车符或如何显示被覆盖的字符完全取决于终端。例如,对于终端来说,将其显示-\r|为类似于加号的东西而不仅仅是管道是完全有效的。
chepner '17

@chepner很高兴知道!感谢分享。我以为这只是一个bash行为。
乔治·瓦西里乌

@GeorgeVasiliou Nope,bash只是将字节写入文件;取决于谁读取这些字节来解释它们。
chepner '17

挑剔:printf,这是内置命令一个bash(虽然它也存在作为一个独立的可执行文件),解释该\r(一个的两个字节序列:0x5c0x72并且产生回车(一个字节:0x0d)。然后,是,则终端解释字节0x0d以一种特殊的方式,但它并没有解释原始的字符串\r
苏珊Dupéron

6

在Unix世界中,回车符(通常\r以编程语言编码)是不起眼的控制字符。您可以在一行文本中包含回车符,就像换行符(也称为newline)以外的其他任何字符一样,换行符用于标记一行的结尾。

特别是在bash脚本中,回车符是普通的单词构成字符,例如字母和数字。回车的任何特殊影响都来自终端,而不是外壳。

回车是控制字符。当您将其打印到终端时,终端不显示字形,而是执行某些特殊效果。对于回车,特殊效果是将光标移动到当前行的开头。因此,如果您在中间打印包含回车符的行,则结果是后半部分写在前半部分上。

其他几个控制字符也有特殊效果:退格字符将光标向左移动一个位置。响铃字符使终端发出声音或以其他方式引起用户的注意。转义字符开始一个转义序列,该序列可以具有各种特殊效果。

如果显示不受信任的输出,则需要清除或转义控制字符。不仅回车,而且还有其他几个回车符,尤其是转义符,可能导致各种不良影响。请参阅“捕获”文件是否有潜在的安全风险?以及如何避免终端中的转义序列攻击?有关该主题的更多信息。


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

资料和进一步阅读:

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.