55 votes

Prévention des attaques CSRF, XSS et SQL Injection dans JSF

J'ai une application web construite sur JSF avec MySQL comme base de données. J'ai déjà implémenté le code pour empêcher CSRF dans mon application.

Maintenant, puisque mon cadre sous-jacent est JSF, je suppose que je n'ai pas à gérer l'attaque XSS, car elle est déjà gérée par UIComponent . Je n'utilise aucun JavaScript dans aucune des pages d'affichage. Même si j'en utilise, dois-je vraiment mettre en place un code pour prévenir les attaques XSS ?

Pour la base de données, nous utilisons des instructions préparées et des procédures stockées dans toutes les interactions avec la base de données.

Y a-t-il autre chose à faire pour prévenir ces 3 attaques courantes ? J'ai déjà parcouru les OWASP et leur antisèches .

Dois-je m'occuper d'autres vecteurs d'attaque potentiels ?

118voto

BalusC Points 498232

XSS

JSF est conçu pour avoir une prévention XSS intégrée. Vous pouvez réafficher en toute sécurité tous entrée contrôlée par l'utilisateur (en-têtes de demande (y compris les cookies !), paramètres de demande (également ceux qui sont enregistrés dans la base de données !) et corps de demande (fichiers texte téléchargés, etc.)) en utilisant n'importe quel composant JSF.

<h:outputText value="#{user.name}" />
<h:outputText value="#{user.name}" escape="true" />
<h:inputText value="#{user.name}" />
etc...

Notez que si vous utilisez JSF 2.0 sur Facelets, vous pouvez utiliser EL dans le texte du modèle comme suit :

<p>Welcome, #{user.name}</p>

Ceci sera aussi implicitement échappé. Vous n'avez pas nécessairement besoin de <h:outputText> ici.

Seulement quand vous êtes explicitement Décomposition de l'entrée contrôlée par l'utilisateur en utilisant escape="false" :

<h:outputText value="#{user.name}" escape="false" />

alors vous avez un trou potentiel d'attaque XSS !

Si vous souhaitez réafficher les entrées contrôlées par l'utilisateur sous forme de HTML, et si vous souhaitez n'autoriser qu'un sous-ensemble spécifique de balises HTML telles que <b> , <i> , <u> etc., alors vous devez assainir l'entrée par une liste blanche. L'analyseur HTML Jsoup est très utile dans ce.

itemLabelEscaped bogue dans Mojarra < 2.2.6

Anciennes versions de Mojarra avant 2.2.6 avait le bug dans lequel <f:selectItems itemLabel> rend de manière incorrecte le libellé non encodé lorsqu'il est fourni avec un fichier List<T> via <f:selectItems var> au lieu de List<SelectItem> o SelectItem[] comme valeur ( numéro 3143 ). En d'autres termes, si vous réaffichez des données contrôlées par l'utilisateur sous la forme d'étiquettes d'éléments via un fichier de type List<T> alors vous avez une faille XSS potentielle. Si la mise à jour vers au moins Mojarra 2.2.6 n'est pas une option, alors vous devez explicitement configurer itemLabelEscaped à l'attribut true pour empêcher cela.

<f:selectItems value="#{bean.entities}" var="entity" itemValue="#{entity}"
    itemLabel="#{entity.someUserControlledProperty}" itemLabelEscaped="true" />

CSRF

