Pergunta

Nós temos uma aplicação de alta segurança e queremos permitir que os usuários insiram URLs que outros usuários verão.

Isto introduz um alto risco de hacks XSS - um usuário poderia entrar javascript que outro usuário acaba execução. Desde que armazenar dados sensíveis é essencial que isso nunca acontece.

O que são as melhores práticas para lidar com isso? É por si só qualquer segurança whitelist ou padrão de fuga bom o suficiente?

Qualquer conselhos sobre como lidar com redirecionamentos ( "esta ligação vai para fora nosso site" mensagem em uma página de aviso antes de seguir o link, por exemplo)

Existe um argumento para não apoiar ligações entrou usuário em tudo?


Esclarecimento:

Basicamente nossos usuários querem de entrada:

stackoverflow.com

E tem saída para outro usuário:

<a href="http://stackoverflow.com">stackoverflow.com</a>

O que eu realmente se preocupar é los usando isso em um hack XSS. Ou seja, eles entrada:

alert ( 'hackeado!');

Assim outros usuários obter este link:

<a href="alert('hacked!');">stackoverflow.com</a>

Meu exemplo é apenas para explicar o risco - Estou bem ciente de que o Javascript e URLs são coisas diferentes, mas por deixá-los de entrada o último que pode ser capaz de executar o ex

.

Você ficaria surpreso quantos sites você pode romper com esse truque - HTML é ainda pior. Se eles sabem lidar com links que eles também sabem a <iframe> sanitize, <img> e referências inteligentes CSS?

Eu estou trabalhando em um ambiente de alta segurança - um único corte XSS pode resultar em muito elevadas perdas para nós. Estou feliz que eu poderia produzir um Regex (ou usar um dos excelentes sugestões até agora) que poderia excluir tudo o que eu poderia pensar, mas isso seria suficiente?

Foi útil?

Solução

Se você acha que URLs não podem conter código, pense novamente!

https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet

Leia isso, e choram.

Aqui está como o fazemos em Stack Overflow:

/// <summary>
/// returns "safe" URL, stripping anything outside normal charsets for URL
/// </summary>
public static string SanitizeUrl(string url)
{
    return Regex.Replace(url, @"[^-A-Za-z0-9+&@#/%?=~_|!:,.;\(\)]", "");
}

Outras dicas

O processo de renderização de um link "seguro" deve passar por três ou quatro etapas:

  • Unescape / re-codificar a string que você foi dado (RSnake documentou uma série de truques em http://ha.ckers.org/xss.html que o uso escapar e UTF codificações).
  • Limpe o link up: Regexes são um bom começo - certifique-se de cortar a corda ou jogá-lo fora se ele contém um "(ou o que você usa para fechar os atributos em sua saída); Se você está fazendo as ligações apenas como referências a outras informações que você também pode forçar o protocolo no final deste processo - se a parte antes do primeiro cólon não é 'http' ou 'https', em seguida, acrescentar 'http: //'. para o início isso permite que você para criar ligações utilizáveis ??a partir da entrada incompleta como um usuário deve digitar em um navegador e lhe dá uma última chance de tropeçar qualquer que seja o mal que alguém tentou esgueirar-se.
  • Verifique se o resultado é uma URL bem formado. (Protocolo: //host.domain [: port] [/ caminho] [/ [arquivo]] [? QUERYFIELD = QueryValue] [#anchor])
  • verificar Possivelmente o resultado contra uma lista negra site ou tentar buscá-la através de algum tipo de verificador de malware.

Se a segurança é uma prioridade Espero que os usuários se perdoaria um pouco de paranóia neste processo, mesmo que não acabam jogando fora algumas ligações seguras.

Use uma biblioteca, tais como OWASP-ESAPI API:

Leia o seguinte:

Por exemplo:

$url = "http://stackoverflow.com"; // e.g., $_GET["user-homepage"];
$esapi = new ESAPI( "/etc/php5/esapi/ESAPI.xml" ); // Modified copy of ESAPI.xml
$sanitizer = ESAPI::getSanitizer();
$sanitized_url = $sanitizer->getSanitizedURL( "user-homepage", $url );

Outro exemplo é a utilização de uma função built-in. do PHP filter_var função é um exemplo:

$url = "http://stackoverflow.com"; // e.g., $_GET["user-homepage"];
$sanitized_url = filter_var($url, FILTER_SANITIZE_URL);

Usando filter_var permite chamadas javascript , e filtra esquemas que não são nem http nem https . Usando o OWASP ESAPI Sanitizer é provavelmente a melhor opção.

Ainda outro exemplo é o código de WordPress :

Além disso, como não há nenhuma maneira de saber onde as ligações de URL (ou seja, pode ser uma URL válida, mas o conteúdo do URL pode ser travesso), o Google tem uma navegação segura API você pode chamar:

Rolling seu próprio regex para o saneamento é problemático por várias razões:

  • A menos que seja Jon Skeet, o código terá erros.
  • APIs existentes têm muitas horas de revisão e teste atrás deles.
  • existentes APIs URL de validação considerar internacionalização.
  • APIs existentes serão mantidos up-to-date com os padrões emergentes.

Outras questões a considerar:

  • O que esquemas você permitir (são file:/// e telnet:// aceitável)?
  • Quais as restrições que você quer lugar no conteúdo do URL (são URLs de malware aceitável)?

Apenas HTMLEncode as ligações quando você enviá-las. Certifique-se de que você não permitem ligações javascript:. (É melhor ter uma lista branca de protocolos que são aceitos, por exemplo, http, https, e mailto).

Você não especificar o idioma de sua aplicação, então vou presumir ASP.NET, e para isso você pode usar o Microsoft Anti-Cross site Scripting Biblioteca

É muito fácil de usar, tudo que você precisa é de um include e que é ele:)

Quando você estiver sobre o tema, por que não deu uma leitura sobre projeto diretrizes para Secure web Applications

Se qualquer outra língua .... se houver uma biblioteca para ASP.NET, tem de estar disponível, bem como para outro tipo de linguagem (PHP, Python, ROR, etc)

Como cerca de não exibi-los como um link? Basta usar o texto.

Combinado com um aviso para proceder ao seu próprio risco pode ser o suficiente.

além - veja também Devo sanitize HTML marcação para um hospedado CMS? para uma discussão sobre saneantes entrada do usuário

No meu projeto escrito em JavaScript Eu uso essa regex como lista branca:

 url.match(/^((https?|ftp):\/\/|\.{0,2}\/)/)

A única limitação é que você precisa colocar ./ ??na frente para arquivos em mesmo diretório, mas eu acho que eu posso viver com isso.

Para Pythonistas, tente de Scrapy w3lib .

OWASP ESAPI datas pré-Python 2.7 e é arquivado no agora extinta Google Code .

Você pode usar um código hexadecimal para converter todo o URL e enviá-lo para o servidor. Dessa forma, o cliente não entender o conteúdo na primeira vista. Depois de ler o conteúdo, você pode decodificar os = URL de conteúdo? e enviá-lo para o navegador.

Permitir que um URL e permitindo JavaScript são 2 coisas diferentes.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top