Статья по безопасности DotNet

Введение

На этой странице представлены краткие базовые советы по безопасности .NET для разработчиков.

Платформа .NET

.NET Framework — это основная платформа Microsoft для разработки корпоративных приложений. Это поддерживающий API для ASP.NET, классических приложений Windows, служб Windows Communication Foundation, SharePoint, инструментов Visual Studio для Office и других технологий.

.NET Framework представляет собой набор API-интерфейсов, которые упрощают использование расширенной системы типов, управление данными, графикой, сетями, файловыми операциями и многим другим, что по существу охватывает подавляющее большинство требований для разработки корпоративных приложений в экосистеме Microsoft. Это почти повсеместная библиотека со строгим названием и версиями на уровне сборки.

Обновление платформы

Microsoft поддерживает актуальность .NET Framework с помощью службы Windows Update. Разработчикам обычно не требуется запускать отдельные обновления платформы. Доступ к Центру обновления Windows можно получить по адресу Центр обновления Windows или из программы Центра обновления Windows на компьютере под управлением Windows.

Отдельные платформы можно поддерживать в актуальном состоянии с помощью NuGet. Когда Visual Studio запрашивает обновления, встройте их в свой жизненный цикл.

Помните, что сторонние библиотеки необходимо обновлять отдельно, и не все из них используют NuGet. Например, ELMAH требует отдельного обновления.

Объявления о безопасности

Получайте уведомления о безопасности, нажав кнопку «Смотреть» в следующих репозиториях:

Общее руководство по .NET

В этом разделе содержатся общие рекомендации для приложений .NET. Это относится ко всем приложениям .NET, включая ASP.NET, WPF, WinForms и другим.

В рейтинге OWASP Top 10 перечислены наиболее распространенные и опасные угрозы веб-безопасности в современном мире, и он пересматривается каждые несколько лет. и обновляется с учетом последних данных об угрозах. Этот раздел шпаргалки основан на этом списке. Ваш подход к обеспечению безопасности вашего веб-приложения должен заключаться в том, чтобы начать с верхней угрозы A1 ниже и двигаться вниз; это гарантирует, что время, потраченное на обеспечение безопасности, будет потрачено наиболее эффективно и сначала охватить основные угрозы, а затем меньшие угрозы. После рассмотрения Топ-10 обычно рекомендуется для оценки других угроз или прохождения профессионально пройденного теста на проникновение.

A01 Нарушение контроля доступа

Слабое управление аккаунтом

Убедитесь, что файлы cookie отправляются с установленным флагом HttpOnly, чтобы предотвратить доступ сценариев на стороне клиента к файлам cookie:

CookieHttpOnly = true,

Сократите период времени, в течение которого сеанс может быть украден, уменьшив время ожидания сеанса и удалив скользящий срок действия:

Решение об использовании скользящего срока действия зависит от модели угроз вашего приложения. Параметр SlidingExpiration к false обеспечивает абсолютное время жизни сеанса, что ограничивает продолжительность повторного использования украденного сеанса за счет снижения удобства использования долгоживущих интерактивных сеансов. Для некоторых приложений включение скользящего срока действия (true) может быть предпочтительнее для взаимодействия с пользователем, поскольку он сохраняет сеанс активным, пока пользователь активен. Это удобство сопряжено с повышенным риском, если сеанс будет скомпрометирован.

ExpireTimeSpan = TimeSpan.FromMinutes(60),
SlidingExpiration = false

Видеть здесь для примера полного фрагмента кода запуска.

Убедитесь, что файлы cookie отправляются через HTTPS в рабочей среде. Это должно быть реализовано в преобразованиях конфигурации:

<httpCookies requireSSL="true" />
<authentication>
    <forms requireSSL="true" />
</authentication>

Защитите методы входа в систему, регистрации и сброса пароля от атак методом грубой силы с помощью запросов регулирования (см. код ниже). Рассмотрите также возможность использования ReCaptcha.

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
[AllowXRequestsEveryXSecondsAttribute(Name = "LogOn",
Message = "You have performed this action more than {x} times in the last {n} seconds.",
Requests = 3, Seconds = 60)]
public async Task<ActionResult> LogOn(LogOnViewModel model, string returnUrl)

НЕ НУЖНО: внедрять собственную аутентификацию или управление сеансами. Используйте тот, который предоставлен .NET.

НЕ: Сообщайте кому-либо, существует ли учетная запись при входе в систему, регистрации или сбросе пароля. Скажите что-то вроде: «Имя пользователя или пароль были неверными» или «Если эта учетная запись существует, токен сброса будет отправлен на зарегистрированный адрес электронной почты». Это защищает от перечисления учетных записей.

Обратная связь пользователю должна быть идентична независимо от того, существует ли учетная запись, как с точки зрения содержания, так и с точки зрения поведения. Например, если ответ занимает на 50% больше времени, когда учетная запись реальна, то информацию о членстве можно угадать и проверить.

Отсутствует контроль доступа на функциональном уровне

НУЖНО: авторизовать пользователей на всех внешних конечных точках. В .NET Framework есть множество способов авторизации пользователя, используйте их на уровне метода:

[Authorize(Roles = "Admin")]
[HttpGet]
public ActionResult Index(int page = 1)

или еще лучше, на уровне контроллера:

[Authorize]
public class UserController

Вы также можете проверить роли в коде, используя функции идентификации в .net:System.Web.Security.Roles.IsUserInRole(userName, roleName)

Более подробную информацию вы можете найти в Шпаргалка по авторизации и Памятка по автоматизации авторизационного тестирования.

Небезопасные прямые ссылки на объекты

Если у вас есть ресурс (объект), к которому можно получить доступ по ссылке (в примере ниже это id), вам необходимо убедиться, что пользователь должен иметь доступ к этому ресурсу.

