Validação segura de URLs em JavaScript
Mannan Tirmizi
9 de maio de 2023
0 minutos de leituraNota do editor: 9 de maio de 2023
Esta publicação, originalmente publicada em 18 de outubro de 2022, foi atualizada para mostrar como a Snyk pode ajudar você a implementar uma validação segura de URLs em JavaScript.
Quando precisamos lidar com URLs de diferentes formas e para diferentes finalidades — como navegar pelo histórico do navegador, acessar destinos com âncoras, usar parâmetros de consulta e muito mais —, costumamos recorrer ao JavaScript. No entanto, seu uso frequente incentiva invasores a explorar suas vulnerabilidades. Esse risco torna essencial implementar a validação de URLs em nossas aplicações JavaScript.
A validação de URLs verifica se elas seguem a sintaxe adequada — a estrutura que toda URL deve ter. Ela pode proteger nossas aplicações contra vulnerabilidades baseadas em URLs, como a injeção de scripts maliciosos e a falsificação de solicitações do lado do servidor (SSRF). Agentes maliciosos podem realizar ataques de SSRF quando não aplicamos boas práticas de programação segura para validar URLs fornecidas por usuários ao buscar um recurso remoto. A SSRF continua sendo uma ameaça crítica para aplicações baseadas em JavaScript, tanto no frontend quanto em aplicações Node.js do lado do servidor, e foi uma categoria em destaque na lista OWASP Top 10 de 2021.
Validação de URLs
A validação de URLs reforça a segurança contra possíveis explorações e elimina a chance de ocorrerem bugs durante a execução do código. Mas quando devemos validar URLs e o que precisamos verificar nesse processo? Devemos implementar a validação de URLs em todos os softwares que precisam identificar e verificar recursos, como páginas, imagens, GIFs e vídeos.
Uma URL típica é composta por vários elementos, como protocolo, nome de domínio, hostname, nome do recurso, origem, porta e outros. Eles informam ao navegador como buscar determinado recurso. Podemos usá-los para validar URLs de várias maneiras:
Usando literais e construtores de regex
Construtores de URL
Método
isValidURLElementos de entrada
Método da tag âncora
Um processo típico de validação de URLs recebe dados de um usuário e os analisa para identificar seus diversos componentes. Esse processo pode garantir que todos os componentes da URL estejam em conformidade com os padrões da internet. Por exemplo, se necessário, ele pode verificar se a URL usa um protocolo seguro.
A validação do hostname começa dividindo-o em rótulos separados para garantir que estejam em conformidade com a especificação de nomes de domínio de nível superior. Um hostname típico tem pelo menos dois rótulos separados por pontos. Por exemplo, www.snyk.com tem os rótulos “www”, “snyk” e “com”. Cada rótulo pode conter apenas caracteres alfanuméricos ou hífens, sem distinção entre maiúsculas e minúsculas. Em seguida, o processo de validação pode verificar se o hostname corresponde a uma lista de permissões de URLs, garantindo que apenas as URLs designadas sejam aceitas e que URLs permitidas não sejam rejeitadas por engano.
Por padrão, a maioria dos caminhos para recursos usados em URLs é permitida. No entanto, as portas só podem estar no intervalo de 1 a 65536. Valores fora desse intervalo devem gerar um erro. Também podemos verificar endereços IP numéricos para determinar se são IPv4 ou IPv6.
Por fim, embora isso não seja óbvio à primeira vista, também podemos verificar se as URLs contêm nomes de usuário e senhas. Esse recurso ajuda a cumprir as políticas da empresa e proteger as credenciais.
Agora que você conhece o básico, vamos ver como validar URLs usando JavaScript!
Como validar URLs em JavaScript
A maneira mais fácil de validar URLs em JavaScript é usar a função construtora new URL. Além de simples, ela é compatível com o runtime Node.js e com a maioria dos navegadores.
A sintaxe básica é a seguinte:
O JavaScript só exige o elemento base se fornecermos uma URL relativa. Se não fornecermos uma, o valor padrão será undefined. Como alternativa, se fornecermos um elemento base com uma URL absoluta, o JavaScript ignorará o elemento base.
Para validar a URL, podemos usar a seguinte função:
Essa função verifica se uma URL é válida: retorna true quando ela é válida e false quando não é. Se você passar www.urlcheck.com para a função, ela retornará false porque o endereço não contém um esquema de URL válido. A versão correta é https://urlcheck.com. Outro exemplo é mailto:John.Doe@example.com. Essa é uma URL válida, mas, se você remover os dois-pontos, o JavaScript deixará de reconhecê-la como URL. Um terceiro exemplo é ftp://. Esse endereço não é válido porque não contém um hostname. Se você adicionar dois pontos (..), ele se tornará válido, pois os pontos serão considerados um hostname. Assim, ftp://.. passa a ser uma URL válida.
É importante lembrar que existem URLs fora do convencional, mas perfeitamente válidas! Elas podem surpreender os desenvolvedores que trabalham com elas, mas ainda assim são totalmente válidas. Por exemplo, as duas URLs a seguir retornarão TRUE:
new URL("youtube://a.b.c.d");
new URL ("a://1.2.3.4@1.2.3.4");
Esses exemplos mostram que os desenvolvedores devem se basear nos princípios de validação de URLs, em vez de se concentrar nas convenções.
Para garantir que a URL válida use um esquema específico, você pode usar a seguinte função:
Essa função valida a URL e, em seguida, verifica se ela usa os esquemas HTTP ou HTTPS. Nesse caso, ftp://.. será inválida porque não contém HTTP nem HTTPS, enquanto http://.. continuará válida. Outras maneiras de usar a função construtora URL incluem:
O exemplo acima usa o elemento base. Ao registrar o valor no log, obtemos https://snyk.io/.
Para retornar um objeto URL sem especificar o parâmetro base, use esta sintaxe:
Para adicionar um caminho ao host, estruturamos a URL da seguinte forma:
A URL armazenada em d é https://snyk.io/en-US/docs.
Outra funcionalidade do módulo URL é implementar a API de URL WHATWG, que segue o padrão de URL WHATWG usado pelos navegadores:
No exemplo acima, criamos um objeto URL chamado adr. Em seguida, o código obteve o host e o caminho da URL — respectivamente, snyk.io e /en-US/docs. Por fim, podemos comparar a URL com uma lista de permissões ou de bloqueio para garantir que apenas as URLs designadas sejam aceitas e que URLs permitidas não sejam rejeitadas por engano.
Como validar uma URL usando regex — embora você não deva
Outra forma de validar uma URL é usar uma expressão regular (regex), ou seja, uma sequência de caracteres que define um padrão de busca. Podemos usar regex para verificar se uma URL é válida.
A sintaxe JavaScript para validar URLs usando regex é:
Para testar algumas URLs:
A sintaxe de URL definida pela regex verifica se o endereço começa com os esquemas http:// ou https://, ou com um subdomínio, e se contém um nome de domínio. A instrução no console retorna true porque segue a sintaxe de URL definida pela regex. Em contrapartida, a instrução a seguir retornará false, pois não começa com nenhum dos esquemas permitidos nem com um subdomínio, e também não contém um nome de domínio:
A regex acima é relativamente simples, mas ainda assim difícil de entender. Ela também é uma abordagem propensa a erros, pois uma regex não consegue lidar adequadamente com as regras de validação de URLs. No máximo, ela consegue corresponder a URLs válidas. Além disso, a validação pode levar muito tempo quando a expressão regular contém uma lógica complexa ou recebe uma string de entrada extensa.
Para cumprir as verificações de validação definidas pela regex, o navegador precisa retroceder milhões de vezes ao percorrer a string de entrada. Esse processo pode causar “retrocesso catastrófico”, um fenômeno em que expressões regulares complexas podem travar o navegador ou consumir ao máximo os processos do núcleo da CPU.
A Snyk detecta pacotes de código aberto vulneráveis
É provável que os responsáveis pela manutenção também cometam erros na validação de URLs, colocando aplicações Node.js em risco. O pacote npm keycloak-connect é um exemplo: o projeto recebe mais de 50 mil downloads por semana, mas, em março de 2023, foi divulgada uma falha na validação segura de URLs que permitia uma vulnerabilidade de redirecionamento aberto via CVE-2023-2237.
Recomendamos que você analise seus projetos gratuitamente com a Snyk para encontrar dependências de código aberto vulneráveis e corrigi-las.