JSF 2.x dispose déjà d'une prévention CSRF intégrée dans la saveur de javax.faces.ViewState champ caché dans le formulaire lors de l'utilisation de l'enregistrement de l'état côté serveur. Dans JSF 1.x, cette valeur était plutôt faible et trop facilement prévisible (elle n'a jamais été conçue comme une prévention CSRF). Dans JSF 2.0, cela a été amélioré en utilisant une valeur autogénérée longue et forte au lieu d'une valeur de séquence plutôt prévisible, ce qui en fait une prévention CSRF robuste.

Dans JSF 2.2, cette fonction est encore améliorée en en faisant une partie obligatoire de la spécification JSF, avec une clé AES configurable pour chiffrer l'état du côté client, au cas où la sauvegarde de l'état du côté client est activée. Voir aussi Question de la spécification JSF 869 y Réutilisation de la valeur ViewState dans une autre session (CSRF) . La nouveauté de JSF 2.2 est la protection CSRF sur les demandes GET en <protected-views> .

Seulement quand vous utilisez des vues sans état comme dans <f:view transient="true"> ou s'il y a un trou d'attaque XSS dans l'application, il y a un trou d'attaque CSRF potentiel.


Injection SQL

Ce n'est pas la responsabilité de JSF. La façon d'éviter cela dépend de l'API de persistance que vous utilisez (JDBC brut, JPA moderne ou le bon vieux Hibernate), mais tout se résume à ce qui suit jamais concaténer les entrées contrôlées par l'utilisateur en chaînes SQL comme suit

String sql = "SELECT * FROM user WHERE username = '" + username + "' AND password = md5(" + password + ")";
String jpql = "SELECT u FROM User u WHERE u.username = '" + username + "' AND u.password = md5('" + password + "')";

Imaginez ce qui se passerait si l'utilisateur final choisissait le nom suivant :

x'; DROP TABLE user; --

Vous devez toujours utiliser des requêtes paramétrées, le cas échéant.

String sql = "SELECT * FROM user WHERE username = ? AND password = md5(?)";
String jpql = "SELECT u FROM User u WHERE u.username = ?1 AND u.password = md5(?2)";

En JDBC classique, vous devez utiliser PreparedStatement pour remplir les valeurs des paramètres et dans JPA (et Hibernate), l'élément Query offre également des paramètres pour cela.

5 votes

J'ajouterais que contrairement à ce que l'on croit, l'utilisation des procédures stockées ne no vous protège automatiquement des attaques par injection SQL : J'ai vu des procédures stockées créer des instructions SQL par concaténation et que es également vulnérables à l'injection SQL ! De la même manière, l'utilisation de PreparedStatements ne vous protège pas automatiquement des attaques par injection SQL, si vous les utilisez mal !

1 votes

@BalusC Eh bien je ne peux pas vous remercier assez pour cette explication géniale..Mais j'ai quelques doutes. Dans mon GUI, j'utilise <h:outputText value="#{user.name}" escape="false" /> pour l'affichage sur le GUI..Maintenant, c'est une attaque XSS potentielle.comment puis-je l'éviter. ??. Deuxièmement, j'utilise toujours JSF 1.2 et donc comment puis-je gérer CSRF alors ? j'ai utilisé l'outil WebScrarab pour intercepter la demande Http et modifier la valeur et il a en effet réussi.cela signifie-t-il que l'application est sujette à l'attaque.comment puis-je l'éviter. J'ai déjà traité l'injection SQL. La seule chose qui me préoccupe est le XSS et le CSRF à l'heure actuelle.

0 votes

@BalusC L'explication fournie par Samuel me suggère également de jeter un coup d'oeil sur le modèle de fermeture pour l'assainissement de l'entrée HTML. Mais j'ai entendu dire que le modèle de fermeture a de sérieux problèmes de performance et de plus, il provient des laboratoires de Google, donc il est presque en version bêta et n'est donc pas stable... Lequel recommanderiez-vous pour la santialisation HTMl... Jsoup ou Closure... Je suis absolument nouveau dans cette santialisation et ce parsing et donc je préférerais quelque chose qui est facile à apprendre et à mettre en œuvre.

8voto

Mike Samuel Points 54712

Je n'utilise aucun JavaScript dans aucune des pages d'affichage. Même si j'en utilise, ai-je vraiment besoin de mettre en place un code pour contourner l'attaque XSS ?

Vous pouvez être vulnérable au XSS même si vous n'utilisez pas de JavaScript dans vos pages. Le XSS se produit lorsque vous incorporez du contenu contrôlé par un attaquant sans le coder correctement.

Chaque fois que vous faites quelque chose comme

response.write("<b>" + x + "</b>")

où un attaquant peut causer x pour contenir du HTML qui contient du JavaScript, alors vous êtes vulnérable au XSS.

La solution n'est généralement pas d'écrire de grandes quantités de code. En général, la solution consiste à coder $x et toute autre valeur contrôlée par un attaquant avant de les inclure dans le HTML que vous générez.

response.write("<b>" + escapePlainTextToHtml(x) + "</b>")

Le filtrage ou l'aseptisation des entrées peut contribuer à fournir une couche de protection supplémentaire.

<shameless-plug>

Vous pouvez également utiliser un langage de modèle qui encode automatiquement la sortie afin de vous protéger contre les XSS.

Modèle de fermeture est l'une de ces options pour Java.

L'auto-scaping contextuel fonctionne en augmentant les modèles de fermeture pour coder correctement chaque valeur dynamique en fonction du contexte dans lequel elle apparaît, ce qui permet de se défendre contre les vulnérabilités XSS dans les valeurs qui sont contrôlées par un attaquant.

EDIT

Puisque vous utilisez JSF, vous devriez vous documenter sur Atténuation de XSS dans JSF :

Échapper au texte de sortie

<h:outputText/> y <h:outputLabel/> a par défaut l'attribut escape défini sur True. En utilisant cette balise pour afficher les sorties, vous êtes en mesure d'atténuer la majorité de la vulnérabilité XSS.

SeamTextParser et <s:formattedText/>

Si vous souhaitez permettre aux utilisateurs d'utiliser certaines des balises html de base pour personnaliser leurs entrées, JBoss Seam propose une fonction <s:formattedText/> qui autorise certaines balises html de base et des styles spécifiés par les utilisateurs.

0 votes

@ankit, y a-t-il une phrase particulière que vous trouvez déroutante ?

0 votes

Le problème est que j'utilise JSF et je suppose que, comme les autres frameworks, il génère automatiquement du HTML... Je ne comprends donc toujours pas ce que vous avez écrit... J'ai également parcouru le modèle de fermeture... C'est tellement nouveau pour moi...

1 votes

Si j'ai bien compris, si j'autorise l'utilisateur à entrer des balises HTML dans mon interface graphique, je dois utiliser le modèle de fermeture pour m'assurer que toutes les balises sont valides et que toutes ne le sont pas... Veuillez me corriger si je me trompe.

1voto

Michał Stochmal Points 1185

Lorsque vous utilisez <h:outputText escape="false"> avec des valeurs non encodées (provenant par exemple d'éditeurs de texte html), vous vous exposez à de vilaines attaques XSS. Dans de tels cas, j'utilise un convertisseur JSF qui utilise Jsoup pour supprimer le javascript du texte en laissant le HTML intact. Le convertisseur peut aussi être utilisé pour assainir les entrées de l'utilisateur. Vous pouvez l'utiliser comme ceci :

<h:outputText value="{bean.value}" escape="false" converter="htmlSanitizingConverter"/>

Et le convertisseur lui-même :

/**
 * Prevents from XSS attack if output text is not escaped.
 */
@FacesConverter("htmlSanitizingConverter")
public class HtmlSanitizingConverter implements Converter {

    private static final Whitelist JSOUP_WHITELIST = Whitelist.relaxed()
            .preserveRelativeLinks(true)
            .addAttributes(":all","style");
            /*
             Optionally - add support for hyperlinks and base64 encoded images.
            .addTags("img")
            .addAttributes("img", "height", "src", "width")
            .addAttributes("a", "href")
            .addProtocols("img", "src", "http", "https", "data");
            */

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String submittedValue) {
        return (submittedValue != null) ? Jsoup.clean(submittedValue, JSOUP_WHITELIST) : null;
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {
        return (value != null) ? Jsoup.clean(value.toString(), JSOUP_WHITELIST) : "";
    }

}

Note : Lorsque vous utilisez JSF avec PrimeFaces, prenez garde à l'utilisation de <p:textEditor> - versions antérieures (avant la version 6.2) ne vérifiait pas par défaut les entrées des utilisateurs.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X