Как удалить теги скрипта из ввода уценки пользователем?

В моем приложении php у меня есть поле textarea, которое получает уценку от пользователей (например, stackoverflow’s), а затем отображается на веб-сайте. Я использую Laravel Framework и использую parsedown-Laravel пакет.
Я могу сделать:

{!! Markdown::parse('__Hello__ Markdown!'); !!}

Оно работает.

{!! Markdown::parse('<h1>Hello</h1> Markdown!'); !!}

Это все еще работает. И я в порядке с этим.

Теперь, если я сделаю:

{!! Markdown::parse('<script>alert("XSS Attack!!!")</script> Markdown!'); !!}

Это все еще работает !!!

Как я могу предотвратить использование тегов сценариев в моем приложении, используя Laravel и этот пакет?

4

Решение

Если вы посмотрите на спецификацию Markdown (либо оригинальный синтаксис Джона Грубера или же CommonMark), вы обнаружите, что Markdown не должен заменять HTML. Его единственная цель — облегчить чтение написанного вами текста. Поскольку Markdown охватывает только небольшое подмножество HTML-тегов, вы все равно можете использовать встроенный HTML-код, чтобы создать именно то, что вам нужно. На самом деле Джон Грубер говорит следующее:

Для любой разметки, на которую не распространяется синтаксис Markdown, вы просто используете сам HTML. Нет необходимости вводить предисловие или разделять его, чтобы указать, что вы переходите с Markdown на HTML; вы просто используете теги.

Так что, по сути, именно так должен работать Markdown. Очевидно, что это не должно иметь место, если вы анализируете ввод пользователя. Поскольку анализатор Markdown выводит HTML-код, вы не можете использовать htmlentities функция или аналогичное решение.

Самый простой способ решить вашу проблему — использовать библиотеку фильтрации HTML, например Очиститель HTML. Это удалит вредоносный код из вывода Markdown и попытается остановить XSS-атаки. По сути, вы должны сначала вызвать ваш анализатор Markdown и с этим выводом вызвать библиотеку HTML Purifier.

5

Другие решения

Оригинал Parsedown В библиотеке есть опция экранирования html:

echo Parsedown::instance()
->setMarkupEscaped(true) # escapes markup (HTML)
->text("<div><strong>*Some text*</strong></div>");

# Output:
# <p>&lt;div&gt;&lt;strong&gt;<em>Some text</em>&lt;/strong&gt;&lt;/div&gt;</p>

От Учебник Parsedown: Начало работы

Предположительно, так как parsedown-Laravel это просто оболочка, вы должны иметь доступ к этой опции.

Очевидно, что это отключает все теги, а не конкретные.

Пользователь GitHub moldcraft на проблема 229 — отключить анализ определенных элементов на Parsedown bugtracker обеспечивает следующий код, это может проложить путь к решению:

Moldcraft прокомментировал 24 фев • 2015-02-24 18:41:31 +0100

Может быть полезно для кого-то: я также использую Parsedown для комментариев пользователей, и я хотел заменить все h1, h2, h3 на h4 для предотвращения SEO-предупреждений (например, на странице должен быть только один h1), вот мой сервис Symfony2

<?php

namespace App\MainBundle\Service;

use Parsedown;
use HTMLPurifier;
use Emojione\Emojione;
use Symfony\Component\DependencyInjection\ContainerInterface;

class Markdown extends Parsedown
{
/**
* @var HTMLPurifier
*/
private $purifier;

public function __construct(ContainerInterface $container)
{
$this->setMarkupEscaped(true);

{
$purifierConfig = array(
'HTML.ForbiddenElements' => array('h1', 'h2', 'h3'),
'HTML.ForbiddenAttributes' => array('style', 'onclick',),
'HTML.TargetBlank' => true,
);

$this->purifier = new HTMLPurifier($purifierConfig);
}

{
Emojione::$imageType = 'svg';
Emojione::$sprites = true;
Emojione::$imagePathSVGSprites = $container->get('templating.helper.assets')->getUrl(
'bundles/appmain/emojione/sprites/emojione.sprites.svg'
);
Emojione::$ascii = true;
}
}

function text($raw)
{
return Emojione::shortnameToImage(
$this->purifier->purify(
parent::text($raw)
)
);
}

private function safeHeader($Block)
{
if ($Block && isset($Block['element'])) {
/**
* Change h1, h2, h3 to h4
*/
if (in_array($Block['element']['name'], array('h1', 'h2', 'h3'))) {
$Block['element']['name'] = 'h4';
}
}

return $Block;
}

protected function blockHeader($Line)
{
return $this->safeHeader(
parent::blockHeader($Line)
);
}

protected function blockSetextHeader($Line, array $Block = null)
{
return $this->safeHeader(
parent::blockSetextHeader($Line, $Block)
);
}
}
3

Принятие пользовательского ввода и его интеграция с кодом приложений никогда не может быть безопасным. Это не идти.

Если это просто отображение кода, то вы можете сделать это, используя <textinput> тег для примера. Вы можете стилизовать его так, чтобы он не выглядел как вход. Или вы просто используете функцию как htmlescape() в сочетании с <pre> тег.

-2
По вопросам рекламы [email protected]