Вимкнути резервну копію SSL та використовувати лише TLS для вихідних з'єднань у .NET? (Пом’якшення пуделя)


106

Я намагаюся пом’якшити нашу вразливість до нападу пуделя SSL 3.0 Fallback . Наші адміністратори вже почали відключати SSL на користь TLS для вхідних підключень до наших серверів. А також ми порадили нашій команді вимкнути SSL у своїх веб-браузерах. Зараз я розглядаю нашу кодову базу .NET, яка ініціює з'єднання HTTPS з різними службами через System.Net.HttpWebRequest . Я вважаю, що ці з'єднання можуть бути вразливими для атаки MITM, якщо вони дозволять відновлювати з TLS до SSL. Ось що я визначив поки що. Може хтось, будь ласка, повторно перевірив це, щоб переконатися, що я правий? Ця вразливість є абсолютно новою, тому я ще не бачив ніяких вказівок від Microsoft щодо її зменшення в .NET:

  1. Дозволені протоколи для класу System.Net.Security.SslStream, який лежить в основі захищеного зв'язку в .NET, встановлюються глобально для кожного AppDomain через властивість System.Net.ServicePointManager.SecurityProtocol .

  2. Значення за замовчуванням цього властивості в .NET 4.5 Ssl3 | Tls(хоча я не можу знайти документацію , щоб підтримати цю діяльність.) SecurityProtocolType є перерахуванням з атрибутом Flags, так що це побітовое АБО з цих двох значень. Ви можете перевірити це у своєму оточенні за допомогою цього рядка коду:

    Console.WriteLine (System.Net.ServicePointManager.SecurityProtocol.ToString ());

  3. Це потрібно змінити на Tlsабо, можливо Tls12, перед тим, як ініціювати будь-які з'єднання у вашому додатку:

    System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls;

  4. Важливо: Оскільки властивість підтримує декілька побітових прапорів, я припускаю, що SslStream не буде автоматично віддаватися до інших не визначених протоколів під час рукостискання. В іншому випадку, який би був сенс підтримувати кілька прапорів?

Оновлення на TLS 1.0 проти 1.1 / 1.2:

За словами експерта служби безпеки Google Адама Ленглі, пізніше було виявлено , що TLS 1.0 є вразливим до POODLE, якщо він не застосовується належним чином , тому слід розглянути можливість виключно переходу на TLS 1.2.

Оновлення для .NET Framework 4.7 і вище:

Як згадував проф. Фон Lemongargle нижче, починаючи з версії 4.7 .NET Framework, не потрібно використовувати цей злом, оскільки налаштування за замовчуванням дозволить ОС вибрати найбільш безпечну версію протоколу TLS. Для отримання додаткової інформації див. Кращі практики безпеки транспортного шару (TLS) із .NET Framework .


1
Щодо пункту 2 вище: див. Referenceource.microsoft.com/#System/net/System/Net/… SslProtocols "Типово = Ssl3 | Tls"
Dai Bok

1
@Dai Bok За замовчуванням зараз опція SystemDefault docs.microsoft.com/en-us/dotnet/api/…
MarwaAhmad

@MarwaAhmad, якщо це так, посилання на вихідний код у моєму посиланні не відображає за замовчуванням (48 | 192). Якщо встановлено значення none (0), він повинен повернутися до системного замовчування. Пахне до мене , і я , ймовірно , перевірити це , перш ніж вносити зміни , оскільки це може привести до missconfiguration ... і вимикаючи протоколів на неправильної структури .net ...
Дай Бок

Відповіді:


137

Ми робимо те саме. Щоб підтримувати лише TLS 1.2 та відсутні протоколи SSL, ви можете зробити це:

System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

SecurityProtocolType.Tls - це лише TLS 1.0, не всі версії TLS.

