10 главных уязвимостей безопасности веб-приложений

кибербезопасность 3 Безопасность

Очень важно учитывать безопасность приложений, которые вы создаете. Существует множество способов решения проблем безопасности, но действенным способом для начала является устранение десяти основных проблем безопасности, определенных OWASP (Открытый проект безопасности веб-приложений). В этой статье мы рассмотрим десятку основных уязвимостей безопасности приложений.

OWASP — международная организация, занимающаяся вопросами безопасности веб-приложений, и каждые четыре года сообщество выпускает отчет OWASP Top 10, в котором излагаются наиболее насущные проблемы безопасности веб-приложений. Мы посмотрим на эти уязвимости через призму разработчика PHP, но они имеют отношение к созданию приложений на любом языке программирования.

Уязвимости безопасности OWASP: обзор и сравнение

В список OWASP Top 10 2021 года вошли десять самых опасных уязвимостей безопасности для веб-приложений. Если мы сравним текущий список со списком 2017 года, мы увидим, что некоторые недостатки безопасности остались в списке, но находятся в другом месте, а также в списке есть пара новых недостатков безопасности.

Ниже приведена таблица сравнения списков за 2017 и 2021 годы. (Пробелы безопасности, которые были привнесены в список за 2021 год, выделены жирным шрифтом, а остальные просто перетасованы.)

2017 OWASP Топ-10 2021 OWASP Топ-10
#1 – Инъекция #1 – Сломанный контроль доступа
#2 – Сломанная аутентификация # 2 — Криптографические сбои
# 3 — Разоблачение конфиденциальных данных №3 – Инъекция
#4 – Внешние объекты XML (XXE) #4 – Небезопасный дизайн
#5 – Сломанный контроль доступа #5 – Неправильная настройка безопасности
#6 – Неправильная настройка безопасности #6 – Уязвимые и устаревшие компоненты
#7 – Межсайтовый скриптинг (XSS) #7 – Ошибки идентификации и аутентификации
#8 – Небезопасная десериализация #8 – Сбои целостности программного обеспечения и данных
#9 – Использование компонентов с известными уязвимостями # 9 — Регистрация безопасности и мониторинг сбоев
#10 – Недостаточное ведение журнала и мониторинг 10. Подделка запросов на стороне сервера (SSRF)
Читайте также:  7 советов по защите сайта от взлома

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

Давайте углубимся в каждую из этих проблем безопасности.

Сломанный контроль доступа

Согласно выпуску OWASP за 2021 год, проблема, на которую мы должны обратить наибольшее внимание, — это нарушенный контроль доступа. Нарушенный контроль доступа — это то, на что это похоже: это происходит, когда мы неправильно контролируем доступ к нашим приложениям. Пример нарушенного контроля доступа показан ниже.

<form method="post" action="">
<input type="text" name="Username" placeholder="Your Username?">
<input type="text" name="Password" placeholder="Your Password?">
<input type="submit" name="Submit" value="Log In">
</form>

<?php
if(isset($_POST['Submit'])) {
  $Username = $_POST['Username'];
  $Password = $_POST['Password'];
  if(!empty($Username)) {
    if(!empty($Password)) {
    header("loggedin_page.php");
    exit;
    }
  }
}
?>

Ты видишь проблему? Код просто проверяет, не пусты ли поля имени пользователя и пароля. Как насчет того, чтобы запустить пару запросов в базе данных, чтобы убедиться, что имя пользователя и пароль существуют? Чтобы проверить рассматриваемый аккаунт? Об этой части благополучно забыли. Пользователь может просто ввести что-нибудь в поля имени пользователя и пароля, чтобы убедиться, что они не пусты, нажать » Отправить «, и пользователь войдет в систему.

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

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

Криптографические сбои ранее были известны как «разоблачение конфиденциальных данных». Раскрытие конфиденциальных данных было переименовано в «криптографические сбои», поскольку это решает ряд проблем безопасности, в то время как «раскрытие конфиденциальных данных» решает только одну из них.

Криптографические сбои охватывают сбой шифрования данных, что часто приводит к раскрытию конфиденциальных данных. Криптографические сбои в PHP в основном связаны с паролями: их хеширование с помощью чего-либо, кроме алгоритмов хеширования, которые были разработаны для работы медленно (вспомните BCrypt и Blowfish), является криптографическим сбоем, потому что другие типы хэшей (MD5 и подобные) легко и быстро вычислить. грубая сила.