As 10 principais vulnerabilidades de JavaScript identificadas pela Snyk
Este guia detalhado explora as vulnerabilidades críticas e de alta gravidade mais comuns em projetos de código aberto, encontradas pelas análises da Snyk em aplicativos JavaScript em 2022.
Vulnerabilidades reais e como resolvê-las
Node.js é um ambiente de execução JavaScript gratuito, de código aberto e multiplataforma que usa um gerenciador de pacotes chamado Node Package Manager (npm).
Um incidente semelhante ocorreu em 2019, quando um invasor conseguiu, por conta própria, acessar sem autorização dados da Capital One, um dos maiores bancos dos Estados Unidos. Essa violação de dados continua sendo uma das mais significativas do século. Segundo o The New York Times, o invasor obteve acesso a registros de 100 milhões de clientes, 140 mil números de Social Security e 80 mil dados bancários vinculados a clientes da Capital One.
O invasor acessou o servidor da Capital One hospedado na Amazon Web Services (AWS). A demora na detecção indica que ele conhecia profundamente a infraestrutura da AWS e identificou uma vulnerabilidade explorável no firewall de aplicações web (WAF) do provedor de serviços de segurança gerenciada (MODSEC). Com esse conhecimento, o invasor realizou o ataque de SSRF e fez novas solicitações HTTP ao manipular o servidor web vulnerável, conseguindo acessar o serviço de metadados da AWS.
Dependendo dos requisitos da empresa, podemos evitar ataques de SSRF restringindo o sistema a apenas alguns protocolos, como HTTP ou HTTPS. Para reforçar a segurança, precisamos configurar a aplicação para que ela não aceite parâmetros de URL sem supervisão. Normalmente, usamos listas de permissões e de bloqueio para filtrar e controlar esse mecanismo, reduzindo significativamente a probabilidade de SSRF. As listas de permissões permitem que a aplicação use um conjunto predefinido de objetos e servidores. Já as listas de bloqueio impedem que ela acesse hostnames geralmente disponíveis.
Como usar JavaScript com segurança
Como mostra a inclusão da SSRF na nova lista OWASP Top 10, a validação de URLs se tornou cada vez mais importante para a segurança de aplicações JavaScript. Felizmente, podemos ajudar a reduzir esse tipo de ataque validando URLs no lado do servidor. Além disso, é altamente recomendável usar a nova função URL e seguir as práticas recomendadas para validar e manipular URLs.
Depois de ver alguns exemplos do que a nova função URL pode fazer, aprendemos a validar URLs com regex e vimos por que essa abordagem é trabalhosa e propensa a erros. Por fim, analisamos um caso de vulnerabilidade de SSRF em JavaScript.
Os riscos de segurança relacionados a URLs têm menos a ver com sua validade e mais com esquemas perigosos. Por isso, precisamos garantir que a validação seja feita pela aplicação no lado do servidor. Um invasor pode contornar o mecanismo de validação no lado do cliente, então não é recomendável depender apenas dele.
Para saber mais sobre como gerenciar a segurança das suas aplicações e sobre o produto da Snyk, acesse Snyk hoje mesmo.
Snyk para a segurança de JavaScript
Da primeira linha de código à última dependência npm, a Snyk mantém seus aplicativos JavaScript seguros diretamente no IDE, na CLI e nos fluxos de trabalho do Git.