// Insecure
public ActionResult Edit(int id)
{
  var user = _context.Users.FirstOrDefault(e => e.Id == id);
  return View("Details", new UserViewModel(user);
}

// Secure
public ActionResult Edit(int id)
{
  var user = _context.Users.FirstOrDefault(e => e.Id == id);
  // Establish user has right to edit the details
  if (user.Id != _userIdentity.GetUserId())
  {
        HandleErrorInfo error = new HandleErrorInfo(
            new Exception("INFO: You do not have permission to edit these details"));
        return View("Error", error);
  }
  return View("Edit", new UserViewModel(user);
}

Более подробную информацию можно найти в Памятка по предотвращению небезопасных прямых ссылок на объекты.

A02 Криптографические сбои

Общее руководство по криптографии

  • Никогда, никогда не пишите свои собственные криптографические функции.
  • По возможности старайтесь вообще не писать какой-либо криптографический код. Вместо этого попробуйте либо использовать уже существующие решения по управлению секретами, либо решение по управлению секретами, предоставленное вашим облачным провайдером. Для получения дополнительной информации см. Памятка по управлению секретами OWASP.
  • Если вы не можете использовать уже существующее решение для управления секретами, попробуйте использовать надежную и хорошо известную библиотеку реализации, а не использовать библиотеки, встроенные в .NET, поскольку с их помощью слишком легко допустить криптографические ошибки.
  • Убедитесь, что ваше приложение или протокол могут легко поддерживать будущие изменения криптографических алгоритмов.

Хеширование

НУЖНО: используйте сильный алгоритм хеширования.

  • В .NET (как Framework, так и Core) самым сильным алгоритмом хеширования для общих требований хеширования является System.Security.Cryptography.SHA512.
  • В .NET Framework 4.6 и более ранних версиях самым надежным алгоритмом хеширования паролей является PBKDF2, реализованный как System.Security.Cryptography.Rfc2898DeriveBytes.
  • В .NET Framework 4.6.1 и более поздних версиях, а также в .NET Core самым надежным алгоритмом хеширования паролей является PBKDF2, реализованный как Microsoft.AspNetCore.Cryptography.KeyDerivation.Pbkdf2 который имеет ряд существенных преимуществ перед Rfc2898DeriveBytes.
  • При использовании функции хеширования для хеширования неуникальных входных данных, таких как пароли, используйте значение соли, добавляемое к исходному значению перед хешированием.
  • Обратитесь к Памятка по хранению паролей для получения дополнительной информации.

Пароли

НУЖНО: применять пароли минимальной сложности, которые выдержат атаку по словарю; то есть более длинные пароли, в которых используется полный набор символов (цифры, символы и буквы) для увеличения энтропии.

Шифрование

НУЖНО: используйте надежный алгоритм шифрования, например AES-512, если личные данные необходимо восстановить в исходном формате.

НУЖНО: Защищайте ключи шифрования больше, чем любой другой актив. Дополнительную информацию о хранении неактивных ключей шифрования см. Шпаргалка по управлению ключами.

НУЖНО: используйте TLS 1.2+ для всего сайта. Получите бесплатный сертификат LetsEncrypt.org и автоматизировать продление.

НЕ: Разрешить SSL, это устарело..

НУЖНО: иметь строгую политику TLS (см. Лучшие практики SSL), используйте TLS 1.2+ везде, где это возможно. Затем проверьте конфигурацию, используя SSL-тест или ТестSSL.

Более подробную информацию о защите транспортного уровня можно найти в Памятка по безопасности транспортного уровня.

НУЖНО: Убедитесь, что заголовки не раскрывают информацию о вашем приложении. Видеть HttpHeaders.cs, Дионах Стрипхедерс, отключить через web.config или Стартап.cs.

например Web.config

<system.web>
    <httpRuntime enableVersionHeader="false"/>
</system.web>
<system.webServer>
    <security>
        <requestFiltering removeServerHeader="true" />
    </security>
    <httpProtocol>
        <customHeaders>
            <add name="X-Content-Type-Options" value="nosniff" />
            <add name="X-Frame-Options" value="DENY" />
            <add name="X-Permitted-Cross-Domain-Policies" value="master-only"/>
            <add name="X-XSS-Protection" value="0"/>
            <remove name="X-Powered-By"/>
        </customHeaders>
    </httpProtocol>
</system.webServer>

например Startup.cs

app.UseHsts(hsts => hsts.MaxAge(365).IncludeSubdomains());
app.UseXContentTypeOptions();
app.UseReferrerPolicy(opts => opts.NoReferrer());
app.UseXXssProtection(options => options.FilterDisabled());
app.UseXfo(options => options.Deny());

app.UseCsp(opts => opts
 .BlockAllMixedContent()
 .StyleSources(s => s.Self())
 .StyleSources(s => s.UnsafeInline())
 .FontSources(s => s.Self())
 .FormActions(s => s.Self())
 .FrameAncestors(s => s.Self())
 .ImageSources(s => s.Self())
 .ScriptSources(s => s.Self())
 );

Более подробную информацию о заголовках можно найти на странице Проект безопасных заголовков OWASP.

Шифрование для хранения

В следующем фрагменте кода показан пример использования AES-GCM для шифрования и дешифрования данных. Настоятельно рекомендуется, чтобы эксперт по криптографии проверил ваш окончательный проект и код, поскольку даже самая тривиальная ошибка может серьезно ослабить ваше шифрование.

Код основан на примере отсюда:https://www.scottbrady91.com/c-sharp/aes-gcm-dotnet

Несколько ограничений/подводных камней с этим кодом:

  • Он не учитывает ротацию ключей или управление, что само по себе является целой темой.
  • Важно использовать разные значения nonce для каждой операции шифрования, даже если используется один и тот же ключ.
  • Ключ необходимо будет надежно хранить.
Нажмите здесь, чтобы просмотреть фрагмент кода «Симметричное шифрование AES-GCM».
// Code based on example from here:
// https://www.scottbrady91.com/c-sharp/aes-gcm-dotnet

public class AesGcmSimpleTest
{
    public static void Main()
    {

        // Key of 32 bytes / 256 bits for AES
        var key = new byte[32];
        RandomNumberGenerator.Fill(key);

        // MaxSize = 12 bytes / 96 bits and this size should always be used.
        var nonce = new byte[AesGcm.NonceByteSizes.MaxSize];
        RandomNumberGenerator.Fill(nonce);

        // Tag for authenticated encryption
        var tag = new byte[AesGcm.TagByteSizes.MaxSize];

        var message = "This message to be encrypted";
        Console.WriteLine(message);

        // Encrypt the message
        var cipherText = AesGcmSimple.Encrypt(message, nonce, out tag, key);
        Console.WriteLine(Convert.ToBase64String(cipherText));

        // Decrypt the message
        var message2 = AesGcmSimple.Decrypt(cipherText, nonce, tag, key);
        Console.WriteLine(message2);


    }
}


public static class AesGcmSimple
{

    public static byte[] Encrypt(string plaintext, byte[] nonce, out byte[] tag, byte[] key)
    {
        using(var aes = new AesGcm(key))
        {
            // Tag for authenticated encryption
            tag = new byte[AesGcm.TagByteSizes.MaxSize];

            // Create a byte array from the message to encrypt
            var plaintextBytes = Encoding.UTF8.GetBytes(plaintext);

            // Ciphertext will be same length in bytes as plaintext
            var ciphertext = new byte[plaintextBytes.Length];

            // perform the actual encryption
            aes.Encrypt(nonce, plaintextBytes, ciphertext, tag);
            return ciphertext;
        }
    }

    public static string Decrypt(byte[] ciphertext, byte[] nonce, byte[] tag, byte[] key)
    {
        using(var aes = new AesGcm(key))
        {
            // Plaintext will be same length in bytes as Ciphertext
            var plaintextBytes = new byte[ciphertext.Length];

            // perform the actual decryption
            aes.Decrypt(nonce, ciphertext, tag, plaintextBytes);

            return Encoding.UTF8.GetString(plaintextBytes);
        }
    }
}

Шифрование для передачи

В следующем фрагменте кода показан пример использования эллиптической кривой/Диффи-Хельмана (ECDH) вместе с AES-GCM для шифрования/дешифрования данных между двумя разными сторонами без необходимости передачи симметричного ключа между двумя сторонами. Вместо этого стороны обмениваются открытыми ключами и затем могут использовать ECDH для создания общего секрета, который можно использовать для симметричного шифрования.

Опять же, настоятельно рекомендуется, чтобы эксперт по криптографии проверил ваш окончательный проект и код, поскольку даже самая тривиальная ошибка может серьезно ослабить ваше шифрование.

Обратите внимание, что этот пример кода основан на AesGcmSimple класс из предыдущий раздел.

Несколько ограничений/подводных камней с этим кодом:

  • Он не учитывает ротацию ключей или управление, что само по себе является целой темой.
  • Код намеренно применяет новый одноразовый номер для каждой операции шифрования, но его необходимо рассматривать как отдельный элемент данных рядом с зашифрованным текстом.
  • Приватные ключи необходимо будет надежно хранить.
  • Код не учитывает проверку открытых ключей перед использованием.
  • В целом, между двумя сторонами нет никакой проверки подлинности.
Нажмите здесь, чтобы просмотреть фрагмент кода «Асимметричное шифрование ECDH».
public class ECDHSimpleTest
{
    public static void Main()
    {
        // Generate ECC key pair for Alice
        var alice = new ECDHSimple();
        byte[] alicePublicKey = alice.PublicKey;

        // Generate ECC key pair for Bob
        var bob = new ECDHSimple();
        byte[] bobPublicKey = bob.PublicKey;

        string plaintext = "Hello, Bob! How are you?";
        Console.WriteLine("Secret being sent from Alice to Bob: " + plaintext);

        // Note that a new nonce is generated with every encryption operation in line with
        // in line with the AES GCM security
        byte[] tag;
        byte[] nonce;
        var cipherText = alice.Encrypt(bobPublicKey, plaintext, out nonce, out tag);
        Console.WriteLine("Ciphertext, nonce, and tag being sent from Alice to Bob: " + Convert.ToBase64String(cipherText) + " " + Convert.ToBase64String(nonce) + " " + Convert.ToBase64String(tag));

        var decrypted = bob.Decrypt(alicePublicKey, cipherText, nonce, tag);
        Console.WriteLine("Secret received by Bob from Alice: " + decrypted);

        Console.WriteLine();

        string plaintext2 = "Hello, Alice! I'm good, how are you?";
        Console.WriteLine("Secret being sent from Bob to Alice: " + plaintext2);

        byte[] tag2;
        byte[] nonce2;
        var cipherText2 = bob.Encrypt(alicePublicKey, plaintext2, out nonce2, out tag2);
        Console.WriteLine("Ciphertext, nonce, and tag being sent from Bob to Alice: " + Convert.ToBase64String(cipherText2) + " " + Convert.ToBase64String(nonce2) + " " + Convert.ToBase64String(tag2));

        var decrypted2 = alice.Decrypt(bobPublicKey, cipherText2, nonce2, tag2);
        Console.WriteLine("Secret received by Alice from Bob: " + decrypted2);
    }
}


public class ECDHSimple
{

    private ECDiffieHellmanCng ecdh = new ECDiffieHellmanCng();

    public byte[] PublicKey
    {
        get
        {
            return ecdh.PublicKey.ToByteArray();
        }
    }

    public byte[] Encrypt(byte[] partnerPublicKey, string message, out byte[] nonce, out byte[] tag)
    {
        // Generate the AES Key and Nonce
        var aesKey = GenerateAESKey(partnerPublicKey);

        // Tag for authenticated encryption
        tag = new byte[AesGcm.TagByteSizes.MaxSize];

        // MaxSize = 12 bytes / 96 bits and this size should always be used.
        // A new nonce is generated with every encryption operation in line with
        // the AES GCM security model
        nonce = new byte[AesGcm.NonceByteSizes.MaxSize];
        RandomNumberGenerator.Fill(nonce);

        // return the encrypted value
        return AesGcmSimple.Encrypt(message, nonce, out tag, aesKey);
    }


    public string Decrypt(byte[] partnerPublicKey, byte[] ciphertext, byte[] nonce, byte[] tag)
    {
        // Generate the AES Key and Nonce
        var aesKey = GenerateAESKey(partnerPublicKey);

        // return the decrypted value
        return AesGcmSimple.Decrypt(ciphertext, nonce, tag, aesKey);
    }

    private byte[] GenerateAESKey(byte[] partnerPublicKey)
    {
        // Derive the secret based on this side's private key and the other side's public key
        byte[] secret = ecdh.DeriveKeyMaterial(CngKey.Import(partnerPublicKey, CngKeyBlobFormat.EccPublicBlob));

        byte[] aesKey = new byte[32]; // 256-bit AES key
        Array.Copy(secret, 0, aesKey, 0, 32); // Copy first 32 bytes as the key

        return aesKey;
    }
}

A03 Инъекция

SQL-инъекция

НУЖНО: Использование реляционного преобразователя объектов (ORM) или хранимых процедур — наиболее эффективный способ противодействия уязвимости SQL-инъекции.

НУЖНО: используйте параметризованные запросы там, где необходимо использовать прямой запрос SQL. Более подробную информацию можно найти в Памятка по параметризации запроса.

Например, используя Entity Framework:

var sql = @"Update [User] SET FirstName = @FirstName WHERE Id = @Id";
context.Database.ExecuteSqlCommand(
    sql,
    new SqlParameter("@FirstName", firstname),
    new SqlParameter("@Id", id));

НЕ НУЖНО: объединять строки в любом месте вашего кода и выполнять их в базе данных (так называемое динамический SQL).

Примечание. Вы все равно можете случайно сделать это с помощью ORM или хранимых процедур, поэтому проверяйте везде. Например:

string sql = "SELECT * FROM Users WHERE UserName='" + txtUser.Text + "' AND Password='"
                + txtPassword.Text + "'";
context.Database.ExecuteSqlCommand(sql); // SQL Injection vulnerability!

НУЖНО: практиковать минимальные привилегии — подключайтесь к базе данных, используя учетную запись с минимальным набором необходимых разрешений. выполнять свою работу, а не учетную запись администратора базы данных.

Внедрение ОС

Общие рекомендации по внедрению ОС можно найти в Памятка по защите от внедрения команд ОС.

ДЕЛАТЬ: использовать System.Diagnostics.Process.Start для вызова базовых функций ОС.

например

var process = new System.Diagnostics.Process();
var startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.FileName = "validatedCommand";
startInfo.Arguments = "validatedArg1 validatedArg2 validatedArg3";
process.StartInfo = startInfo;
process.Start();

НЕЛЬЗЯ: Предполагайте, что этот механизм защитит от вредоносного ввода, предназначенного для взлома одного аргумента и последующего вмешательства в другой аргумент процесса. Это все равно будет возможно.

НУЖНО: По возможности используйте проверку белого списка для всех вводимых пользователем данных. Проверка ввода предотвращает попадание неправильно сформированных данных в информационную систему. Для получения дополнительной информации см. Шпаргалка по проверке ввода.

например Проверка ввода пользователя с помощью Метод IPAddress.TryParse

//User input
string ipAddress = "127.0.0.1";

//check to make sure an ip address was provided
if (!string.IsNullOrEmpty(ipAddress))
{
 // Create an instance of IPAddress for the specified address string (in
 // dotted-quad, or colon-hexadecimal notation).
 if (IPAddress.TryParse(ipAddress, out var address))
 {
  // Display the address in standard notation.
  return address.ToString();
 }
 else
 {
  //ipAddress is not of type IPAddress
  ...
 }
    ...
}

НУЖНО: Старайтесь принимать только простые буквенно-цифровые символы.

НЕТ: Предположим, что вы можете очистить специальные символы, не удаляя их. Различные комбинации \, ' и @ может оказать неожиданное влияние на попытки санитарной обработки.

НЕ: Полагайтесь на методы без гарантии безопасности.

например Поддержка .NET Core 2.2 и более поздних версий, а также .NET 5 и более поздних версий.ProcessStartInfo.ArgumentList который выполняет экранирование некоторых символов, но объект включает в себя отказ от ответственности о том, что небезопасно использовать ненадежный ввод.

НУЖНО: Посмотрите на альтернативы передаче необработанных ненадежных аргументов через параметры командной строки, такие как кодирование с использованием Base64 (которое также безопасно кодирует любые специальные символы), а затем декодируйте параметры в принимающем приложении.

LDAP-инъекция

В отличительных именах можно использовать практически любые символы. Однако некоторые из них необходимо экранировать обратной косой чертой.\ escape-символ. Таблицу, показывающую, какие символы следует экранировать в Active Directory, можно найти в разделе Памятка по предотвращению LDAP-инъекций.

Примечание. Символ пробела необходимо экранировать только в том случае, если он является начальным или конечным символом в имени компонента, например в общем имени. Встроенные пространства не следует экранировать.

Более подробную информацию можно найти в Памятка по предотвращению LDAP-инъекций.

A04 Небезопасный дизайн

Небезопасный дизайн относится к сбоям в безопасности в дизайне приложения или системы. Это отличается от других предметов в списке OWASP Top 10, которые относятся к неудачам реализации. Таким образом, тема безопасного проектирования не связана с конкретным технологии или языка и поэтому выходит за рамки данной шпаргалки. См. Шпаргалка по безопасному проектированию продукта для получения дополнительной информации.

A05 Неправильная конфигурация безопасности

Отладка и трассировка стека

Убедитесь, что отладка и трассировка отключены в рабочей среде. Это можно обеспечить с помощью преобразований web.config:

<compilation xdt:Transform="RemoveAttributes(debug)" />
<trace enabled="false" xdt:Transform="Replace"/>

НЕЛЬЗЯ: использовать пароли по умолчанию.

НУЖНО: Перенаправить запрос, сделанный через HTTP, на HTTPS:

Например, Global.asax.cs:

protected void Application_BeginRequest()
{
    #if !DEBUG
    // SECURE: Ensure any request is returned over SSL/TLS in production
    if (!Request.IsLocal && !Context.Request.IsSecureConnection) {
        var redirect = Context.Request.Url.ToString()
                        .ToLower(CultureInfo.CurrentCulture)
                        .Replace("http:", "https:");
        Response.Redirect(redirect);
    }
    #endif
}

Например, Startup.cs в Configure():

app.UseHttpsRedirection();

Подделка межсайтового запроса

НЕ: Отправляйте конфиденциальные данные без проверки токенов Anti-Forgery (.СЕТЬ / .NET ядро).

СДЕЛАЙТЕ: Отправляйте токен защиты от подделки с каждым запросом POST/PUT:

Использование .NET Framework
using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm",
                        @class = "pull-right" }))
{
    @Html.AntiForgeryToken()
    <ul class="nav nav-pills">
        <li role="presentation">
        Logged on as @User.Identity.Name
        </li>
        <li role="presentation">
        <a href="javascript:document.getElementById('logoutForm').submit()">Log off</a>
        </li>
    </ul>
}