Чтобы избежать криптографических сбоев: убедитесь, что все пароли, хранящиеся в вашей базе данных, хешированы с помощью алгоритма, медленного для перебора. Мы предлагаем вам выбрать Blowfish или BCrypt, так как эти алгоритмы безопасны для длительного использования, были протестированы экспертами по безопасности и доказали свою устойчивость к атакам.

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

Инъекция и небезопасный дизайн

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

На изображении ниже показан соответствующий пример кода.

<form method="post" action="">
<input type="text" name="Username" placeholder="Your Username?">
<input type="text" name="Password" placeholder="Your Password?">
<input type="submit" name="Submit" value="Log In">
</form>

<?php
if(isset($_POST['Submit'])) {
  $Username = $_POST['Username'];
  $Password = $_POST['Password'];
  if(!empty($Username)) {
    if(!empty($Password)) {
$Query = $DB->query("SELECT * FROM users WHERE username = $Username AND password = $Password");
    } else {
    echo "Password empty!";
    exit;
    }
  } else {
    echo "Username empty!";
    exit;
  }
}
?>

Показанная выше ошибка довольно очевидна: когда любой пользовательский ввод передается в базу данных, каждый может делать все, что приходит ему в голову. Этот недостаток характерен не только для PHP. Если вы передаете пользовательский ввод прямо в базу данных, используя любой другой язык программирования, у вас будет точно такая же проблема.

Последствия успешно смонтированной атаки SQL-инъекцией могут быть самыми разными, но в большинстве случаев они охватывают следующие вещи:

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

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

Чтобы избежать SQL-инъекций: используйте PDO с параметризованными запросами. Такой подход защищает приложения от SQL-инъекций, поскольку данные отправляются отдельно от самого запроса.

Такой подход к показанному ранее запросу будет выглядеть так, как показано на рисунке ниже (обратите внимание на изменения в строках 13 и 14).

<?php
if(isset($_POST['Submit'])) {
  $Username = $_POST['Username'];
  $Password = $_POST['Password'];
  if(!empty($Username)) {
    if(!empty($Password)) {
    $Query = $DB->prepare("SELECT * FROM users WHERE username = :Username AND password = :Password");
    $Query->execute(array(":Username" => $Username, ":Password" => $Password));
    } else {
    echo "Password empty!";
    exit;
    }
  } else {
    echo "Username empty!";
    exit;
  }
}
?>

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

Чтобы избежать внедрения SQL, передачи пользовательского ввода в базу данных и небезопасных недостатков дизайна, убедитесь, что вы следуете рекомендациям по безопасному кодированию, изложенным OWASP или другими поставщиками. Если вы будете следовать этим рекомендациям, вы должны быть в безопасности на этом фронте.

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

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

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

Вот почему так важно всегда делать следующее:

  • Убедитесь, что ваше приложение использует компоненты, которые всегда обновлены.
  • Не забудьте принудительно разлогинить пользователей после определенного периода бездействия. (То есть убедитесь, что сеансы истекают через указанный период времени.)
  • Если возможно, рассмотрите возможность внедрения CAPTCHA после определенного периода безуспешных попыток отправить форму или войти в какую-либо часть веб-сайта и т. д.
  • Если возможно, используйте брандмауэр веб-приложений, чтобы защитить свое веб-приложение от атак, направленных на него, и рассмотрите возможность использования таких сервисов, как предоставляемый Cloudflare, для одновременной защиты вашего приложения от DoS- и DDoS-атак.

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

Чтобы ваше приложение было более безопасным, уделите особое внимание компонентам, которые позволяют пользователям аутентифицировать себя.

Ошибки идентификации и аутентификации

Ошибки идентификации и аутентификации ранее были известны как уязвимость Broken Authentication. Такая уязвимость возникает, когда приложение не защищает должным образом ту часть себя, которая позволяет пользователям аутентифицировать себя, что может означать одну или несколько из следующих вещей:

  • Приложение не защищает свои формы от попыток брутфорса с помощью CAPTCHA или других мер.
  • Страница регистрации приложения позволяет использовать слабые пароли. (То есть для приложения не определена минимальная длина пароля.)
  • В регистрационной форме отсутствует поле «повторить пароль». (То есть пользователи регистрируются без перепроверки правильности пароля.)
  • Форма смены пароля не защищена от CSRF (подделка межсайтовых запросов), что позволяет пользователю Б подделывать запросы от имени пользователя А. (То есть пользователь Б может отправить специально созданный URL-адрес, который при открытии изменится пароль пользователя А.)
  • Учетные записи могут быть перечислены: приложение предоставляет различные виды сообщений в зависимости от того, существует ли определенная учетная запись в базе данных или нет.
  • Приложение хранит пароли в виде обычного текста.
  • Приложение возвращает имя пользователя после его указания во входном параметре без его фильтрации. (Такой подход делает возможной XSS-атаку, когда злоумышленник может внедрять вредоносные скрипты на веб-сайт.)

