Back-End

5 mai, 2017

Lidando com o bloqueio de envio de formulários e exploit XSS no Chrome

Publicidade

Desde a versão 57, o Chrome começou a bloquear o envio de formulários com conteúdo criado por entradas de editor de HTML regulares.

O problema é que isso está impedindo que muitos sites que usam editores de conteúdo HTML comuns funcionem, apesar de não existir um exploit XSS acontecendo de verdade.

Leia este artigo para saber mais por que isso acontece e quais alternativas você pode implementar enquanto o Chrome bloqueia as solicitações.

 

O que é um Exploit de Segurança XSS?

XSS é a abreviação de Cross-Site Scripting. É um ataque de segurança que consiste em enviar HTML com JavaScript mal-intencionado para um site.

Se o site exibir esse HTML com JavaScript sem ter filtrado o código JavaScript mal-intencionado, os cookies enviados pelo site podem ser roubados e enviados para um site invasor, para que ele possa usar para forjar sessões de usuário e acessar a conta do site do usuário sem permissões.

O erro de envio de formulário no Chrome

O navegador Chrome (e o Chromium) possui um recurso de auditoria de segurança XSS que analisa o HTML enviado por meio de valores de formulário e bloqueia essas solicitações XSS, de forma que os formulários nunca são enviados e eventuais exploits XSS são evitadas.

O problema é que, desde a versão 57 do Chrome, ele começou a bloquear os envios POST de formulário com certas estruturas HTML. Por isso, mostra uma mensagem de erro denominada ERR_BLOCKED_BY_XSS_AUDITOR e o formulário não é enviado.

O recurso de auditoria XSS do Chrome é uma boa ideia porque protege os usuários de terem suas contas exploradas em determinados sites.

O problema é que este auditor não é muito confiável na versão 57 do Chrome. Há alguns casos que ele bloqueia o envio de HTML que não contém JavaScript mal-intencionado, ou mesmo nenhum JavaScript.

Este é o caso quando um site usa um editor de conteúdo HTML. Na realidade, editores de conteúdo HTML são partes de páginas HTML com o atributo contenteditable.

<div contenteditable="true">Some HTML goes here</div>

Esse atributo diz ao navegador que o usuário pode inserir conteúdo, por exemplo, digitando texto ou colando parte de uma página ali. Em seguida, algum código JavaScript na página extrai o HTML editado e o coloca em uma entrada de formulário oculto, para que ele possa ser enviado ao servidor quando o formulário for enviado.

Geralmente, os editores de HTML mostram áreas de edição dentro de um iframe para que as operações de seleção, corte, cópia e colagem sejam contidas dentro do iframe. Então, algum código JavaScript puxa o HTML editado do iframe para a entrada oculta do formulário.

O problema está acontecendo com o Chrome 57 porque, aparentemente, ele está detectando o HTML retirado do elemento contenteditable como inseguro, mesmo quando ele não contém nenhum código JavaScript.

É difícil saber qual é exatamente o código HTML que está sendo detectado como mal-intencionado porque o problema não acontece com todos os tipos de código HTML sendo editados.

Usando o cabeçalho X-XSS-Protection como alternativa temporária para evitar o erro de bloqueio

Infelizmente, isso afeta milhares de web sites que usam editores HTML para permitir que seus usuários legítimos editem conteúdo HTML. Este é o caso deste sistema de blog que estou usando agora para editar este artigo.

O problema foi comunicado à equipe do Google Chrome, mas não foi corrigido. Não está sequer claro se eles vão corrigir para futuras versões do Chrome.

Uma alternativa até que o Google Chrome pare de filtrar o envio de formulário com HTML é usar o cabeçalho X-XSS-Protection. Você pode definir esse cabeçalho antes de enviar a página HTML atual para o navegador em PHP assim:

Header('X-XSS-Protection: 0');

Tenha em mente que a proteção XSS é uma coisa boa quando funciona e não bloqueia HTML inofensivo. Portanto, é recomendável que você use esse cabeçalho apenas enquanto o Chrome estiver bloqueando o envio de HTML nas versões atuais.

Tornar mais seguro por filtragem de HTML prejudicial no lado do servidor usando PHP

As aplicações seguras devem sempre validar e filtrar HTML inseguro que é recebido no lado do servidor, precisamente para evitar ataques XSS executados por invasores que falsificam envios de formulários.

Uma maneira de filtrar adequadamente é usar um interpretador de HTML completo que irá descartar HTML malformado e filtrar JavaScript inseguro. Essa é uma das capacidades do pacote Secure HTML parser and filter.

Este é um interpretador de marcação modular que analisa HTML, ignora tags HTML malformadas e sequências de texto. Ele fornece várias classes de módulos que podem ser encadeadas para executar diferentes operações de filtragem.

Ele usa uma White list para determinar quais atributos de tag HTML e atributos de estilo CSS são seguros. Desta forma, o código JavaScript e quaisquer atributos tag desconhecidos ou propriedades CSS são ignorados.

O pacote pode reescrever o HTML como resultado da operação de filtragem HTML, como você pode ver usando o script de exemplo a seguir.

$html = 'some HTML code here';

$filter = new markup_filter_safe_html_class;

/* Add here the proprietary CSS properties that you know that are 
 * safe to allow.
 */
$filter->safe_proprietary_css_properties = array(
    '-moz-border-radius'=>array(),
    '-moz-border-radius-topleft'=>array(),
    '-moz-border-radius-topright'=>array(),
    '-moz-border-radius-bottomleft'=>array(),
    '-moz-border-radius-bottomright'=>array(),
    '-webkit-border-radius'=>array(),
    '-webkit-border-top-left-radius'=>array(),
    '-webkit-border-top-right-radius'=>array(),
    '-webkit-border-bottom-left-radius'=>array(),
    '-webkit-border-bottom-right-radius'=>array(),
);
    
/* Add here the CSS property function names properties that you know
 * that are safe to allow.
 */
$filter->safe_css_property_functions = array(
    'alpha'=>array()
);

$parameters=array(
    'Data'=>$html,
    /* Set to 1 if want to filter HTML that only contains the body
       part of a page */
    'OnlyBody'=>0,
);

if(($success = $filter->StartParsing($parameters)))
{
    $output = '';
    do
    {
        if(!($success = $filter->Parse($end, $elements)))
            break;
        $te = count($elements);
        for($e = 0; $e < $te; ++$e)
        {
            if(!($success = $filter->RewriteElement( $elements[$e], $markup)))
                break;
            $output.= $markup;
        }
    }
    while(!$end);
    if($success)
        $success = $filter->FinishParsing();
    if($success)
        echo $output;
}

Faça o download do pacote PHP Secure HTML parser and filter

Você pode fazer o download e instalar o arquivo ZIP do pacote Secure HTML parser and filter ou instalá-lo usando a ferramenta composer PHP usando as instruções da página de download do pacote.

Se você gostou deste artigo, compartilhe-o com seus amigos. Se você tiver dúvidas ou observações, poste um comentário abaixo.

 

***

Manuel Lemos faz parte do time de colunistas internacionais do iMasters. A tradução do artigo é feita pela Redação iMasters, com autorização do autor, e você pode acompanhar o artigo em inglês no link: https://www.phpclasses.org/blog/package/5614/post/1-How-to-Handle-Chrome-HTML-Editor-Form-Submission-Block-Due-to-Bogus-XSS-Detection-Causing-ERRBLOCKEDBYXSSAUDITOR-Error.html