З іншого боку: Якщо ви хочете перевірити, чи ваш сайт не дозволяє підключення SSL, ви можете зробити це тут (я не думаю, що це вплине на наведені вище параметри, нам довелося редагувати реєстр, щоб змусити IIS використовувати TLS для вхідних з'єднань): https://www.ssllabs.com/ssltest/index.html

Щоб вимкнути SSL 2.0 та 3.0 в IIS, див. Цю сторінку: https://www.sslshopper.com/article-how-to-disable-ssl-2.0-in-iis-7.html


Правильно. Хороша ідея підтримати і новіші версії TLS: захист від майбутнього.
Йордан Рігер

1
І для користі інших, згадане вами редагування реєстру також можна виконати з цими кроками: serverfault.com/a/637263/98656 . У Windows Server 2003 до 2012 R2 протоколи управляються прапорами HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Control \ SecurityProviders \ Schannel \ Protocols. Щоб відключити SSLv3, створіть підрозділ у вказаному вище місці під назвою "SSL 3.0", а під ним - підрозділ з назвою "Сервер", а під ним - значення DWORD під назвою "Увімкнено", встановлене на 0. Також слід вимкнути SSL 2.0 таким же чином.
Йордан Рігер

4
@ScotterMonkey Вам потрібно встановити System.Net.ServicePointManager.SecurityProtocol, якщо ви ініціюєте вихідні з'єднання з коду .NET, наприклад, підключення до веб-сервісу або API з користувацького коду, що працює на вашому сервері. Якщо ви працюєте лише з простим веб-сайтом, і ви приймаєте лише вхідні з'єднання із браузерів, то виправлення реєстру достатньо.
Йордан Рігер

7
Примітка: По- видимому , SecurityProtocolType.Tls11і SecurityProtocolType.Tls12значення перерахування доступно тільки в ASP.net 4.5 і вище. Не впевнений, що нам доведеться робити для старих баз коду, які працюють на 2.0, якщо TLS 1.0 піде в сторону.
Сем

1
@AnishV Ви додали цей рядок коду під час ініціалізації свого додатка перед будь-яким кодом, який ініціює вихідне з’єднання SSL / TLS.
Джордан Рігер

23

Відповідь @ Eddie Loeffen, здається, є найпопулярнішою відповіддю на це запитання, але вона має деякі погані довгострокові наслідки. Якщо ви переглянете сторінку документації для System.Net.ServicePointManager.SecurityProtocol, тут розділ із зауваженнями передбачає, що етап переговорів повинен просто вирішити це питання (а примушування протоколу є поганою практикою, оскільки в майбутньому TLS 1.2 також буде порушена). Однак ми б не шукали такої відповіді, якби це було.

Досліджуючи, виявляється, що для переходу до TLS1.2 на етапі переговорів необхідний протокол переговорів ALPN. Ми взяли це як вихідний пункт і спробували нові версії фреймворку .Net, щоб побачити, звідки починається підтримка. Ми виявили, що .Net 4.5.2 не підтримує переговори з TLS 1.2, але .Net 4.6.

Тож, навіть якщо примусовий TLS1.2 виконає роботу зараз, я рекомендую замість цього оновити до .Net 4.6. Оскільки це проблема PCI DSS за червень 2016 року, вікно коротке, але нова рамка - краща відповідь.

ОНОВЛЕННЯ: Працюючи з коментарів, я створив це:

ServicePointManager.SecurityProtocol = 0;    
foreach (SecurityProtocolType protocol in SecurityProtocolType.GetValues(typeof(SecurityProtocolType)))
    {
        switch (protocol)
        {
            case SecurityProtocolType.Ssl3:
            case SecurityProtocolType.Tls:
            case SecurityProtocolType.Tls11:
                break;
            default:
                ServicePointManager.SecurityProtocol |= protocol;
            break;
        }
    }

Для того щоб підтвердити концепцію, я або об'єднав SSL3 і TLS1.2 і запустив код, орієнтований на сервер, який підтримує лише TLS 1.0 і TLS 1.2 (1.1 відключено). З протоколами or'd, здається, добре поєднується. Якщо я перейду на SSL3 та TLS 1.1, не вдалося підключитися. Моя перевірка використовує HttpWebRequest від System.Net та просто дзвонить GetResponse (). Наприклад, я спробував це і не вдалося:

        HttpWebRequest request = WebRequest.Create("https://www.contoso.com/my/web/resource") as HttpWebRequest;
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls11;
        request.GetResponse();

поки це працювало:

        HttpWebRequest request = WebRequest.Create("https://www.contoso.com/my/web/resource") as HttpWebRequest;
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls12;
        request.GetResponse();

Це має перевагу перед форсуванням TLS 1.2 в тому, що, якщо .Net фрейм буде оновлений так, що в Enum буде більше записів, вони будуть підтримуватися кодом, як є. Він має недолік, ніж просто використовувати .Net 4.6, оскільки 4.6 використовує ALPN і повинен підтримувати нові протоколи, якщо не вказано обмеження.

Редагувати 29.04.2019 - Microsoft опублікувала цю статтю в жовтні минулого року. У них є досить хороший конспект їх рекомендацій щодо того, як це слід робити в різних версіях .net фреймворку.


3
Цікаво. Схоже, що сторінка документації була оновлена ​​разом із переходом MSDN до ".NET Framework (поточна версія) ", і тепер пояснюється, що "для цієї властивості спеціально не вказано значення за замовчуванням". Можливо, більш прийнятною у майбутньому версією прийнятої відповіді буде спочатку запитувати властивість для отримання списку дозволених протоколів, а потім видалити ті, які ваша програма вважає небезпечними (тобто що-небудь менше, ніж TLS 1.2), а не явно додавати лише ті, які ви вважаєте захищеними. Це не виключає нових версій у майбутньому.
Йордан Рігер

Було б добре, щоб програма могла видаляти протоколи зі списку, який генерує система, але я не бачу способу зробити це в поточному API. Єдиним варіантом, здається, є примусити конкретний протокол, який я не бачу, чому хтось хотів би це зробити. На жаль, без підтримки ALPN, здається, це єдиний спосіб підключити TLS1.2 до роботи.
Проф Фон Лемонгорг

1
Повинно бути можливим прокрутити всі переліки SecurityProtocolType, побачити, які з них є у переліку перелічених прапорів ServicePointManager.SecurityProtocol (це логічне АБО всіх встановлених прапорів, тож ви можете протестувати кожного з AND), а потім створити новий список їх із тими, які ви не хочете видалити. Потім об'єднайте їх в один перерахунок і встановіть властивість з цим.
Йордан Рігер

Я просто перечитував ваш enum / looping-код, і я думаю, що це неправильно. Логічний оператор | = призведе до властивості, включаючи ті, які значення за замовчуванням були задані у властивості спочатку, а не включатимуть лише Tls12 та вище. Щоб виправити це, вам потрібно ініціалізувати змінну перерахунку SecurityProtocolType зі значенням 0, виконати цикл | = проти цієї змінної, а потім призначити її властивості ServicePointManager.SecurityProtocol.
Йордан Рігер

7
Хтось ще вважає божевільним, що .NET автоматично не узгоджує найвищу версію протоколу, на яку він здатний ?!
Раман

5

@watson

На віконних формах вона доступна, вгорі класу кладемо

  static void Main(string[] args)
    {
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
       //other stuff here
    }

оскільки вікно є однопоточним, це все, що вам потрібно, у випадку, якщо це послуга, вам потрібно поставити його прямо над викликом до сервісу (оскільки немає жодної інформації про те, на яку нитку ви будете входити).

using System.Security.Principal 

також потрібен.


5

Якщо вам цікаво, які протоколи підтримує .NET, ви можете спробувати HttpClient на https://www.howsmyssl.com/

// set proxy if you need to
// WebRequest.DefaultWebProxy = new WebProxy("http://localhost:3128");

File.WriteAllText("howsmyssl-httpclient.html", new HttpClient().GetStringAsync("https://www.howsmyssl.com").Result);

// alternative using WebClient for older framework versions
// new WebClient().DownloadFile("https://www.howsmyssl.com/", "howsmyssl-webclient.html");

Результат - прокляття:

Ваш клієнт використовує TLS 1.0, який дуже старий, можливо сприйнятливий до атаки BEAST, і не має в ньому найкращих пакетів шифрів. Додатки на зразок AES-GCM та SHA256 замінити MD5-SHA-1 недоступні для клієнта TLS 1.0, а також багатьох інших сучасних пакетів шифрів.

Як пояснює Едді вище, ви можете ввімкнути кращі протоколи вручну:

System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11; 

Я не знаю, чому в ньому використовуються погані протоколи. Це здається поганим вибором налаштувань, рівносильним значним помилкам у безпеці (я думаю, що багато програм не змінюють типових параметрів). Як ми можемо повідомити про це?


5

Мені довелося привести цілочисельний еквівалент, щоб обійти той факт, що я все ще використовую .NET 4.0

System.Net.ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
/* Note the property type  
   [System.Flags]
   public enum SecurityProtocolType
   {
     Ssl3 = 48,
     Tls = 192,
     Tls11 = 768,
     Tls12 = 3072,
   } 
*/

Це працює, але .NET 4.0 не підтримує TLS 1.2, однак .NET 4.5 і вище підтримує TLS 1.2. Таким чином, ви можете додати цей код (або додати побіжно АБО, щоб додати підтримку узгодження TLS 1.2) до програми .NET 4.0 та створити його, але вам потрібно буде розгорнути код на .NET 4.5 або новішої версії. blogs.perficient.com/microsoft/2016/04/tsl-1-2-and-net-support
rboy

Також в цьому переконатися, .NET 4.0 код буде працювати нормально на більш високої версії .NET , включаючи .NET 4.5 і .NET 4.6 stackoverflow.com/questions/33378902 / ...
rboy

Цілочисельний склад працював для надсилання TLS 1.2. Значення перерахунку Tls12 просто не існує. NET 4.0
CZahrobsky

Дві різні точки. Дивіться мій коментар. Ви можете встановити значення, але якщо ваша версія Net Net версії виконання 4,0, це не вдасться. Ви можете компілювати з цим прапором, але версії .NET для виконання повинні бути 4,5 або вище, оскільки базові компоненти в .NET 4.0 не підтримують шифри, необхідні для TLS 1.2 (див. Посилання)
rboy

2
Є кілька виправлень для старих версій .NET для виконання, щоб додати підтримку TLS 1.2. наприклад, support.microsoft.com/en-us/help/3154518/… , CZahrobsky міг би також використовувати це для оновлення для творців падіння Win10, яке також включало виправлення.
тихим тоном

1

Я знайшов найпростіше рішення - додати дві записи реєстру наступним чином (запустіть це в командному рядку з правами адміністратора):

reg add HKLM\SOFTWARE\Microsoft\.NETFramework\v4.0.30319 /v SchUseStrongCrypto /t REG_DWORD /d 1 /reg:32

reg add HKLM\SOFTWARE\Microsoft\.NETFramework\v4.0.30319 /v SchUseStrongCrypto /t REG_DWORD /d 1 /reg:64

Ці записи, схоже, впливають на те, як .NET CLR вибирає протокол під час встановлення безпечного з'єднання як клієнта.

Більше інформації про цей запис у реєстрі тут:

https://docs.microsoft.com/en-us/security-updates/SecurityAdvisories/2015/2960358#sugges-action

Це не тільки простіше, але припускаючи, що він працює у вашому випадку, набагато надійніший за рішення на основі коду, яке вимагає від розробників відстежувати протокол та розробку та оновлювати весь відповідний код. Сподіваємось, подібні зміни середовища можуть бути внесені для TLS 1.3 і вище, доки .NET залишається досить тупим, щоб не автоматично вибирати найвищий доступний протокол.

ПРИМІТКА . Хоча, згідно зі статтею вище, це повинно вимкнути RC4, і не можна було б думати, що це зміниться, чи дозволено клієнту .NET використовувати TLS1.2 + чи ні, чомусь у нього є це ефект.

ПРИМІТКА . Як зазначає @Jordan Rieger у коментарях, це не рішення для POODLE, оскільки він не вимикає старіші протоколи a - він просто дозволяє клієнту працювати з новішими протоколами, наприклад, коли виправлений сервер відключив старіший протоколи. Однак при атаці MITM, очевидно, компрометований сервер запропонує клієнту старіший протокол, який клієнт потім із задоволенням використовуватиме.

TODO : Спробуйте відключити використання клієнтами TLS1.0 та TLS1.1 на базі клієнта з цими записами реєстру, однак я не знаю, чи дотримуються ці параметри бібліотеки клієнтів .NET http:

https://docs.microsoft.com/en-us/windows-server/security/tls/tls-registry-settings#tls-10

https://docs.microsoft.com/en-us/windows-server/security/tls/tls-registry-settings#tls-11


Параметри реєстру як альтернатива коду були б чудовими, але чи фактично ці налаштування вимикають TLS 1.0 та 1.1 на користь лише дозволу клієнтських з'єднань з використанням TLS 1.2 і вище? За посиланням, схоже, відключення RC4 лише в TLS. Я думаю, що атака Пуделя ширша за це.
Йордан Рігер

@JordanRieger Ці записи реєстру дозволяють клієнту .NET підключитися до сервера, на якому старі протоколи вимкнено, щоб пом'якшити POODLE. Без цього клієнт видасть помилку, оскільки клієнт .NET тупо наполягає на використанні більш старого протоколу, навіть коли сервер просить більш новий. Усі ставки знімаються, якщо ваш сервер все ще дозволяє з'єднання за допомогою старих протоколів. Теоретично старіші протоколи повинні бути відключені. Цікаво, чи будуть ті самі записи реєстру, які дозволяють відключити їх на сервері (наприклад, nartac.com/Products/IISCrypto ), працюватимуть і для клієнта?
Раман

У записах реєстру, якими маніпулює nartac, є окремі налаштування для (при виконанні функцій) клієнта та (коли діє як) сервера. Я не пам'ятаю, чи відрізняється їх інтерфейс. Чи знаєте ви, які версії .net підтримують цей злом реєстру?
Проф. Фон Лемонгорг

@Raman, однак, питанням мого питання було зменшення вразливості POODLE, коли ваш клієнт підключається до сервера, який ви не контролюєте. Уразливість дозволить зловмиснику MITM знизити протокол до старої версії TLS або SSL, яку можна зламати. Просто відключення RC4 недостатньо. Ці параметри реєстру можуть бути корисними для певних випадків, але це не сценарій мого питання.
Йордан Рігер

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