Как и где может применяться защита XSS в Laravel?

Интересно, как (если так или иначе) обеспечивается защита XSS в Laravel. Я не мог найти ничего об этом в документации.

проблема

Я использую метод Eloquent create() для вставки данных в базу данных (в моделях установлены свойства $fillable/$guarded). Как оказалось, я могу свободно поместить что-то подобное в любой форме ввода текста:

<script>alert('Hacking Sony in 3...2...')</script>

и значение будет вставлено в базу данных. Тогда, когда echo ИНГ это - предупреждение показывается.

Возможные решения

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

Если я не прав, каков оптимальный способ решить проблему?

  • Использую ли я необычную проверку регулярных выражений, чтобы запретить определенные символы?
  • Я использую mysql_real_escape_string() на каждом Input::get() я использую?
  • Должен ли я strip_tags()?

Экранирования на уровне просмотра недостаточно

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

Кто-нибудь уже сталкивался с этой проблемой?

Ответ 1

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

Собственно - это неверно.

Причина, по которой XSS обрабатывается только клиентом, заключается в том, что атаки XSS являются проблемой вывода. Нет угрозы безопасности, если вы храните <script>alert('Hacking Sony in 3...2...')</script> в своей базе данных - это просто текст - это ничего не значит.

Но в контексте вывода HTML - тогда текст имеет смысл, и поэтому именно там должна произойти фильтрация.

Также - возможно, что атака XSS может быть отраженной атакой, когда отображаемые данные не поступают из базы данных, а из другого источника. то есть загруженный файл, URL-адрес и т.д. Если вы не можете отфильтровать все различные местоположения ввода - вы рискуете потерять что-то.

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

p.s. В Laravel 5 по умолчанию {{ }} выйдет весь выход, что подчеркивает важность этого.

Изменить: вот хорошая дискуссия с дальнейшими соображениями о том, почему вы должны фильтровать вывод, а не вводить: html/XSS escape на входе и выходе

Ответ 2

Насколько я знаю, "официальная" позиция Laravel заключается в том, что Лучшая практика предотвращения XSS заключается в том, чтобы избежать выхода. Таким образом, {{{ }}}.

Вы можете добавить выходное экранирование через входную санитарию с помощью Input::all(), strip_tags() и array_map():

$input = array_map('strip_tags', \Input::all());

Ответ 3

Я исследовал защиту Laravel {{{...}}} против атаки xss. Он просто использует функцию htmlentities() следующим образом: htmlentities('javascript:alert("xss")', ENT_QUOTES, 'UTF-8', false); Это защищает вас от xss, только если вы используете его правильно, значит, не используйте его в определенных тегах HTML, потому что это приведет к возможности атаки XSS. Например:

$a = htmlentities('javascript:alert("xss")', ENT_QUOTES, 'UTF-8', false); 
echo '<a href="'.$a.'">link</a>';

В этом случае он уязвим для xss.

Ответ 4

Вы также фильтруете ввод перед валидацией, например: Сначала создайте /app/Common/Utility.php

<?php
namespace App\Common;
use Illuminate\Support\Facades\Input;

class Utility {
    public static function stripXSS()
    {
        $sanitized = static::cleanArray(Input::get());
        Input::merge($sanitized);
    }
    public static function cleanArray($array)
    {
        $result = array();
        foreach ($array as $key => $value) {
            $key = strip_tags($key);
            if (is_array($value)) {
                $result[$key] = static::cleanArray($value);
            } else {
                $result[$key] = trim(strip_tags($value)); // Remove trim() if you want to.
            }
       }
       return $result;
    }
}

И используйте в своем контроллере, как это

use App\Common\Utility;
public function store()
{
    Utility::stripXSS();
    // Remaining Codes
}

Этот код очистит ваш вход до проверки

Ответ 5

Пакет laravelgems/blade-escape расширяет Blade, добавляя различные стратегии/директивы побега - @text, @attr, @css, @js, @param

Пример:

<style>
.userPrefix:before { content: "@css($content)"; }
</style>
<div>
    <label class="userPrefix">@text($label)</label>
    <input type="text" name="custom" value="@attr($value)"/>
</div>
<a href="/[email protected]($username)">Profile</a>
<button onclick="callMyFunction('@js($username)');">Validate</button>
<script>
    var username = "@js($username)";
</script>

Прочитайте их README. XSS очень сложный, есть много контекстов и подходов.

Страница тестирования - http://laragems.com/package/blade-escape/test

Ответ 6

class XSSProtection
{
    /**
     * The following method loops through all request input and strips out all tags from
     * the request. This to ensure that users are unable to set ANY HTML within the form
     * submissions, but also cleans up input.
     *
     * @param Request $request
     * @param callable $next
     * @return mixed
     */
    public function handle(Request $request, \Closure $next)
    {
        if (!in_array(strtolower($request->method()), ['put', 'post'])) {
            return $next($request);
        }

        $input = $request->all();

        array_walk_recursive($input, function(&$input) {
            $input = strip_tags($input);
        });

        $request->merge($input);

        return $next($request);
    }
}

Ответ 7

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