По умолчанию, Eloquent ORM Laravel защищает от SQL-инъекций путем параметризации запросов и использования привязок SQL.
Например, рассмотрим следующий запрос:
use App\Models\User;
User::where('email', $email)->get();
Приведенный выше код выполняет следующий запрос:
select *
from `users`
where `email` = ?
Таким образом, даже если $email
является ненадежными данными ввода пользователя, вы защищены от атак SQL-инъекций.
Однако есть несколько случаев, когда вы можете быть уязвимы к SQL-инъекция:
Хотя Laravel предоставляет возможность использовать необработанные выражения запросов для создания более сложных или
специфичных запросов (Например, для не поддерживаемой базы данных), следует быть осторожным и всегда использовать
привязку данных.
Например:
use Illuminate\Support\Facades\DB;
use App\Models\User;
User::whereRaw('email = "'.$request->input('email').'"')
->get();
// или так:
DB::table('users')
->whereRaw('email = "'.$request->input('email').'"')
->get();
Эти запросы уязвимы к инъекциям, так как не используют привязки SQL для данных полученных от пользователя.
Мы можем исправить код выше, сделав следующую модификацию:
use App\Models\User;
User::whereRaw('email = ?', [
$request->input('email')
])->get();
Мы даже можем использовать именованные привязки SQL, как показано ниже:
use App\Models\User;
User::whereRaw('email = :email', [
'email' => $request->input('email')
])->get();
Вы никогда не должны разрешать пользовательские данные влиять на имена столбцов, на которые ссылаются ваши запросы.
Следующие запросы могут быть уязвимы к SQL-инъекциям:
use App\Models\User;
User::where($request->input('colname'), 'somedata')
->get();
User::query()->orderBy($request->input('sortBy'))
->get();
Важно отметить, что несмотря на то, что в Laravel имеются встроенные средства защиты от SQL-инъекций, такие как
оборачивание имен столбцов, некоторые базы данных могут оставаться уязвимыми из-за ограничений или конфигураций.
Всегда проверяйте пользовательский ввод для таких ситуаций, как показано ниже:
use App\Models\User;
$request->validate([
'sortBy' => Rule::in(['price', 'updated_at']),
]);
User::query()
->orderBy($request->validated()['sortBy'])
->get();
Некоторые механизмы валидации данных могут включать в себя возможность указания имен столбцов в базе данных. Эти правила
подвержены уязвимостям SQL-инъекций, аналогично ситуации, когда SQL-инъекции направлены на имена столбцов, поскольку
запросы формируются аналогичным образом.
Например, в следующем коде может существовать уязвимость:
use Illuminate\Validation\Rule;
$request->validate([
'id' => Rule::unique('users')
->ignore($id, $request->input('colname'))
]);
На самом деле, этот код генерирует следующий запрос:
use App\Models\User;
$colname = $request->input('colname');
User::where($colname, $request->input('id'))
->where($colname, '<>', $id)
->count();
Поскольку имя столбца определяется пользовательским вводом, подобная ситуация эквивалентна SQL-инъекции по именам
столбцов.