TripleDESCryptoServiceProvider - уязвим для отказа в обслуживании?
У нас есть устаревший сайт ASP.NET, который использует здесь методы шифрования:
http://www.codekeep.net/snippets/af1cd375-059a-4175-93d7-25eea2c5c660.aspx
Когда мы вызываем следующий метод, страница загружается очень медленно и в конечном итоге возвращается сброс соединения:
Decrypt(" ", true);
Если метод вызывается несколько раз в последующих запросах страниц, пул приложений отключается.
Это происходит на сервере Windows 2008 под управлением.NET Framework v3.5.
Я сузил проблему до TransformFinalBlock()
вызов.
ПРИМЕЧАНИЕ: на Кассини я не получаю тайм-аут соединения; вместо этого выдается следующее исключение:
System.Security.Cryptography.CryptographicException: Bad Data
Вызов Decrypt() для других строк не вызывает проблем в любой среде.
Почему это происходит? Это ошибка в TripleDESCryptoServiceProvider?
Очевидно, я мог бы отфильтровать cipherString, чтобы отклонить " " и избежать этой конкретной проблемы. Однако меня беспокоит, что некоторые другие значения cipherString, которые я не подозреваю, вызовут DoS.
ОБНОВЛЕНИЕ 2011.06.28
Ниже приведен минимальный код для воспроизведения проблемы:
// problem occurs when toEncryptArray is an empty array {}
byte[] toEncryptArray = {};
MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
byte[] keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes("dummy_key"));
hashmd5.Clear();
TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
tdes.Key = keyArray;
tdes.Mode = CipherMode.ECB;
tdes.Padding = PaddingMode.PKCS7;
ICryptoTransform cTransform = tdes.CreateDecryptor();
// the following line can crashes the ASP.NET Application Pool (may need to call multiple times).
byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
tdes.Clear();
2 ответа
Проблема, как упомянуто выше, состоит в том, что логика дешифрования неправильно обрабатывает случай, когда входной шифр является массивом нулевой длины.
Для этого был создан тикет:
Обратите внимание, что он работает нормально при работе.NET Framework 4.0.
Последний блок - это место, где находится отступ. В вашем примере один пробел - это первый и последний блок. DES/Triple DES - это 64-битный блочный шифр, текст шифра должен быть кратным 8 байтам (64 бита).
У меня нет среды для тестирования, но вы пробовали играть с опциями заполнения? Заполнение с большим количеством пробелов не подойдет, потому что заполнение не будет соответствовать.
Распространенной схемой заполнения является PKCS5. Для одного байта (который зашифрован символом пробела) ваш обычный текст должен быть в шестнадцатеричном виде:
0x?? 0x07 0x07 0x07 0x07 0x07 0x07 0x07
Но в вашем примере кода ожидается ввод base64. Что означает, что ваша входная строка должна быть:
- Кратное 12 карат
- Допустимая строка base64
Любая другая строка может быть отклонена.
true
значение выглядит как MAC, что означает, что за вашим вводимым простым текстом должен следовать хеш (MD5 в вашем коде). Он поможет вам обнаружить изменения в зашифрованном тексте. Это полезно, когда вы шифруете двоичные данные. Если вы можете легко обнаружить искаженный текст, вы можете установить его в false.