O mundo era um lugar muito mais simples de se viver. Designers e desenvolvedores podiam integrar conteúdos de diferentes sites sempre que quiserem. Bastava um IFRAME e pronto. A imaginação era o limite.
Eram bons tempos. Todos viviam felizes e em paz, numa grande aldeia global onde todos eram irmãos e compartilhavam livremente seus sites.
Foi quando surgiu o clickjacking. O mundo como conhecíamos deixou de existir e a livre coexistência passou a ser uma lembrança distante…
ABADE, Igor. “Lendas Antigas da Teia Mundial”
Brincadeiras à parte, uma coisa é fato: Clickjacking mudou para sempre o comportamento da tag IFRAME nas páginas HTML. Explicando: A motivação deste post veio de uma thread de emails na lista do time de produto do VSTS. Lá, alguém perguntou o seguinte:
We make use of Jenkins to schedule various test executions. Today, I was thinking I could simply create a custom hub that would host the Jenkins site within an IFRAME within the Test hub in our VSTS account. However, quickly testing this idea out seems to show that I can’t do that. Possibly due to some CORS limitations?
Is it possible to host an IFRAME in a custom hub in VSTS showing content from outside the VSTS account? If so, does someone have an example?
Em outras palavras: Teria algum jeito de hospedar uma página externa (neste caso, uma página do Jenkins) dentro do VSTS? Dá para imaginar um monte de cenários onde isso seria útil: Mostrar builds do Jenkins, análises de código do Sonar, documentação do SharePoint… Tudo direto na interface Web do VSTS.
Legal, né? Só tem um probleminha:
Current versions of Jenkins have the X-Frame-Options headers set to disallow IFraming the Jenkins site for security reasons (…)
Sites don’t allow iframing because you can use that for clickjacking.
Hein? Quer dizer que sites não permitem mais que se faça uso de IFRAME? Tudo por causa do tal do clickjacking?
Clickjacking
Clickjacking é uma técnica usada por sites maliciosos para enganar usuários e força-los a clicar em páginas que eles não queriam. É como se o malfeitor estivesse “sequestrando” os cliques do usuários, redirecionando-os de um site legítimo para outro malicioso. Daí o nome (“click hijacking”).
Vários sites foram vítimas de clickjacking no passado, como Twitter e Facebook. Até mesmo o Flash Player passou por maus bocados por uso de técnicas de clickjacking.
Como o ataque se baseia no uso de um IFRAME transparente contendo uma página de um site legítimo, era preciso que esses mesmos sites pudessem pedir aos browsers para que não fossem abertos dentro de um IFRAME. Dessa maneira – impedindo a abertura da página num IFRAME – estariam protegidos contra esse tipo de ataque. Surgiu então o cabeçalho HTTP X-Frame-Options.
Se você quiser impedir que seu site seja aberto em um IFRAME por um outro site qualquer (inclusive sites seus, que estejam no mesmo domínio), deve adicionar o seguinte cabeçalho
X-Frame-Options: DENY
Um meio-termo – liberar o uso de IFRAME entre páginas do seu site, mas sem permitir o uso externo – pode ser obtido assim:
X-Frame-Options: SAMEORIGIN
Por fim, você pode liberar o uso de IFRAME para um site específico. Ou seja, se você quiser que um site externo fictício www.abc.com possa usar um IFRAME para exibir uma página vinda do seu site, você colocaria em seu site o cabeçalho:
X-Frame-Options: ALLOW-FROM: http://www.abc.com
Quer ver como funciona? Então crie uma página HTML com o código abaixo.
<html> <body> <iframe src="https://www.google.com" width="800" height="800"></iframe> </body> </html>
Agora abra-a e veja o que acontece:
Ou seja: Se você quer embutir uma página vinda de algum site ou serviço que limita o iframing através da tag X-Frame-Options, então é no dice. Não vai funcionar.
Opções?
Se ainda assim você quiser, como no nosso exemplo, usar IFRAME para criar um widget para o TFS que exiba uma página do Jenkins, tem duas opções:
Remover cabeçalho X-Frame-Options
Esta é a solução mais óbvia, mas também a mais complicada. Isso porque ela, tipicamente, envolve a alteração do código-fonte da aplicação original ou, ao menos, algum ajuste no servidor Web (Apache ou IIS) que está servindo a aplicação.
CORS e jQuery
Uma outra alternativa é: ao invés de um IFRAME puro e simples, é usar o método Load() do jQuery. Entretanto, para carregar uma página hospedada em outro site, é preciso primeiramente configurar as permissões de CORS – que vêm com sua própria cota de complicação.
Conclusão
A verdade é que não tem solução fácil. O risco de clickjacking tornou o uso de IFRAME algo excessivamente complicado e que tende a cair cada vez mais em desuso.
E você, caro leitor? Já se deparou com esse tipo de situação? Tem alguma ideia/sugestão de como lidar com isso? Deixe seu comentário!
Um abraço,
Igor
(Cross-post de http://www.tshooter.com.br/2016/08/18/sobre-iframe-e-clickjacking/)
Igor Abade
Igor Abade V. Leite ([email protected]) é Microsoft MVP (Most Valuable Professional) de Visual Studio ALM desde 2006. Palestrante em diversos eventos da comunidade de desenvolvimento de software (TechEd Brasil, The Developers’ Conference, DevOps Summit Brasil, Agile Brazil, Visual Studio Summit, QCON e outros), é também autor de artigos em revistas e sites como o MSDN Brasil. Desde março de 2011 é um dos sócios da Lambda3, uma consultoria especializada em ALM, desenvolvimento de software e treinamentos. Siga-o no Twitter @igorabade.