
Я был связан сСправочник ненавистников 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()
.