Bash

BASH 和輸入行為

  • July 12, 2018

我有一個簡單的問題。

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 怎麼辦?

另一個測試,這次有點不安全:

$ 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>

想像一個 hiddenrm而不是 hidden ls

使用 echo -e 時的行為相同:

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

難道是我做錯了什麼……?

echo "$a"列印“hello”,然後返回到行首(這是什麼\r),列印“again”,再次返回,列印“george”,再次返回,然後轉到下一行(\n)。這一切都很正常,但正如chepner指出的那樣,它與 Bash: 沒有任何關係,\r並且\n由終端解釋,而不是由 Bash 解釋(這就是為什麼當你將命令傳遞給 時你會得到完整的輸出od)。

你可以更好地看到這一點

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

因為這將留下覆蓋文本的結尾:

georgen,o

但是,您不能真正使用它來隱藏命令,只能使用它們的輸出(並且僅當您可以確保用足夠的字元覆蓋時),除非eval按照您顯示的方式使用(但eval通常不建議使用)。一個更危險的技巧是使用 CSS 來屏蔽要從網站複製和粘貼的命令。

引用自:https://unix.stackexchange.com/questions/355559