вторник, 23 августа 2011 г.

Безопасность: не забывайте обнулять вещи, на которые вам наплевать

Это перевод Security: Don't forget to initialize the stuff you don't care about. Автор: Реймонд Чен.

Затерянным в волнении уязвимостей повышения привилегий является простое раскрытие информации через отсутствующую инициализацию мусора (прим.пер.: понятия не имею, зачем оригинальное предложение так построено).

Сегодня каждый знаком с использованием функции SecureZeroMemory для гарантии того, что буфера, содержащие чувствительную (важную) информацию, очищены после работы с ними (*), но вы также должны очищать буфера перед их записью в другое место. Рассмотрим, к примеру, такой формат данных:
type
  TFileHeader = packed record
    dwMagic: DWORD;
    dwVersion: DWORD;
    wszComment: array[0..256-1] of WideChar;
    cbData: DWORD;
    // далее следует cbData байт данных
  end;
Код, который заполняет такие файлы, мог бы выглядеть так:
function SaveToFile(hFile: THandle; pszComment: PWideChar; cbData: DWORD; pbData: PByte): Boolean;
var
  cbWritten: DWORD;
  fh: TFileHeader;
begin
  fh.dwMagic := FILE_MAGICNUMBER;
  fh.dwVersion := FILE_CURRENTVERSION;
  fh.cbData := cbData;
  Result := SUCCEEDED(StringCchCopyW(fh.wszComment, 256, pszComment)) and
                  WriteFile(hFile, @fh, SizeOf(fh), cbWritten, nil) and
                  (cbWritten = SizeOf(fh)) and
                  WriteFile(hFile, pbData, cbData, cbWritten, nil) and
                  (cbWritten = cbData);
end;
Увидели баг безопасности?

Если комментарий к файлу будет менее 255 символов, то байты после терминирующего нуля будут содержать не инициализированный мусор со стека. Мусор со стека может содержать интересную информацию, которую вы бы не хотели выкладывать в файл. Конечно, он не будет содержать информацию, которую вы уже идентифицировали как чувствительную (вроде паролей) - потому что вы уже подчистили её; но мусор может содержать информацию, хотя и менее критическую, но всё же привлекательную для злоумышленника. К примеру, у вас может утечь имя аккаунта.

Мне рассказали, что одна сетевая программа известной компании содержала аналогичный баг. Они использовали очень продвинутый алгоритм "смены пароля", детали которого сейчас не важны. Дизайном было предусмотрено, что по сети передавались только сложно зашифрованные данные. Таким образом, если кто-то просматривал сетевые пакеты, то он не мог увидеть ничего интересного. Вот только у них был баг в их клиентской программе: когда они отправляли зашифрованный пароль на сервер, они забыли обнулить не используемые байты в пакете "смена пароля". А в этих данных была... ага, верно: не зашифрованная копия пароля.

Примечание переводчика:
(*) SecureZeroMemory практически не известна в Delphi, потому что предназначена для обхода оптимизатора C++ (видимо, по причине того, что ZeroMemory в C++ является макросом, а не функцией; поэтому её "вызов" последним действием на переменную может быть выброшен оптимизатором). Вместо неё в Delphi используется стандартная системная ZeroMemory (которая в Delphi является обычной функцией; фактически - inline-переходником к FillChar) или чисто Delphi-ёвая FillChar.

Комментариев нет:

Отправить комментарий

Можно использовать некоторые HTML-теги, например:

<b>Жирный</b>
<i>Курсив</i>
<a href="http://www.example.com/">Ссылка</a>

Вам необязательно регистрироваться для комментирования - для этого просто выберите из списка "Анонимный" (для анонимного комментария) или "Имя/URL" (для указания вашего имени и ссылки на сайт). Все прочие варианты потребуют от вас входа в вашу учётку (поддерживается OpenID).

Пожалуйста, по возможности используйте "Имя/URL" вместо "Анонимный". URL можно просто не указывать.

Ваше сообщение может быть помечено как спам спам-фильтром - не волнуйтесь, оно появится после проверки администратором.