Затем проверьте его на уровне метода или, желательно, на уровне контроллера:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult LogOff()

Убедитесь, что токены полностью удалены для аннулирования при выходе из системы.

/// <summary>
/// SECURE: Remove any remaining cookies including Anti-CSRF cookie
/// </summary>
public void RemoveAntiForgeryCookie(Controller controller)
{
    string[] allCookies = controller.Request.Cookies.AllKeys;
    foreach (string cookie in allCookies)
    {
        if (controller.Response.Cookies[cookie] != null &&
            cookie == "__RequestVerificationToken")
        {
            controller.Response.Cookies[cookie].Expires = DateTime.Now.AddDays(-1);
        }
    }
}
Использование .NET Core 2.0 или более поздней версии

Начиная с .NET Core 2.0 можно автоматически генерировать и проверять токен защиты от подделки.

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

@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

IHtmlHelper.BeginForm также автоматически отправляет токены защиты от подделки.

Если вы не используете вспомогательные теги или IHtmlHelper.BeginForm, вы должны использовать необходимый помощник в формах, как показано здесь:

<form action="RelevantAction" >
@Html.AntiForgeryToken()
</form>

Чтобы автоматически проверять все запросы, кроме GET, HEAD, OPTIONS и TRACE, вам необходимо добавить глобальный фильтр действий с помощью AutoValidateAntiforgeryToken атрибут внутри вашего Startup.cs как указано ниже статья:

