С# | Защита от DOS-атак в ASP.NET

Тема в разделе "C++ / C# / .NET", создана пользователем Евгенька, 18 мар 2015.

  1. Евгенька

    Евгенька Banned

    Регистр:
    20 фев 2015
    Сообщения:
    153
    Репутация:
    192
    Баллы:
    30
    Пол:
    Мужской
    Веб-сервисы являются самой привлекательной мишенью для хакеров. Даже школьник может большим количеством запросов уронить сайт на котором выполняются скрипты, создающие ощутимую нагрузку на серверную операционную систему. Особенно хорошо в качестве мишени подходят страницы, на которых расположено большое количество информеров, обрабатываемых серверными скриптами (такими как Ajax). Чтобы самостоятельно устроить такую атаку, достаточно запустить элементарный код:
    PHP:
    for( int i 0100000++ )
    {
       
    WebClient client = new WebClient();
       
    client.DownloadString("http://www.microsoft.com/default.aspx");
    }
    Уже после нескольких запросов Вы обнаружите, что в ответ от сервера приходит страница с ошибкой. Однако, это совсем не значит, что сервер уже упал. Просто сайт отверг Ваши последние запросы. Таким образом Вы получили отказ в ообслуживании (Denial of Service или сокращённо DOS).

    Самым простым способом защиты от подобного флуда является подсчёт количества запросов с определённого айпишника и запоминание этого значения в кэше ASP.NET. А когда количество запросов превысит допустимый порог, то отвергать запросы с этого адреса в течение определённого срока, например на 10 минут. Через 10 минут вновь начать обрабатывать поступающие запросы с конкретного айпишника.

    Ниже приведён пример класса ActionValidator, который позволяет запоминать такие параметры посетителя как первый визит, последующий визит, асинхронные постбэки, добавление нового виджета, создание новой страницы и т.д. В классе по каждому параметру заданы предельно допустимые значения для конкретного IP-адреса.
    PHP:
    public static class ActionValidator
    {
         private const 
    int DURATION 10// 10-минутный период
     
         
    public enum ActionTypeEnum
         
    {
             
    FirstVisit 100// Самый значимый параметр, подбирать его значение надо осторожно.
             
    ReVisit 1000,  // Повторные посещения особо не ограничиваем
             
    Postback 5000,    // Это тем более не проблема
             
    AddNewWidget 100,
             
    AddNewPage 100,
         }
    Далее рассмотрим статический метод IsValid, который проверяет не достигнуто ли предельное значение по каждому типу запраса. Метод возвращает true, если лимит по запросу не достигнут и false, если запрос пользователя можно отклонить. Если IsValid вернул false, то можно просто вызвать Request.End(), тем самым защитив ASP.NET от дальнейшей загрузки. Так же можно сделать редирект на страницу с сообщением о превышении количества запросов с этого айпи.
    PHP:
    public static bool IsValidActionTypeEnum actionType )
    {
       
    HttpContext context HttpContext.Current;
       if( 
    context.Request.Browser.Crawler ) return false;
      
       
    string key actionType.ToString() + context.Request.UserHostAddress;
       var 
    hit = (HitInfo)(context.Cache[key] ?? new HitInfo());
        
       if( 
    hit.Hits > (int)actionType ) return false;
       else 
    hit.Hits ++;
       
       if( 
    hit.Hits == )
          
    context.Cache.Add(keyhitnullDateTime.Now.AddMinutes(DURATION),
             
    System.Web.Caching.Cache.NoSlidingExpiration,
             
    System.Web.Caching.CacheItemPriority.Normalnull);
       return 
    true;
    }
    Ключом в кэше является пара: "типа действия" и IP-адрес клиента. Сначала идёт проверка, есть ли в кэше точно такая же пара. Если нет, то пара добавляется в кэш и начинается отсчёт срока. По истечение срока пара автоматически удалится из кэша и, если пользователь продолжит посещение сайта, то всё повторится сначала. В случае если пара уже присутствует в кэше, то метод проверяет не достигнут ли предел и, если нет превышения, то счётчик увеличивается на еденицу. Принудительно записывать новое значение счётчика в кэш не нужно, так как hit всего лишь ссылается на строку в кэше и обновление счётчика происходит автоматически. Однако если это сделать, то значение экспирации в кэше для данной пары будет обновлено и нарушится логика возобновления отсчёта на конкретный срок.

    Использовать этот класс можно прямо на default.aspx:
    PHP:
    protected override void OnInit(EventArgs e)
    {
       
    base.OnInit(e);
       
    // Проверяем можно ли обработать повторное посещение
       
    if( !base.IsPostBack )
       {
          
    // Блокируем запросы без кукисов
          
    if( Profile.IsFirstVisit )
          {
             if( !
    ActionValidator.IsValid(ActionValidator.ActionTypeEnum.FirstVisit)) 
                
    Response.End();
          }
          else
          {
             if( !
    ActionValidator.IsValid(ActionValidator.ActionTypeEnum.ReVisit) ) 
                
    Response.End();
          }
       }
       else
       {
          
    // Ограничение количества постбэков
          
    if( !ActionValidator.IsValid(ActionValidator.ActionTypeEnum.Postback) )
                
    Response.End();
       }
    }
    В этом примере проверяются первый визит, повторный визит, постбэки и т.д.

    Конечно, защиту от DoS атак можно переложить на плечи брэндмауэров, таких как Cisco. Любой хостинг-провайдер будет уверять Вас, что вся их сеть защищена от DOS и DDOS (Distributed DOS) атак. Однако, от TCP SYN атак и флуда кривых пакетов они защищаются на аппаратном уровне, в то время как DOS-атаки работают на уровне приложения и, соответственно, защита от них так же должна быть встроена в приложение.

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