Чтобы избежать сбоев идентификации и аутентификации: убедитесь, что формы регистрации и входа в систему защищены. Конечно, это легче сказать, чем сделать, но следуйте шагам, описанным ниже, и все будет готово:

  • Убедитесь, что все зарегистрированные пользователи используют безопасные пароли. (Применить политику из восьми или более символов.)
  • Представьте пользователей с помощью CAPTCHA после определенного количества неудачных попыток входа в систему (скажем, пяти или более). Другими словами, примените ограничение скорости.
  • Убедитесь, что все параметры, представленные пользователем, чистые. (То есть не возвращайте пользовательский ввод обратно пользователю без проверки. Это активирует атаку XSS.)
  • Убедитесь, что форма, позволяющая изменять пароли, защищена от CSRF. Другими словами, создайте токен, который меняется при каждом запросе, чтобы злоумышленник не мог подделать запрос и выдать себя за пользователя.
  • По возможности используйте двухфакторную аутентификацию, чтобы избежать атак с подстановкой учетных данных, нацеленных на вашу форму входа.

Сбои программного обеспечения и целостности, а также проблемы с регистрацией и мониторингом

В то время как проблемы, связанные с механизмом ведения журнала и мониторинга, относительно очевидны, сбои программного обеспечения и целостности могут быть не такими. Однако в этом нет ничего волшебного: сообщество OWASP просто говорит нам, что мы должны проверять целостность всех видов программного обеспечения, которое мы используем, независимо от того, основано оно на PHP или нет. Подумайте об этом: когда вы в последний раз обновляли свое приложение? Вы проверяли целостность обновления? А как насчет ресурсов, которые вы загружаете в свое веб-приложение?

Взгляните на пример кода, изображенный ниже. Вы ничего не замечаете?

<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-rbsA2VBKQhggwzxH7pPCaAg046MgnOM80zWlRWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">

<form method="post" action="">
<input type="text" name="Username" placeholder="Your Username?">
<input type="text" name="Password" placeholder="Your Password?">
<input type="submit" name="Submit" value="Log In">
</form>

<?php
if(isset($_POST['Submit'])) {
  $Username = $_POST['Username'];
  $Password = $_POST['Password'];
  if(!empty($Username)) {
    if(!empty($Password)) {
    $Query = $DB->prepare("SELECT * FROM users WHERE username = :Username AND password = :Password");
    $Query->execute(array(":Username" => $Username, ":Password" => $Password));
    } else {
    echo "Password empty!";
    exit;
    }
  } else {
    echo "Username empty!";
    exit;
  }
}
?>

<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"
integrity="sha384-kenUlKFdBIe4zVFOs0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script>

И таблица стилей, и загруженный в нее файл JavaScript защищены атрибутом целостности. Атрибут целостности жизненно важен для гарантии того, что таблицы стилей и файлы JavaScript, загруженные в веб-приложение, не были подделаны. Если код файла вообще изменился с момента создания атрибута целостности, скрипты не будут загружаться в веб-приложение, а вместо этого появится сообщение об ошибке, как показано на рисунке ниже.

И таблица стилей, и загруженный в нее файл

Целостность везде. И хотя в некоторых ситуациях нарушение целостности будет сопровождаться предупреждениями (как на изображении выше), в других случаях последствия будут более серьезными и могут привести к утечке данных.

Чтобы удостовериться, что ваш код не был подделан, крайне важно надлежащим образом отслеживать вашу инфраструктуру, но такой подход сам по себе может быть ошибочным. Когда ваш подход к мониторингу несовершенен, вы не будете ловить ошибки. Некоторые ошибки небольшие, как показано выше. Некоторые ошибки являются более серьезными, например, когда ваше приложение уязвимо для SQL-инъекций, неправильной настройки безопасности или любых других недостатков, перечисленных выше. Поэтому всегда следите за тем, чтобы ваше приложение регистрировало любые аномалии, связанные с критически важными функциями вашего веб-сайта.

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

