Что особенного в "!xxx%s%s%s%s%s%s%s%s%s"?

Что особенного в "!xxx%s%s%s%s%s%s%s%s%s"?

Я был связан сСправочник ненавистников Unixи наткнулся на (стр. 149):

Тема: Соответствующая ошибка Unix

11 октября 1991 г.

Студенты W4115x —

Пока мы говорим о записях активации, передаче аргументов и соглашениях о вызовах, знаете ли вы, что ввод:

!xxx%s%s%s%s%s%s%s%s

в любой C-shell приведет к его немедленному краху? Знаете почему?

Вопросы для размышления:

  • Что делает оболочка, когда вы печатаете !xxx?
  • Что он делает с введенными вами данными, когда вы печатаете !xxx%s%s%s%s%s%s%s%s?
  • Почему это приводит к сбою оболочки?
  • Как можно (довольно легко) переписать проблемную часть оболочки, чтобы не возникало этой проблемы?

Чисто из любопытства, может кто-нибудь объяснить, в чем проблема? Неудивительно, что поиск строки в Google не помогает. Поиск других цитат из сообщения дал мне только другие копии сообщения, но никаких объяснений.

решение1

Мне не хочется копаться в источниках 25-летних ракушек, но

Это может бытьуязвимость форматной строки.

Если оболочка содержит код вроде

printf(str);

где strнекоторая строка, взятая из ввода пользователя, содержимое строки будет строкой формата, которая printfиспользует. %s' говорит о printfнеобходимости вывести строку, на которую указывает аргумент. Если аргументы не указаны (как выше, есть только строка формата), функция будет считывать некоторые другие данные из стека и следовать им как указателям. Вероятно, обращаясь к неотображенной памяти и завершая процесс.

В некотором смысле, я думаю, что формулировка сообщения также намекает на решение, подобное этому. Если вы набираете !xxx, оболочка явно выводит сообщение об ошибке, например !xxx: event not found. Отсюда не так уж и много, чтобы попытаться также вывести !xxx%s%s%s%s%s%s%s%s: event not found, что подразумевает уязвимость форматной строки.


Мне не следовало этого делать, но я заглянул в источник.здесь( 4.3BSD-Tahoe/usr/src/bin/csh, даты с 1988 года).

findev(cp, anyarg)вsh.lex.cпохоже, это может быть функция для поиска соответствующего события истории: она проходит по связанному списку struct Histвызванных Histlist. Если ничего не находит, то вызывает seterr2(cp, ": Event not found");. noev()здесь cpвыглядит строка, которую ищут в истории.

seterr2()устанавливает переменную errкак конкатенацию аргументов и errиспользуется как if (err) error(err);в нескольких местах в process(), вsh.c. Наконец, error()sh.err.c) содержит классическую уязвимость форматной строки:if (s) printf(s, arg), printf(".\n");

В некоторых других местах error()вызывается с аргументом, например error("Unknown user: %s", gpath + 1);, , поэтому очевидно, что идея заключается в том, что первым аргументом error()может быть строка формата.

Я бы не был честен, если бы сказал, что полностью понял функции подстановки истории. Это, по сути, некомментированная ручная обработка строк в C. %имеет особое значение в подстановке истории, но я вижу, что она обрабатывается специально только при вызове первого символа (как в !%) или после findev().

Связанный контент