services.AddMvc(options =>
{
    options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
});

Если вам нужно отключить проверку атрибутов для определенного метода на контроллере, вы можете добавить ИгнорироватьAntiforgeryToken атрибут метода контроллера (для контроллеров MVC) или родительского класса (для страниц Razor):

[IgnoreAntiforgeryToken]
[HttpDelete]
public IActionResult Delete()
[IgnoreAntiforgeryToken]
public class UnsafeModel : PageModel

Если вам также необходимо проверить токен в запросах GET, HEAD, OPTIONS и TRACE, вы можете добавить ВалидироватьАнтифоргериТокен атрибут метода контроллера (для контроллеров MVC) или родительского класса (для страниц Razor):

[HttpGet]
[ValidateAntiforgeryToken]
public IActionResult DoSomethingDangerous()
[HttpGet]
[ValidateAntiforgeryToken]
public class SafeModel : PageModel

Если вы не можете использовать фильтр глобальных действий, добавьте AutoValidateAntiforgeryToken атрибут вашим классам контроллера или моделям страниц бритвы:

[AutoValidateAntiforgeryToken]
public class UserController
[AutoValidateAntiforgeryToken]
public class SafeModel : PageModel
Использование .Net Core или .NET Framework с AJAX

Вам нужно будет прикрепить токен защиты от подделки к запросам AJAX.

