BASH- und Wagenrücklaufverhalten

10

Ich habe eine kurze Frage.
Ist es normal, dass bash (ich verwende 4.4.11) keine Zeilen / Texte anzeigt, die getrennt sind / mit Plain enden \r?

Ich war etwas überrascht, dieses Verhalten zu sehen:

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

Aber "Hallo nochmal" Text ist immer noch da, irgendwie "versteckt":

$ 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

Und sobald wir nur mit Bash spielen, ist das in Ordnung ... Aber ist dies ein potenzielles Sicherheitsrisiko? Was ist, wenn der Inhalt der Variablen "a" aus der Außenwelt stammt und "schlechte Befehle" enthält, anstatt nur Hallo?

Ein weiterer Test, diesmal etwas unsicher:

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

Stellen Sie sich ein verstecktes rmstatt eines versteckten vor ls.

Gleiches Verhalten bei Verwendung von echo -e:

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

Bin ich es, der etwas falsch macht ...?

George Vasiliou
quelle

Antworten:

19

Ihr echo "$a"druckt "Hallo", geht dann zurück zum Anfang der Zeile (was auch immer der \rFall ist), druckt "wieder", geht wieder zurück, druckt "George", geht wieder zurück und geht zur nächsten Zeile ( \n). Es ist alles völlig normal, aber wie chepner betont , hat es nichts mit Bash zu tun: \rund \nwird vom Terminal interpretiert, nicht von Bash (weshalb Sie die volle Ausgabe erhalten, wenn Sie den Befehl an weiterleitenod ).

Sie können dies besser sehen mit

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

da das Ende des überschriebenen Textes übrig bleibt:

georgen,o

Sie können dies jedoch nicht wirklich verwenden, um Befehle auszublenden, sondern nur deren Ausgabe (und nur, wenn Sie sicher sein können, dass Sie mit genügend Zeichen überschreiben), es sei denn, evalSie verwenden sie wie gezeigt (die Verwendung evalwird jedoch im Allgemeinen nicht empfohlen). Ein gefährlicherer Trick ist die Verwendung von CSS zum Maskieren von Befehlen , die von Websites kopiert und eingefügt werden sollen.

Stephen Kitt
quelle
Klar genug, danke. Ich hatte Glück / Pech, ein letztes Wort in meinem Test zu verwenden, das die beiden vorherigen Wörter vollständig überschreiben konnte.
George Vasiliou
2
Beachten Sie jedoch, dass dies eigentlich nichts damit zu tun bashhat. Es liegt ganz beim Terminal, wie der Wagenrücklauf "angezeigt" wird oder wie die überschriebenen Zeichen angezeigt werden. Zum Beispiel wäre es durchaus gültig, wenn ein Terminal -\r|als etwas angezeigt würde, das einem Pluszeichen ähnelt, und nicht nur als Pipe.
Chepner
@chepner Gut zu wissen! Danke für das Teilen. Ich dachte, dass dies nur ein Bash-Verhalten war.
George Vasiliou
@ GeorgeVasiliou Nein, bashschreibt nur Bytes in eine Datei; Es liegt an jedem, der diese Bytes liest, sie zu interpretieren.
Chepner
Nitpick: printf, die ein bash Befehl eingebaut ist (auch wenn es existiert auch als eigenständiges ausführbaren), interpretiert die \r(eine Folge von zwei Bytes 0x5cund 0x72und erzeugt den Wagenrücklauf (ein Byte: 0x0d.) Dann, ja, das Endgerät interpretiert das Byte 0x0dauf besondere Weise, interpretiert aber nicht die ursprüngliche Zeichenfolge \r.
Suzanne Dupéron
6

In der Unix-Welt ist ein Wagenrücklauf (üblicherweise wie \rin Programmiersprachen codiert ) ein unauffälliges Steuerzeichen. Sie können Wagenrückläufe innerhalb einer Textzeile haben, wie jedes andere Zeichen außer einem Zeilenvorschub (auch Zeilenumbruch genannt ), der das Ende einer Zeile markiert.

Insbesondere in einem Bash-Skript ist ein Wagenrücklauf ein gewöhnliches Wortbestandteil wie Buchstaben und Ziffern. Ein besonderer Effekt des Wagenrücklaufs kommt vom Terminal, nicht von der Schale.

Ein Wagenrücklauf ist ein Steuerzeichen . Wenn Sie es auf einem Terminal drucken, führt das Terminal anstelle eines Glyphen einen Spezialeffekt aus. Bei einem Wagenrücklauf besteht der Spezialeffekt darin, den Cursor an den Anfang der aktuellen Zeile zu bewegen. Wenn Sie also eine Zeile drucken, die einen Wagenrücklauf in der Mitte enthält, wird die zweite Hälfte über die erste Hälfte geschrieben.

Einige andere Steuerzeichen haben Spezialeffekte: Das Rücktastezeichen bewegt den Cursor um eine Position nach links. Das Klingelzeichen bewirkt, dass das Terminal einen Ton abgibt oder auf andere Weise die Aufmerksamkeit des Benutzers auf sich zieht. Der Escape-Charakter startet eine Escape-Sequenz, die alle Arten von Spezialeffekten haben kann.

Wenn Sie eine nicht vertrauenswürdige Ausgabe anzeigen, müssen Sie Steuerzeichen bereinigen oder maskieren. Nicht nur der Wagen kehrt zurück, sondern auch einige andere, insbesondere der Fluchtcharakter, der alle möglichen negativen Auswirkungen haben kann. Siehe Kann das "Cating" einer Datei ein potenzielles Sicherheitsrisiko darstellen? und Wie vermeide ich Fluchtsequenzangriffe in Terminals? für mehr zum Thema.

Gilles 'SO - hör auf böse zu sein'
quelle
0

Sie können die Wagenrückläufe in einer Bash-Variablen anzeigen, indem Sie die printfFunktion mit einem %qFormat verwenden.

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

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

Quellen und weiterführende Literatur:

Nuwandame
quelle