Чтобы смягчить сбои программного обеспечения и целостности, а также проблемы с ведением журналов и мониторингом: изучите предложения брандмауэров веб-приложений, такие как предлагаемые Cloudflare, Sucuri или Imperva. И помните: платить поставщикам безопасности всегда дешевле, чем восстанавливать данные после утечки.

Подделка запросов на стороне сервера

Последней важной проблемой в списке OWASP Top 10 2021 года является подделка запросов на стороне сервера (SSRF). SSRF — это атака, которая позволяет злоумышленнику отправлять запросы на веб-сайт через уязвимый сервер. SSRF — это новая уязвимость в списке OWASP, и она действует аналогично своему кузену CSRF. В то время как CSRF стремится делать непреднамеренные запросы от имени пользователя, SSRF нацелен на сервер. SSRF заставляет приложение делать запросы к местоположению, указанному злоумышленником. Посмотрите на фрагмент кода, изображенный ниже. (Обратите внимание, что вызов header()функции должен быть завершен до того, как какой-либо текст будет записан на страницу, иначе вызов может быть проигнорирован.)

<?php
if(isset ($_POST['Submit'])) {
  $URL = $_GET('picture_url'];
  if(filter_var($URL, FILTER_VALIDATE_URL)) {
  $Contents = file_get_contents($URL);
  header("Content-Type: image/png");
  echo $Contents;
  header ("Location:picture_changed.php");
  exit;
  } else {
  echo "Incorrect URL.";
  exit;
  }
}
?>

Этот фрагмент кода делает несколько вещей. Сначала он проверяет, является ли URL-адрес, указанный в picture_urlпараметре GET, допустимым URL-адресом. Затем он предоставляет содержимое URL-адреса пользователю и перенаправляет пользователя на другой PHP-скрипт. Предоставление содержимого в URL-адресе пользователю — это именно то, что делает этот PHP-код восприимчивым к SSRF. Отображать что-либо, предоставленное пользователем, опасно, потому что пользователь может сделать одно из следующих действий:

  • Укажите URL-адрес внутреннего файла на сервере и прочитайте конфиденциальную информацию. Например, когда предоставлен URL-адрес file:///etc/passwd/, приложение, восприимчивое к SSRF, отобразит /etc/passwdфайл на экране. Но этот файл содержит информацию о пользователях, которым принадлежат процессы, запущенные на сервере.
  • Предоставьте приложению URL-адрес файла на сервере, а затем прочитайте файл. (Подумайте о предоставлении URL-адреса веб-службы на сервере и т. д.)
  • Предоставьте приложению URL-адрес фишинговой страницы, а затем перешлите его пользователю. Поскольку фишинговая страница будет располагаться по исходному URL-адресу (URL-адресу вашего сервера), высока вероятность того, что ничего не подозревающий пользователь попадется на такую ​​уловку.

Избегание SSRF: возможно, самый простой способ избежать такой атаки — использовать белый список URL-адресов, которые можно использовать. Белый список в веб-приложении PHP будет выглядеть примерно так, как показано на рисунке ниже. (Обратите внимание на строки с 25 по 28.)

<?php
if(isset ($_POST['Submit'])) {
  $URL = $_GET('picture_url'];

  $whitelist = array("https://google.com", "https://twitter.com", ""...");
  if(!in_array($URL, $whitelist)) {
    echo "Incorrect URL.";
  }

  if(filter_var($URL, FILTER_VALIDATE_URL)) {
  $Contents = file_get_contents($URL);
  header("Content-Type: image/png");
  echo $Contents;
  header ("Location:picture_changed.php");
  exit;
  } else {
  echo "Incorrect URL.";
  exit;
  }
}
?>
</div>
</form>

Теперь приложение, повторяющее вывод URL-адреса обратно пользователю, больше не является проблемой, поскольку список URL-адресов контролируется вами. Ваше приложение больше не уязвимо для SSRF!

Заключение

В этой статье мы познакомили вас с десятью основными недостатками безопасности, которые могут поставить под угрозу ваши веб-приложения PHP. Некоторые из этих недостатков впервые появились в OWASP в 2021 году, а другие были перетасованы из более старой версии OWASP 2017 года. Однако один принцип остается неизменным: все они относительно опасны, и с ними следует обращаться надлежащим образом.

Оцените статью
bestprogrammer.ru
Добавить комментарий