Если вы используете jQuery в представлении ASP.NET Core MVC, этого можно добиться с помощью этого фрагмента:

@inject  Microsoft.AspNetCore.Antiforgery.IAntiforgery antiforgeryProvider
$.ajax(
{
    type: "POST",
    url: '@Url.Action("Action", "Controller")',
    contentType: "application/x-www-form-urlencoded; charset=utf-8",
    data: {
        id: id,
        '__RequestVerificationToken': '@antiforgeryProvider.GetAndStoreTokens(this.Context).RequestToken'
    }
})

Если вы используете .NET Framework, вы можете найти некоторые фрагменты кода. здесь.

Более подробную информацию можно найти в Памятка по предотвращению подделки межсайтовых запросов.

A06 Уязвимые и устаревшие компоненты

НУЖНО: обновлять .NET Framework последними исправлениями.

НУЖНО: Держите свой NuGet пакеты актуальные

НУЖНО: запустить Средство проверки зависимостей OWASP против вашего приложения в рамках процесса сборки и устраняйте любые уязвимости высокого или критического уровня.

НУЖНО: Включите инструменты SCA (анализ состава программного обеспечения) в свой конвейер CI/CD, чтобы гарантировать, что любые новые уязвимости в ваших зависимостях обнаруживаются и принимаются меры.

A07 Сбои идентификации и аутентификации

ДЕЛАТЬ: использовать Базовая идентификация ASP.NET. Платформа ASP.NET Core Identity по умолчанию хорошо настроена и использует безопасные хэши паролей и индивидуальную соль. Identity использует функцию хеширования PBKDF2 для паролей и генерирует случайную соль для каждого пользователя.

НУЖНО: установить политику безопасных паролей

например, основная идентификация ASP.NET

//Startup.cs
services.Configure<IdentityOptions>(options =>
{
 // Password settings
 options.Password.RequireDigit = true;
 options.Password.RequiredLength = 8;
 options.Password.RequireNonAlphanumeric = true;
 options.Password.RequireUppercase = true;
 options.Password.RequireLowercase = true;
 options.Password.RequiredUniqueChars = 6;

 options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30);
 options.Lockout.MaxFailedAccessAttempts = 3;

 options.SignIn.RequireConfirmedEmail = true;

 options.User.RequireUniqueEmail = true;
});

НУЖНО: установить политику использования файлов cookie

например

//Startup.cs
services.ConfigureApplicationCookie(options =>
{
 options.Cookie.HttpOnly = true;
 options.ExpireTimeSpan = TimeSpan.FromMinutes(60);
 // See the discussion in A01 for trade-offs on using sliding expiration.
 options.SlidingExpiration = false;
});

A08 Сбои в целостности программного обеспечения и данных

НУЖНО: снабжать сборки и исполняемые файлы цифровой подписью.

НУЖНО: использовать подпись пакета Nuget.

НУЖНО: просмотреть изменения кода и конфигурации, чтобы избежать вредоносного кода. или зависимости вводятся

НЕЛЬЗЯ: отправлять по сети неподписанные или незашифрованные сериализованные объекты.

НУЖНО: выполнить проверку целостности или проверить цифровые подписи на сериализованных объекты, полученные из сети

НЕЛЬЗЯ: используйте тип BinaryFormatter, который опасен и не рекомендуется для обработки данных. .NET предлагает несколько встроенных сериализаторов, которые могут безопасно обрабатывать ненадежные данные:

  • XmlSerializer и DataContractSerializer для сериализации графов объектов в XML и из него. Не путайте DataContractSerializer с NetDataContractSerializer.
  • BinaryReader и BinaryWriter для XML и JSON.
  • API System.Text.Json для сериализации графов объектов в JSON.

A09 Сбои ведения журнала безопасности и мониторинга

