Топ-8 плохих практик безопасности в Laravel, о которых вы должны знать

Настоящая безопасность заключается в самой практике кода, мы не можем определить, безопасен фреймворк или нет, Laravel настолько безопасен, насколько это возможно, и максимально оптимизирован, это действительно зависит от разработчика.

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

  • SQL-инъекция через имена столбцов и необработанные запросы.
  • SQL-инъекция через правила проверки.
  • Внедрение правил проверки.
  • Использование GET для не-GET-маршрутов.
  • Использование $request->all().
  • Забыть режим отладки в продакшене.
  • XSS с использованием неэкранированного оператора данных.
  • XSS с использованием атрибута href.

SQL-инъекция через имена столбцов:

Очень распространенная практика передачи управляемых пользователем столбцов в Query Builder, думая, что Laravel проверяет их с помощью привязки параметров PDO, но, как упоминается в документации Laravel :

PDO не поддерживает привязку имен столбцов. Поэтому вы никогда не должны позволять вводу пользователем диктовать имена столбцов, на которые ссылаются ваши запросы, включая столбцы «упорядочить по».

Чтобы было понятно, предположим, что у нас есть следующий запрос:

Product::where('brand_id',$request->brand_id) 
->orderBy($request->orderBy)
->get();

поэтому, если пользователь ввел что-то вроде price->”%27))%23injection , запрос будет переведен следующим образом:

выберите * из `продуктов`, где brand_id =? упорядочить по json_unquote( 
json_extract(`price`, '$.""')
) #injection"')) asc

Что делать: как упоминается в документации Laravel:

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

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

Так что не забудьте использовать привязку параметров

SQL-инъекция через правила проверки

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

Эта практика распространена при проверке запроса на обновление и предоставлении идентификатора из самого запроса. Вот пример.

$id = $запрос->id; 
$rules = [
'email'=>'email|обязательный|уникальный: пользователи, электронная почта,'.$id
];
$validator = Validator::make($request->all(),$rules);

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

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

Внедрение правил проверки:

1- Сделайте правило необязательным:
как в предыдущем примере

$id = $запрос->id; 
$rules = [
'email'=>'email|обязательный|уникальный: пользователи, электронная почта,'.$id
];
$validator = Validator::make($request->all(),$rules);

пользователь передал следующее:

10|иногда

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

2- Проверка регулярного выражения DDOS:

Давайте представим, что пользователь отправляет это регулярное выражение:

1|регулярное выражение:(*а){10000}Предыдущее регулярное выражение потребляло много ресурсов, а несколько запросов с одной и той же полезной нагрузкой приводили к перегрузке ЦП.

Что вам следует делать: Как упоминалось ранее: просто не создавайте правила проверки на основе вашей пользовательской записи, если вы вынуждены, просто проверьте значения вручную, а затем создайте свое правило.

Использование GET для не-GET-маршрутов

Как упоминалось в документации Laravel:

Каждый раз, когда вы определяете HTML-форму «POST», «PUT», «PATCH» или «DELETE» в своем приложении, вы должны включить в форму скрытое _tokenполе CSRF, чтобы промежуточное программное обеспечение защиты CSRF могло проверить запрос.

По умолчанию Laravel не выполнит любой запрос от упомянутых действий без поля _token.

Так почему мы упомянули об этом?
За свою карьеру я видел, как многие разработчики определяют маршрут GET для не-GET действий, как, например, этот маршрут

Route::get('product/{id}/delete','ProductController@delete);

Для предыдущего маршрута, если он был вызван, он выполнит действие удаления, потому что laravel не будет проверять поле _token, и действие будет выполнено.

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

Использование $request->all() для создания модели

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

\Приложение\Модели\User.php

<?php 
namespace App\Models;
class User extends Authenticatable
{

protected $fillable = [
'usernamename',
'email',
'password',
'role'
];

}

UserRequest.php

<?php 

namespace App\Http\Requests;

class UserRequest extends FormRequest
{

public function rules()
{
return [
'username'=>'required',
'email'=>'email|required|unique:users,email'
'password'=>'required|min:8'
];
}
}

UserController.php

<?php 

namespace App\Http\Controllers;

класс UserController расширяет контроллер
{
общедоступное хранилище функций (UserRequest $ request)
{
User :: create ( $ request-> all () );
вернуть ответ()->json();
}
}

Многие разработчики думают, что при использовании проверки FormRequest.php $request->all() будет возвращать только проверенные данные, НЕПРАВИЛЬНО
для предыдущего примера, если пользователь отправит полезную нагрузку как:

{ 
"имя пользователя": "тест",
"электронная почта": "email@email.com",
"пароль": "Pssw0rd",
"роль": "admin"
}

Пользователь Test будет администратором и бум.

Это простой пример, так что продолжайте свое воображение.

Что делать:
вместо использования $request->all()
вы можете использовать $request->validated() или $request->only().

Забыть включенный режим отладки в производстве

Итак, мы сделали все возможное, чтобы сделать приложение безопасным. И последнее: НЕ ЗАБЫВАЙТЕ APP_DBUG=TRUE в файле .env.

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

например, я создал функцию для исключения исключения следующим образом

На странице исключений было открыто содержимое моего файла модели пользователя:

Что делать:
просто установить для APP_DEBUG в файле .env значение false.
если вы хотите отслеживать журнал исключений, просто добавьте следующий код в файл App\Exceptions\Handler.php:

защищенная функция LogException(\Exception $ex){ 
Log::error("Сообщение: ".$ex->getMessage());
Log::error("Строка: ".$ex->getLine());
Log::error("Файл: ".$ex->getFile());
}
public function register(){
$this->reportable(function (Throwable $e) {
$this->LogException($exception);
});
}

XSS с использованием неэкранированного оператора данных

По умолчанию операторы Blade {{ }}автоматически отправляются через htmlspecialcharsфункцию PHP для предотвращения XSS-атак. Если вы не хотите, чтобы ваши данные были экранированы, вы можете использовать следующий синтаксис:
{!! $data !!}

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

$data = '<b>Полужирный</b>'; 
-----------------------
<body>
это экранировано {{$data}}
это не экранировано {!! $данные !!}
</body>

страница будет следующей

например, если $data был пользовательским вводом, например:

$data = '<script>alert("XSS-атака");</script>';

результат будет:

Что делать:
будьте осторожны и не используйте неэкранированный оператор {!! !!} с данными, предоставленными пользователем, Никогда не доверяйте вводу пользователя

XSS с использованием атрибута href

не только {!! !!} позволяет выполнять вредоносный код на стороне клиента, но также это можно сделать с помощью атрибута href в теге <a>.

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

$data = 'javascript:alert("XSS-атака");'; 
--------------------------------------------------
.blade-файл:
<a href="{{$data}}">Нажмите здесь, чтобы увидеть дополнительную ссылку</a>

Итак, когда пользователь нажимает на него:

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

Комментарии

Популярные сообщения из этого блога

Две сетевые карты Windows 7. Настройка маршрутизации

Cisco Packet Tracer + Русификатор

Восстановление конфигурации Cisco с tftp сервера