jeudi 22 mars 2012

OWASP S12S10 - X-XSS-Protection

A partir d'Internet Explorer 8  Microsoft a introduit une entête supplémentaire dans le but de pouvoir se défendre des failles XSS.
Cet entête est assez ancienne, (2010) mais n'est pas encore interprétée par les différents navigateurs (même si de plus en plus d'applications renvoie cette entête).

WARNING : Néanmoins, cette entête n'est PAS LA SOLUTION pour lutter contre les failles XSS. Il s'agit d'un élément supplémentaire dans votre Défense en profondeur de votre application Web.

L'interprétation d'Internet Explorer de l'entête est la suivante : 

Si la ligne X-XSS-Protection est rencontré, alors le module de filtrage des XSS peut se mettre en oeuvre au sein de Internet Explorer.

Les valeurs possibles sont : 

X-XSS-Protection: 0

Le code Java associé (ajout d'une entête):
response.addHeader("X-XSS-Protection", "0");

Cette valeur ne change rien à la manière dont le navigateur va réagir. La navigateur réagira comme si la ligne d'entête n'existait pas...Elle n'est à utiliser que si vous êtes sur d'avoir sécuriser l'ensemble de vos formulaires contre les XSS. Mais qui peut le dire ? 

X-XSS-Protection: 1
Le code Java associé (ajout d'une entête):
response.addHeader("X-XSS-Protection", "1");

Dans ce cas le navigateur va essayer de limiter l'impact du XSS en modifiant votre contenu affiché en fonction de ce qu'il aura détecté.

X-XSS-Protection: 1; mode=block
Le code Java associé (ajout d'une entête):
response.addHeader("X-XSS-Protection", "1; mode=block");

Le navigateur va alors bloquer le contenu. Il ne l'affichera pas, ni n'essayera de modifier le contenu à afficher. 

Pour mettre en place le nouvel entête, il faut donc ajouter une entête dans votre cote coté Java, et donc faire un




Globalement, ce nouvel-entete peut aider, mais rappeler vous que cela ne solutionne pas tous les cas...Le Filtre XSS implémenté se bipasse, et en plus cela n'est valable actuellement que pour IE > 8

mercredi 21 mars 2012

OWASP S12S05 - GET ou POST ?

Ce post se veut une aide pour déterminer la perte d'informations avérée en fonction du type de méthode d'envoi de données utilisé.

Petit rappel important au sujet de ces deux méthodes : 


Il faut être clair que, si on utilise GET ou POST les données circulent en clair, nous ne sommes pas la pour affirmer autre chose, mais plutôt pour déterminer les risques de fuite d'informations dans les logs serveur, le navigateur (y compris le cache), les proxy (ou tout autre élément sur la ligne entre le navigateur et l'applicatif).

Ces deux méthodes sont définies dans le RFC 2616 de la manière suivante (copier/coller du RFC en italique, explication autrement) :

GET : 


The GET method means retrieve whatever information (in the form of an
   entity) is identified by the Request-URI. If the Request-URI refers
   to a data-producing process, it is the produced data which shall be
   returned as the entity in the response and not the source text of the
   process, unless that text happens to be the output of the process.
Ici les données sont envoyés dans l'URL uniquement.

L'URL n'étant pas limitée d'après le RFC 2616, bien qu'en pratique je n'ai jamais aperçu une URL de 50Ko....

The HTTP protocol does not place any a priori limit on the length of
   a URI. Servers MUST be able to handle the URI of any resource they
   serve, and SHOULD be able to handle URIs of unbounded length if they
   provide GET-based forms that could generate such URIs. A server
   SHOULD return 414 (Request-URI Too Long) status if a URI is longer
   than the server can handle (see section 10.4.15).
      Note: Servers ought to be cautious about depending on URI lengths
      above 255 bytes, because some older client or proxy
      implementations might not properly support these lengths.

POST : 


The POST method is used to request that the origin server accept the
   entity enclosed in the request as a new subordinate of the resource
   identified by the Request-URI in the Request-Line. POST is designed
   to allow a uniform method to cover the following functions:
      - Annotation of existing resources;
      - Posting a message to a bulletin board, newsgroup, mailing list,
        or similar group of articles;
      - Providing a block of data, such as the result of submitting a
        form, to a data-handling process;
      - Extending a database through an append operation.


Ici les données du formulaire sont envoyées dans le corps de la requête après les entêtes. Et donc la limite n'existe pas non plus(cf RFC1867). Par contre ici on rencontre régulièrement des données de plusieurs Ko/Mo...

Donc concernant ces deux méthodes :

  1. En GET toutes les données sont forcément envoyées dans l'URL.
  2. En POST les données sont généralement envoyées en corps de message, mais peuvent aussi être passées dans l'URL


Donc en prenant ces deux méthodes et une combinaison HTTP/HTTPS on peut déterminer les points suivants :

Dans l'historique du  navigateur

  • Utilisation de HTTP + GET => Perte de confidentialité; les arguments apparaissent dans l'URL et donc dans l'historique 
  • Utilisation de HTTPS + GET => Perte de confidentialité; les arguments apparaissent dans l'URL et donc dans l'historique 
  • Utilisation de HTTP + POST + données dans l'URL => Perte de confidentialité; les arguments apparaissent dans l'URL et donc dans l'historique 
  • Utilisation de HTTPS + POST + données dans l'URL => Perte de confidentialité; les arguments apparaissent dans l'URL et donc dans l'historique 
  • Utilisation de HTTP + POST + données dans le corps du message => Pas de perte de confidentialité; il n'apparait que l'URL dans l'historique. 
  • Utilisation de HTTPS + POST + données dans le corps du message => Pas de perte de confidentialité; il n'apparait que l'URL dans l'historique. Cette méthode est malgré tout a préférer à la précédente étant donnée qu'elle chiffre le trafic :)
Dans le cas d'une écoute de trafic (type Homme du milieu) : 


  • Utilisation de HTTP + GET => Perte de confidentialité; les arguments sont lisibles sur le canal
  • Utilisation de HTTPS + GET => Pas de perte de confidentialité; le trafic est entièrement chiffré. 
  • Utilisation de HTTP + POST + données dans l'URL => Perte de confidentialité; les arguments sont lisibles sur le canal
  • Utilisation de HTTPS + POST + données dans l'URL => Pas de perte de confidentialité; le trafic est entièrement chiffré.
  • Utilisation de HTTP + POST + données dans le corps du message => Perte de confidentialité; les arguments sont lisibles sur le canal
  • Utilisation de HTTPS + POST + données dans le corps du message =>  Pas de perte de confidentialité; le trafic est entièrement chiffré.


Dans les logs du serveur (si le pirate réussi à accéder a ceux-ci)

  • Utilisation de HTTP + GET => Perte de confidentialité; les arguments apparaissent dans l'URL et donc dans les logs
  • Utilisation de HTTPS + GET => Perte de confidentialité; les arguments apparaissent dans l'URL et donc dans les logs
  • Utilisation de HTTP + POST + données dans l'URL => Perte de confidentialité; les arguments apparaissent dans l'URL et donc dans les logs
  • Utilisation de HTTPS + POST + données dans l'URL => Perte de confidentialité; les arguments apparaissent dans l'URL et donc dans les logs
  • Utilisation de HTTP + POST + données dans le corps du message => Pas de perte de confidentialité; il n'apparait que l'URL dans les logs.
  • Utilisation de HTTPS + POST + données dans le corps du message => Pas de perte de confidentialité; il n'apparait que l'URL dans les logs. Cette méthode est malgré tout a préférer à la précédente étant donnée qu'elle chiffre le trafic :)

On peut donc dire que la meilleure méthode exposant le moins de données et de perte de confidentialité dans le cas d'une analyse des risques, reste le POST avec les données dans le Corps du message, tout cela étant chiffré en HTTPS....Mais on n'avait pas besoin de toute cette démonstration pour le savoir.

mardi 13 mars 2012

OWASP S12S09 - Forcer le dialogue en SSL/TLS

Actuellement il est intéressant de voir que nous trouvons encore des sites web qui vont chercher des données en HTTP, ces données n'étant pas jugées "critiques", on se dispense d'utiliser TLS/SSL car il parait que ca "charge le réseau et les serveurs"[1]. En Gros cela revient a cela :


1/ Le login se fait en HTTPS super sécurisé (Certificat SSL à 1500€ permettant un chiffrment[2] à 256 bits) comme il le faut
2/ Les images sont chargées en HTTP (et hop, un petit FireSheep par exemple), et on est mal...

Bref, pour éviter cela, il est nécessaire de TOUT charger en HTTPS. Et le navigateur peut nous aider. Il est apparut une norme IETF récemment (en 2011 quand même...) permettant de forcer le navigateur à ne faire qu'un dialogue en SSL. Il s'agit de HTTP Strict Transport Security (HSTS).

Comment cela fonctionne (dans les grosses mailles) :
  1. Le navigateur se rend sur une page en HTTP ou en HTTPS.
  2. L'application serveur renvoie dans les entêtes de retour un ligne propre à HSTS qui spécifie que le site ne doit être uniquement visité en HTTPS dans les 42 prochains jours.
  3. Si le navigateur supporte l'extension HSTS, il n'enverra plus une seule requête HTTP vers le serveur pour les 42 jours a venir
L'implémentation :

Plusieurs solutions sont possibles.


1/ Implémentation via le serveur Web (nous prendrons l'exemple d'Apache avec mod_rewrite) : 

# Mise en place de l'entête
Header always set Strict-Transport-Security "max-age=3628800; includeSubDomains"
 
# Renvoie de toutes les requêtes HTTP en vers de l'HTTPS en ajoutant l'entete
<VirtualHost *:80>
       ServerAlias *
       RewriteEngine On
       RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [redirect=301]
</VirtualHost>
2/ Implémentation via l'application :

/* 
  Gestion via les servlets
   a placer dans votre doGet() ou doPost()
*/
if(request.getScheme().equals("https")) 
  {
    // On est en HTTPS, donc on force l'entête HSTS
    response.setHeader("Strict-Transport-Security", "max-age=3628800; includeSubdomains");
  } else {
    // On est donc dans un autre protocole (a priori HTTP....)
    // On redirige donc vers le serveur HTTPS
    response.setStatus(301);
    String url = "https://" + request.getServerName(); // Renvoie vers le serveur ayant reçu la requête
    // Eventuellement on rajoute ici l'ensemble de l'URL si l'on veut être plus propre coté utilisateur
    // Utilisation des classes et interfaces ad-hoc 
    // Classe : HttpUtils
    // Méthodes : getRequestURL
    response.setHeader("Location", url);
  }

Ici nous définissons à 42 jours la politique HSTS vis a vis du site qui renvoie la page ainsi que pour les sous-domaines.

Les attributs sont les suivants :

max-age :

L'attribut max-age permet de définir le temps maximum (en seconde) ou le navigateur doit utiliser forcément HTTPS. Une valeur à 0 supprime l'effet de HSTS dans le navigateur.

includeSubDomains
Cet attribut est optionnel. Aucune valeur n'est associée à cet attribut, et sa présence permet d'appliquer la même politique HSTS aux sous-domaines du serveur d'ou est envoyer l'entête.

Quelques points importants à savoir 

Reset de max-age  :
A chaque réception du navigateur de cet attribut dans une ligne d'entête HSTS, le navigateur doit changer la politique par la nouvelle valeur reçue et remettre à zéro le compteur de temps
Liste de site HSTS :
Il est possible de demander l'ajout de sites dans une liste pré-établie (a priori uniquement pour Chrome actuellement)

Cette option est supportée par les navigateurs suivants :

  • Firefox à partir de la version 4.0
  • Chrome à partir de la version 4.0.211.0
  • Internet Explorer : a priori non supporté...Quoi qu'il se peut que ca le soit sur IE10 ?
  • Opera : non supporté.
  • Safari : 


L'utilisation de cet élément se doit d'être un complément à l'utilisation de cookies Secure. En effet le navigateur pourrait ne pas implémenter la norme HSTS... Bref, il faut garder a l'esprit le principe de Défense en profondeur.


1 : rigolez pas, un expert réseau d'une grande entreprise d'assurance en 2010, m'a dit cela pour justifier le fait de ne pas mettre de SSL sur un lien ou circulait des données financières...Effectivement le login/passwd était lui envoyer chiffré en TLS/SSL...

2: comme dirait Hervé et Stéphane, on ne dit pas cryptage, mais chiffrement, mais regardez ce qu'ils disent ;)

dimanche 11 mars 2012

OWASP S12S08 - Comment aider le navigateur

Pour lutter contre l'insécurité du Web il est répéter régulièrement de ne pas faire confiance au contenu venant des navigateurs. Mais il n'est jamais dit que le navigateur ne peut être d'une certaine utilité dans cette lutte.

Dans cette lutte implacable, Madame Michu (ou mamie du Cantal[1]) dispose d'un navigateur qu'elle a téléchargée sur Internet, ou qui lui a été livré avec son ordinateur PC ou Mac (il est loin le temps des Kit FAI avec le navigateur moisi fourni[2][3]).

Récemment un certain nombres de fonctionnalités sont apparues (sous forme de draft IETF voir plus) permettant d'améliorer la sécurité globale dans un monde Web.

Voici donc quelques "outils" que vous allez pouvoir utiliser pour "aider" le navigateur et la sécurité de votre application Web :





Avec tous ces éléments il devient vite simple de s'y perdre....Nous allons voir dans les semaines a venir l'utilité de chacun des éléments.

Tout d'abord il est nécessaire de comprendre que l'ensemble de ces éléments est une entête de retour supplémentaire ajoutée par le serveur (votre application). Pour cela il suffit d'ajouter dans votre code les éléments suivants :


response.setHeader("X-Mon-Entete", "lavaleurnecessaire");



C'est aussi simple que cela.





1:Madame michu et mamie du cantal

//Activation syntaxhilight