НУЖНО: Убедитесь, что все ошибки входа в систему, контроля доступа и проверки входных данных на стороне сервера регистрируются с достаточным пользовательским контекстом для выявления подозрительных или вредоносных учетных записей.

НУЖНО: Обеспечьте эффективный мониторинг и оповещение, чтобы подозрительные действия обнаруживались и своевременно реагировали.

НЕ: Регистрируйте общие сообщения об ошибках, такие как:csharp Log.Error("Error was thrown");. Вместо этого запишите трассировку стека, сообщение об ошибке и идентификатор пользователя, вызвавшего ошибку.

НЕ: Записывайте конфиденциальные данные, такие как пароли пользователей.

Ведение журнала

Какие журналы собирать, а также дополнительную информацию о журналировании можно найти в разделе Шпаргалка по ведению журналов.

.NET Core поставляется с LoggerFactory, который находится в Microsoft.Extensions.Logging. Более подробную информацию о ILogger можно найти здесь.

Вот как регистрировать все ошибки из Startup.cs, поэтому каждый раз, когда возникает ошибка, она регистрируется:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        _isDevelopment = true;
        app.UseDeveloperExceptionPage();
    }

    //Log all errors in the application
    app.UseExceptionHandler(errorApp =>
    {
        errorApp.Run(async context =>
        {
            var errorFeature = context.Features.Get<IExceptionHandlerFeature>();
            var exception = errorFeature.Error;

            Log.Error(String.Format("Stacktrace of error: {0}",exception.StackTrace.ToString()));
        });
    });

    app.UseAuthentication();
    app.UseMvc();
 }
}

Например. внедрение в конструктор класса, что упрощает написание модульного теста. Это рекомендуется, если экземпляры класса будут создаваться с использованием внедрения зависимостей (например, контроллеры MVC). В приведенном ниже примере показана регистрация всех неудачных попыток входа в систему.

public class AccountsController : Controller
{
        private ILogger _Logger;

        public AccountsController(ILogger logger)
        {
            _Logger = logger;
        }

        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Login(LoginViewModel model)
        {
            if (ModelState.IsValid)
            {
                var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false);
                if (result.Succeeded)
                {
                    //Log all successful log in attempts
                    Log.Information(String.Format("User: {0}, Successfully Logged in", model.Email));
                    //Code for successful login
                    //...
                }
                else
                {
                    //Log all incorrect log in attempts
                    Log.Information(String.Format("User: {0}, Incorrect Password", model.Email));
                }
             }
            ...
        }

Мониторинг

Мониторинг позволяет нам проверять производительность и работоспособность работающей системы с помощью ключевых показателей производительности.

В .NET отличным вариантом добавления возможностей мониторинга является Аналитика приложений.

Более подробную информацию о ведении журнала и мониторинге можно найти здесь.

A10 Подделка запросов на стороне сервера (SSRF)

НУЖНО: проверять и очищать все вводимые пользователем данные, прежде чем использовать их для отправки запроса.

НУЖНО: использовать список разрешенных протоколов и доменов.

ДЕЛАТЬ: использовать IPAddress.TryParse() и Uri.CheckHostName() чтобы убедиться, что IP-адреса и доменные имена действительны

НЕ НУЖНО: следовать HTTP-перенаправлениям.

НЕЛЬЗЯ: пересылать пользователю необработанные HTTP-ответы.

Для получения дополнительной информации см. Памятка по предотвращению подделки запросов на стороне сервера.

ОВАСП 2013 и 2017 гг.

Ниже приведены уязвимости, вошедшие в список 10 лучших по версии OWASP 2013 или 2017 гг. которые не вошли в список 2021 года. Эти уязвимости все еще актуальны но не были включены в список 2021 года, поскольку стали менее распространенными.

A04:2017 Внешние объекты XML (XXE)

Атаки XXE происходят, когда синтаксический анализ XML неправильно обрабатывает вводимые пользователем данные, содержащие объявления внешних сущностей в типе документа полезных данных XML.

Эта статья обсуждаются наиболее распространенные параметры обработки XML для .NET.

Пожалуйста, обратитесь к XXE шпаргалка для получения более подробной информации о предотвращении XXE и других XML-атак типа «отказ в обслуживании».

A07:2017 Межсайтовый скриптинг (XSS)

НЕТ: доверяйте любым данным, которые вам отправляет пользователь. Предпочитайте списки разрешенных (всегда безопасные) спискам запрещенных.

Вы получаете кодирование всего HTML-контента с помощью MVC3. Чтобы правильно закодировать весь контент, будь то HTML, JavaScript, CSS, LDAP и т. д. используют библиотеку Microsoft AntiXSS:

Install-Package AntiXSS

Затем установите в конфиге:

<system.web>
<httpRuntime targetFramework="4.5"
enableVersionHeader="false"
encoderType="Microsoft.Security.Application.AntiXssEncoder, AntiXssLibrary"
maxRequestLength="4096" />

НЕЛЬЗЯ: используйте [AllowHTML] атрибут или вспомогательный класс @Html.Raw если только ты не совсем убедитесь, что содержимое, которое вы записываете в браузер, безопасно и правильно экранировано.

НУЖНО: включить Политика безопасности контента. Это предотвратит доступ ваших страниц к ресурсам, к которым у них не должно быть доступа (например, вредоносным скриптам):

<system.webServer>
    <httpProtocol>
        <customHeaders>
            <add name="Content-Security-Policy"
                value="default-src 'none'; style-src 'self'; img-src 'self';
                font-src 'self'; script-src 'self'" />

Более подробную информацию можно найти в Памятка по предотвращению межсайтового скриптинга.

A08:2017 Небезопасная десериализация

НЕ: Принимайте сериализованные объекты из ненадежных источников.

НУЖНО: проверить ввод пользователя

Злоумышленники могут использовать такие объекты, как файлы cookie, для вставки вредоносной информации и изменения ролей пользователей. В некоторых случаях хакеры могут повысить свои привилегии до прав администратора, используя уже существующий или кэшированный хэш пароля от предыдущего сеанса.

НУЖНО: предотвратить десериализацию объектов домена

НУЖНО: запустить код десериализации с ограниченными правами доступа. Если десериализованный враждебный объект попытается инициировать системный процесс или получить доступ к ресурсу на сервере или в ОС хоста, ему будет отказано в доступе и будет поднят флаг разрешения, чтобы системный администратор был уведомлен о любой аномальной активности на сервере.

