Usando o HTML Purifier em um site com apenas input de texto simples

Eu apreciaria uma resposta para resolver um desacordo entre mim e alguns colegas de trabalho.

Temos uma aplicação web típica PHP / LAMP.

A única input que queremos dos usuários é texto simples. Não convidamos ou queremos que os usuários entrem em HTML em qualquer ponto. Os elementos do formulário são principalmente tags de texto de input básicas. Pode haver algumas áreas de texto, checkboxs de seleção etc.

Atualmente, não há desinfecção de saída para páginas. Todo o conteúdo dynamic, alguns dos quais provenientes da input do usuário, é simplesmente ecoado para a página. Obviamente, precisamos garantir a segurança.

Minha solução é usar htmlspecialchars em todas as saídas no momento em que é ecoado na página.

A solução de meus colegas de trabalho é adicionar HTML Purifier à camada de database. Eles querem passar todas as inputs introduzidas pelo usuário através do Purificador HTML antes de serem salvas no database. Aparentemente, eles o usaram assim em outros projetos, mas acho que é um mal entendido sobre o que é o Purificador de HTML.

O meu entendimento é que só faz sentido usar o HTML Purifier em um site que permite ao usuário inserir HTML. É preciso HTML e torna mais seguro e limpo com base em uma lista branca e outras regras.

Quem está certo e quem está errado?

Há também todo o problema “escape na input ou saída”, mas acho que é um debate para outro horário e lugar.

obrigado

Como regra geral, o escape deve ser feito para o contexto e para o caso de uso.

Se o que você quer fazer é produzir texto sem formatação em um contexto HTML (e você faz), então você precisa usar funcionalidades de escape que garantam que você sempre emitirá texto sem formatação em um contexto HTML. Dado o PHP básico, isso seria realmente htmlspecialchars($yourString, ENT_QUOTES, 'yourEncoding'); .

Se o que você quer fazer é produzir HTML em um contexto HTML (você não), então você gostaria de salientar o HTML quando você o emitiu para evitar que ele cause dano – aqui você usaria $purifier->purify($yourString); na saída.

Se você quiser armazenar input de usuário de texto simples em um database (novamente, você faz) executando instruções SQL, então você deve usar declarações preparadas para evitar a injeção de SQL ou uma function de escape específica para seu database, como mysql_real_escape_string($yourString) .

Você não deve:

  • escape para HTML quando você está colocando dados no database
  • desinfetar como HTML quando você está colocando dados no database
  • desinfecte como HTML quando você está enviando dados como texto simples

Destes, todos são totalmente prejudiciais, embora em graus diferentes. Observe que o seguinte pressupõe que o database é o seu meio de armazenamento único ou canônico para os dados (também pressupõe que você tenha uma injeção de SQL de alguma outra forma – se você não fizer isso, esse será seu principal problema):

  • Se você escaping para HTML quando coloca os dados no database, você confia na garantia de que você estará sempre enviando os dados para um contexto HTML; de repente, se você quiser simplesmente colocá-lo em um arquivo de texto claro para imprimir como está, você precisa decodificar os dados antes de emiti-lo.
  • Se você sanitize como HTML quando coloca os dados no database, você está destruindo informações que o usuário colocou lá. É um sistema de mensagens e seu usuário queria dizer a alguém sobre tags ? Seu usuário não pode fazer isso - você vai destruir essa parte de sua mensagem!

Sanitizar como HTML quando você está enviando dados como texto sem formatação (sem também escaping) pode ter resultados confusos e quebrando a página se você não definir seu módulo de desinfecção para tirar todo o HTML (o que você não deveria, desde então, você claramente não quer emitir HTML).

Você desinfetou um contexto

, mas está colocando seus dados em um elemento inline? Seu usuário pode colocar um

em seu elemento inline, forçando uma quebra de layout no layout da página (como isso é irritante, depende do seu layout) ou para influenciar a percepção do usuário sobre metadados (por exemplo, para facilitar o phishing), por exemplo, como esta:

  • Nome: John Doe
    (Administrador do site)

Você desinfetou um contexto ? O usuário pode usar outras tags para influenciar a percepção do usuário sobre os metadados, por exemplo, assim:

  • Nome: John Doe (este usuário é um administrador)

Pior cenário: você sanificou seu HTML com uma versão do HTML Purifier que, mais tarde, revela um bug que permite que um certo tipo de HTML malicioso sobreviva? Agora você está enviando dados não confiáveis ​​e colocando em risco os usuários que visualizam esses dados em sua página da Web.

Sanitizar como HTML e escaping para HTML (naquela ordem!) Não tem esse problema, mas significa que o passo de desinfecção é desnecessário, o que significa que esta conscanvasção só irá custar-lhe desempenho. (É por isso que o seu colega queria fazer a sanitização ao salvar os dados, não ao exibi-lo - presumivelmente seu caso de uso (como a maioria) exibirá os dados com mais freqüência do que os dados serão enviados, o que significa que você evitaria ter que lidar com o desempenho atingido com frequência.)

tl dr dr

Sanitizar como HTML quando você está exibindo como texto simples não é uma boa idéia.

Escape / sanitização para uso e contexto.

Na sua situação, você deseja escaping do texto simples para um contexto HTML (= use htmlspecialchars() ).