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

І як тільки ми просто граємо з башем, це добре .... Але це потенційний ризик для безпеки? Що робити, якщо вміст змінної "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

Це я щось робить не так ...?

Відповіді:


20

Ваші echo "$a"відбитки "привіт", потім повертаються до початку рядка (що і \rробить), друкуються "знову", повертаються назад, друкуються "george", повертаються знову і переходять до наступного рядка ( \n). Це абсолютно нормально, але, як вказує Чепнер , це не має нічого спільного з Bash: \rі \nінтерпретується терміналом, а не Bash (саме тому ви отримуєте повний вихід, коли передаєте команду od).

Ви можете це бачити краще

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

оскільки це залишить кінець перезаписаного тексту:

georgen,o

Ти не можеш використовувати це, щоб приховати команди, лише їх вихід (і лише якщо ти можеш перезаписати достатньо символів), за винятком випадків використання, evalяк показуєш (але використання, evalяк правило, не рекомендується). Більш небезпечний трюк - це використання CSS для маскування команд, призначених для копіювання та вставлення з веб-сайтів.


Досить чітко, дякую. Мені пощастило / не пощастило використати останнє слово у своєму тесті, здатне повністю переписати попередні два слова.
Джордж Васильоу

2
Зауважте, що це насправді не має нічого спільного bash; повністю залежить від терміналу, як "відобразити" повернення каретки або як відобразити перезаписані символи. Наприклад, було б цілком справедливо, щоб термінал відображав -\r|як щось, що нагадує знак плюс, а не просто трубу.
чепнер

@chepner Добре знати! Дякую, що поділились. Я подумав, що це просто баштанська поведінка.
Георгій Васильоу

@GeorgeVasiliou Nope, bashпросто записує байти у файл; це залежить від того, хто читає ці байти, щоб їх інтерпретувати.
чепнер

Чіплятися: printf, який Баш вбудовані команди (хоча вона також існує як окремий виконуваний файл), інтерпретує \r(послідовність з двох байт: 0x5cі 0x72та здійснює повернення каретки (один байт: 0x0d.) Тоді, так, термінал інтерпретує байт 0x0dпо-особливому, але він не інтерпретує початковий рядок \r.
Сюзанна Дюперон

6

У світі Unix повернення каретки (зазвичай кодується як \rу мовах програмування) - це непересічний характер управління. Ви можете мати повернення каретки всередині рядка тексту, як і будь-який інший символ, крім каналу рядка (який також називається новим рядком ), який позначає кінець рядка.

Зокрема, у баш-скрипті повернення вагона - це звичайне слово, що складається зі символів, як букви та цифри. Будь-який особливий ефект повернення каретки надходить з терміналу, а не з оболонки.

Повернення вагона - це контрольний символ . Коли ви друкуєте його до терміналу, замість того, щоб відображати гліф , термінал виконує якийсь особливий ефект. Для повернення каретки особливим ефектом є переміщення курсору на початок поточного рядка. Таким чином, якщо ви надрукуєте рядок, який містить повернення каретки посередині, то ефект полягає в тому, що друга половина пишеться за першу половину.

Кілька інших символів управління мають спеціальні ефекти: символ зворотної області переміщує курсор вліво на одну позицію. Символ дзвоника змушує термінал видавати звук або іншим чином привертати увагу користувача. Персонаж втечі починає послідовність евакуації, яка може мати всі види спеціальних ефектів.

Якщо відображається ненадійний висновок, вам потрібно скребти або уникнути символів управління. Повертається не лише вагон, а й кілька інших, зокрема персонаж втечі, який може спричинити всілякі погані наслідки. Див. Чи може "котирування" файлу бути потенційним ризиком для безпеки? і Як уникнути атак послідовності втечі в терміналах? для отримання додаткової інформації по темі.


0

Ви можете переглянути повернення каретки у змінній bash, використовуючи printfфункцію з %qформатом.

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

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

Джерела та подальше читання:

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.