Более подробную информацию о небезопасной десериализации можно найти в Памятка по десериализации.

A10:2013 Непроверенные перенаправления и пересылки

Защита от этого была введена в шаблоне MVC 3. Вот код:

public async Task<ActionResult> LogOn(LogOnViewModel model, string returnUrl)
{
    if (ModelState.IsValid)
    {
        var logonResult = await _userManager.TryLogOnAsync(model.UserName, model.Password);
        if (logonResult.Success)
        {
            await _userManager.LogOnAsync(logonResult.UserName, model.RememberMe);  
            return RedirectToLocal(returnUrl);
...
private ActionResult RedirectToLocal(string returnUrl)
{
    if (Url.IsLocalUrl(returnUrl))
    {
        return Redirect(returnUrl);
    }
    else
    {
        return RedirectToAction("Landing", "Account");
    }
}

Другие советы

  • Защита от кликджекинга и атаки «человек посередине» путем перехвата исходного запроса, отличного от TLS: установите X-Frame-Options и Strict-Transport-Security (HSTS) заголовки. Полная информация здесь
  • Защитите от атаки «посредник» пользователя, который никогда раньше не был на вашем сайте. Зарегистрируйтесь для Предварительная загрузка HSTS
  • Поддерживайте тестирование и анализ безопасности служб веб-API. Они скрыты внутри сайтов MVC и являются общедоступными частями сайта, которые будет обнаружен злоумышленником. Все рекомендации MVC и большая часть рекомендаций WCF также применимы и к веб-API.
  • Также см. Шпаргалка по непроверенным перенаправлениям и переадресациям.

Пример проекта

Дополнительные сведения обо всем вышеперечисленном и примеры кода, включенные в пример приложения MVC5 с расширенным базовым уровнем безопасности. пойти в Базовый проект Security Essentials.

Руководство по конкретным темам

В этом разделе содержатся рекомендации по конкретным темам, связанным с .NET.

Конфигурация и развертывание

  • Заблокируйте файлы конфигурации.
    • Удалите все аспекты конфигурации, которые не используются.
    • Зашифруйте конфиденциальные части web.config с использованием aspnet_regiis -pe ( справка по командной строке).
  • Для приложений ClickOnce необходимо обновить .NET Framework до последней версии, чтобы обеспечить поддержку TLS 1.2 или более поздней версии.

Доступ к данным

  • Использовать Параметризованный SQL команды для доступа ко всем данным без исключения.
  • Не используйте Sqlкоманда со строковым параметром, состоящим из объединенная строка SQL.
  • Список допустимых значений, поступающих от пользователя. Используйте перечисления,TryParse или значения поиска, чтобы убедиться, что данные, поступающие от пользователя, соответствуют ожиданиям.
    • Перечисления по-прежнему уязвимы к неожиданным значениям, поскольку .NET проверяет только успешное приведение к базовому типу данных, целочисленному по умолчанию.Enum.IsDefined может проверить, допустимо ли входное значение в списке определенных констант.
  • Применяйте принцип наименьших привилегий при настройке пользователя базы данных в выбранной вами базе данных. Пользователь базы данных должен иметь доступ только к тем элементам, которые имеют смысл для данного варианта использования.
  • Использование Entity Framework является очень эффективным SQL-инъекция механизм предотвращения. Помните, что создание собственных специальных запросов в Entity Framework так же восприимчиво к SQLi, как и простой запрос SQL..
  • При использовании SQL Server предпочитайте встроенная аутентификация над SQL-аутентификация.
  • Использовать Всегда зашифровано где это возможно, для конфиденциальных данных (SQL Server 2016+ и Azure SQL)

Руководство по веб-формам ASP NET

ASP.NET Web Forms — это исходный API разработки приложений на основе браузера для .NET Framework, который до сих пор остается наиболее распространенной корпоративной платформой для разработки веб-приложений.

  • Всегда используйте HTTPS.
  • Давать возможность требуетсяSSL на файлах cookie и элементах форм и HttpOnly о файлах cookie в файле web.config.
  • Осуществлять пользовательские ошибки.
  • Убеждаться отслеживание выключен.
  • Хотя ViewState не всегда подходит для веб-разработки, его использование может обеспечить смягчение последствий CSRF. Чтобы обеспечить защиту ViewState от атак CSRF, вам необходимо установить параметр ViewStateUserKey:
protected override OnInit(EventArgs e) {
    base.OnInit(e);
    ViewStateUserKey = Session.SessionID;
}

Если вы не используете Viewstate, перейдите на главную страницу по умолчанию шаблона веб-форм ASP.NET по умолчанию для ручного токена защиты от CSRF с использованием файла cookie двойной отправки.

private const string AntiXsrfTokenKey = "__AntiXsrfToken";
private const string AntiXsrfUserNameKey = "__AntiXsrfUserName";
private string _antiXsrfTokenValue;
protected void Page_Init(object sender, EventArgs e)
{
    // The code below helps to protect against XSRF attacks
    var requestCookie = Request.Cookies[AntiXsrfTokenKey];
    Guid requestCookieGuidValue;
    if (requestCookie != null && Guid.TryParse(requestCookie.Value, out requestCookieGuidValue))
    {
       // Use the Anti-XSRF token from the cookie
       _antiXsrfTokenValue = requestCookie.Value;
       Page.ViewStateUserKey = _antiXsrfTokenValue;
    }
    else
    {
       // Generate a new Anti-XSRF token and save to the cookie
       _antiXsrfTokenValue = Guid.NewGuid().ToString("N");
       Page.ViewStateUserKey = _antiXsrfTokenValue;
       var responseCookie = new HttpCookie(AntiXsrfTokenKey)
       {
          HttpOnly = true,
          Value = _antiXsrfTokenValue
       };
       if (FormsAuthentication.RequireSSL && Request.IsSecureConnection)
       {
          responseCookie.Secure = true;
       }
       Response.Cookies.Set(responseCookie);
    }
    Page.PreLoad += master_Page_PreLoad;
}
protected void master_Page_PreLoad(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
       // Set Anti-XSRF token
       ViewState[AntiXsrfTokenKey] = Page.ViewStateUserKey;
       ViewState[AntiXsrfUserNameKey] = Context.User.Identity.Name ?? String.Empty;
    }
    else
    {
       // Validate the Anti-XSRF token
       if ((string)ViewState[AntiXsrfTokenKey] != _antiXsrfTokenValue ||
          (string)ViewState[AntiXsrfUserNameKey] != (Context.User.Identity.Name ?? String.Empty))
       {
          throw new InvalidOperationException("Validation of Anti-XSRF token failed.");
       }
    }
}
  • Учитывать HSTS в IIS. Видеть здесь для процедуры.
  • Это рекомендуемый web.config установка, которая, помимо прочего, обрабатывает HSTS.
<?xml version="1.0" encoding="UTF-8"?>
 <configuration>
   <system.web>
     <httpRuntime enableVersionHeader="false"/>
   </system.web>
   <system.webServer>
     <security>
       <requestFiltering removeServerHeader="true" />
     </security>
     <staticContent>
       <clientCache cacheControlCustom="public"
            cacheControlMode="UseMaxAge"
            cacheControlMaxAge="1.00:00:00"
            setEtag="true" />
     </staticContent>
     <httpProtocol>
       <customHeaders>
         <add name="Content-Security-Policy"
            value="default-src 'none'; style-src 'self'; img-src 'self'; font-src 'self'" />
         <add name="X-Content-Type-Options" value="NOSNIFF" />
         <add name="X-Frame-Options" value="DENY" />
         <add name="X-Permitted-Cross-Domain-Policies" value="master-only"/>
         <add name="X-XSS-Protection" value="0"/>
         <remove name="X-Powered-By"/>
       </customHeaders>
     </httpProtocol>
     <rewrite>
       <rules>
         <rule name="Redirect to https">
           <match url="(.*)"/>
           <conditions>
             <add input="{HTTPS}" pattern="Off"/>
             <add input="{REQUEST_METHOD}" pattern="^get$|^head$" />
           </conditions>
           <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent"/>
         </rule>
       </rules>
       <outboundRules>
         <rule name="Add HSTS Header" enabled="true">
           <match serverVariable="RESPONSE_Strict_Transport_Security" pattern=".*" />
           <conditions>
             <add input="{HTTPS}" pattern="on" ignoreCase="true" />
           </conditions>
           <action type="Rewrite" value="max-age=15768000" />
         </rule>
       </outboundRules>
     </rewrite>
   </system.webServer>
 </configuration>
  • Удалите заголовок версии, добавив следующую строку в Machine.config файл:
<httpRuntime enableVersionHeader="false" />
  • Также удалите заголовок сервера, используя класс HttpContext в своем коде.
HttpContext.Current.Response.Headers.Remove("Server");

HTTP-проверка и кодирование

  • Не отключать валидироватьзапрос в web.config или настройки страницы. Это значение включает ограниченную защиту XSS в ASP.NET, и его следует оставить без изменений, поскольку оно обеспечивает частичное предотвращение межсайтового сценария. В дополнение к встроенным средствам защиты рекомендуется полная проверка запроса.
  • Версия .NET Framework 4.5 включает в себя АнтиXssEncoder библиотека, которая имеет комплексную библиотеку кодирования ввода для предотвращения XSS. Используйте это.
  • Перечисляйте допустимые значения каждый раз, когда принимается пользовательский ввод.
  • Проверьте формат URI, используя Uri.IsWellFormedUriString.

Аутентификация с помощью форм

  • По возможности используйте файлы cookie для устойчивости.Cookieless аутентификация по умолчанию будет Уседевицепрофиле.
  • Не доверяйте URI запроса на сохранение сеанса или авторизации. Его можно легко подделать.
  • Уменьшите время ожидания проверки подлинности с помощью форм по умолчанию.20 минут в кратчайшие сроки, соответствующие вашему заявлению. Если скользящий срок действия используется, этот тайм-аут сбрасывается после каждого запроса, поэтому активные пользователи не будут затронуты.
  • Если HTTPS не используется, скользящий срок действия должен быть отключен. Рассмотрите возможность отключения скользящий срок действия даже с HTTPS.
  • Всегда обеспечивайте надлежащий контроль доступа.
    • Сравните имя пользователя, предоставленное пользователем, с User.Identity.Name.
    • Проверьте роли по User.Identity.IsInRole.
  • Используйте Поставщик членства ASP.NET и поставщик ролей, но проверьте хранилище паролей. Хранилище по умолчанию хеширует пароль с помощью одной итерации SHA-1, что довольно слабо. Шаблон ASP.NET MVC4 использует Идентификация ASP.NET вместо членства в ASP.NET, а ASP.NET Identity по умолчанию использует PBKDF2, что лучше. Ознакомьтесь с OWASP Памятка по хранению паролей для получения дополнительной информации.
  • Явно разрешайте запросы ресурсов.
  • Используйте авторизацию на основе ролей, используя User.Identity.IsInRole.

Руководство по XAML

  • Работайте в рамках ограничений безопасности зоны Интернета для вашего приложения.
  • Используйте развертывание ClickOnce. Для расширенных разрешений используйте повышение разрешений во время выполнения или развертывание доверенного приложения во время установки.

Руководство по Windows Forms

  • Используйте частичное доверие, когда это возможно. Частично доверенные приложения Windows уменьшают поверхность атаки приложения. Управляйте списком разрешений, которые ваше приложение должно использовать и что оно может использовать, а затем декларативно запрашивайте эти разрешения во время выполнения.
  • Используйте развертывание ClickOnce. Для расширенных разрешений используйте повышение разрешений во время выполнения или развертывание доверенного приложения во время установки.

Руководство WCF

  • Имейте в виду, что единственный безопасный способ передать запрос в службах RESTful — через HTTP POST, с включенным TLS. С использованием HTTP GET требует помещения данных в URL-адрес (например, строку запроса), который будет виден пользователю и будет регистрироваться и храниться в истории браузера.
  • Избегать БазоваяHttpBinding. У него нет конфигурации безопасности по умолчанию. Использовать WSHttpBinding вместо.
  • Используйте как минимум два режима безопасности для привязки. Безопасность сообщений включает в себя меры безопасности в заголовках. Транспортная безопасность означает использование SSL. Транспортсмессажекредентиал сочетает в себе два.
  • Проверьте свою реализацию WCF с помощью фаззера, например ЗАП.

© Перевод на русский язык. Оригинальные материалы: OWASP Cheat Sheet Series.
Этот проект использует материалы OWASP, распространяемые по лицензии CC BY-SA 4.0.