Vulnérabilités dans le code. Comment différencier un défaut dangereux d'une erreur mineure?

À quoi cela ressemble-t-il généralement de vérifier le code de l'application pour les vulnérabilités? Le spécialiste de la sécurité lance la procédure, le code est scanné et des milliers de vulnérabilités sont découvertes dans l'application. Tout le monde - à la fois le responsable de la sécurité et les développeurs - est choqué. La réaction naturelle du développeur: "Oui, sûrement la moitié sont des faux positifs, et les autres sont des vulnérabilités non critiques!"



En ce qui concerne les faux positifs, tout est simple ici: vous pouvez prendre et regarder directement les endroits du code où des vulnérabilités ont été découvertes avec suspicion de faux positifs. En effet, certains d'entre eux peuvent s'avérer être des faux positifs (mais évidemment pas la moitié du total).



Mais à propos de ce qui est critique et de ce qui ne l'est pas, j'aimerais parler de manière plus substantielle. Si vous comprenez pourquoi il n'est plus possible d'utiliser SHA-1 et pourquoi échapper à ";", peut-être que cet article ne vous ouvrira pas quelque chose de nouveau. Mais si l'analyse résulte des vulnérabilités découvertes éblouissantes, bienvenue sous la coupe - nous vous dirons quels «trous» se trouvent le plus souvent dans les applications mobiles et Web, comment ils fonctionnent, comment les corriger et, surtout, comment comprendre ce qui se trouve devant vous - une faille dangereuse ou une erreur mineure dans le code.







la mise en oeuvre



Eh bien, un type de vulnérabilité tellement commun. Elles sont embarquées partout: dans les requêtes SQL, LDAP, XML, XPath, XSLT, Xquery ... Toutes ces injections se distinguent par l'utilisation de données non fiables, grâce auxquelles un attaquant accède à des informations ou modifie le comportement de l'application. Par exemple, avec une entrée utilisateur qui n'est pas suffisamment validée.



Selon la classification internationale des vulnérabilités OWASP , les attaques utilisant la méthode «injection» sont classées en premier dans le niveau de criticité des menaces de sécurité des applications Web. Considérons les types d'implémentations les plus typiques.



Injection SQL . Les données non approuvées entrent dans la requête SQL vers la base de données.







Si la requête à la base de données n'implémente pas une authentification correcte des données d'entrée, un attaquant peut corrompre la requête SQL:



  • lui envoyer du code malveillant;
  • ajoutez le symbole "-" ou ";" et abandonner la commande SQL correcte: tout ce qui suit le "-" est interprĂ©tĂ© comme un commentaire, et le ";" marque la fin d'une commande;
  • devinez le mot de passe en exĂ©cutant sĂ©quentiellement une sĂ©rie de requĂŞtes SQL.


Comment se défendre? Voici quelques recommandations de l' OWASP :



  • Utilisez une API qui fournit une interface paramĂ©trĂ©e ou des outils de mappage objet-relationnel (ORM).
  • ImplĂ©mentez un mĂ©canisme de validation pour les donnĂ©es saisies par l'utilisateur. Utilisez une liste blanche de validation cĂ´tĂ© serveur.
  • Échapper les caractères spĂ©ciaux (";", "-", "/ *", "* /", "'"; la liste exacte dĂ©pend de la base de donnĂ©es).
  • Utilisez des procĂ©dures stockĂ©es en conjonction avec un mĂ©canisme de filtrage de leurs paramètres pour valider l'entrĂ©e utilisateur.


Injection XML . Les applications utilisent XML pour stocker ou échanger des données, afin qu'elles puissent contenir des informations précieuses.







Si un attaquant peut écrire des données dans un document XML, il peut changer sa sémantique. Dans ce cas, le scénario le plus inoffensif vous permettra d'injecter des balises supplémentaires dans le document, à la suite de quoi l'analyseur XML se fermera avec une erreur. Mais vous pouvez faire face à un incident plus grave: par exemple, avec la substitution des données d'authentification dans la base clients ou le prix dans la base de données produits du magasin. L'injection XML peut également conduire à des scripts intersites (XSS) - l'injection de code malveillant qui est exécuté dans le navigateur de l'utilisateur lorsque la page est ouverte.



Que pouvons-nous conseiller?



  • Ne crĂ©ez pas de balises et d'attributs dont les noms sont dĂ©rivĂ©s de donnĂ©es provenant d'une source non approuvĂ©e (par exemple, saisis par un utilisateur).
  • Encode (encodage d'entitĂ© XML) les donnĂ©es saisies par l'utilisateur avant de les Ă©crire dans un document XML.


L' injection XQuery est une forme d'injection SQL classique, mais dans ce cas, l'attaque ciblera la base de données XML et les données non fiables se retrouveront dans l'expression XQuery.



Dans l'exemple ci-dessous, l'application crée et exécute une expression XQuery basée sur des paramètres usernameet à passwordpartir d'une requête HTTP (source non approuvée):



XQDataSource xqs = new XQDataSource();
XQConnection conn = xqs.getConnection();
String query = "for \$user in doc(users.xml)//user[username='" + request.getParameter("username") + "'and pass='" + request.getParameter("password") + "'] return \$user";
XQPreparedExpression xqpe = conn.prepareExpression(query);
XQResultSequence rs = xqpe.executeQuery();


Si les données sont correctes, la demande renverra des informations sur l'utilisateur avec le nom et le mot de passe appropriés:



for \$user in doc(users.xml)//user[username='test_user' and pass='pass123'] return \$user


Si un attaquant spécifie une chaîne contenant des caractères spéciaux (par exemple, admin' or 1=1 or ''=') comme paramètre , la sémantique de la requête changera:



//user[username='admin']


La demande reçue renverra des données sur tous les utilisateurs.



Option sûre (utilise prepared statements):



XQDataSource xqs = new XQDataSource();
XQConnection conn = xqs.getConnection();
String query = "declare variable $username as xs:string external; declare variable $password as xs:string external; for \$user in doc(users.xml)//user[username='$username' and pass='$password'] return \$user";
XQPreparedExpression xqpe = conn.prepareExpression(query);
xqpe.bindString(new QName("username"), request.getParameter("username"), null);
xqpe.bindString(new QName("password"), request.getParameter("password"), null);
XQResultSequence rs = xqpe.executeQuery();


L'incorporation dans XSLT (XML Document Transformation Language) est possible si l'application utilise des données provenant d'une source non approuvée lorsqu'elle travaille avec XSL.



Les applications utilisent XSL pour transformer des documents XML. Les fichiers de style XSL contiennent des fonctions qui décrivent la transformation et, s'ils sont mis en œuvre de manière incorrecte, peuvent inclure des vulnérabilités. Dans ce cas, il existe un risque accru de scénarios d'attaque dans lesquels un attaquant modifie la structure et le contenu du fichier de style XSL, et donc le fichier XML correspondant. Que pouvons-nous obtenir à la sortie?



Tout d'abord, une attaque XSS: injection de code malveillant dans une page émise par un système web et interaction de ce code avec le serveur de l'attaquant. Deuxièmement, le pirate a accès aux ressources système. Troisièmement, l'exécution de code arbitraire. Et pour le dessert - attaque XXE (XML eXternal Entity - injection d'une entité externe dans XML).



L'intégration du protocole LDAP (Lightweight Directory Access Protocol ) dans les commandes peut entraîner une perte ou une modification des données. Dans ce cas, des données non approuvées entrent dans la requête LDAP.



Injection d'une commande d'interpréteur malveillante.Les données non approuvées entrent dans la commande d'interpréteur. Un attaquant peut choisir une telle entrée afin que la commande soit exécutée avec succès et que des autorisations supplémentaires dans l'application deviennent disponibles pour lui.



Dans l'exemple ci-dessous, l'application exécute un script pour créer une sauvegarde de base de données. L'application prend le type de sauvegarde comme paramètre et exécute le script avec des privilèges élevés:



String btype = request.getParameter("backuptype");
String cmd = new String("cmd.exe /K
\"c:\\util\\rmanDB.bat "+btype+"&&c:\\utl\\cleanup.bat\"")
System.Runtime.getRuntime().exec(cmd);


Le problème ici est que le paramètre n'est backuptypepas validé. N'exécute généralement Runtime.exec()pas plusieurs commandes, mais dans ce cas, cmd.exe est d'abord lancé pour exécuter plusieurs commandes en appelant Runtime.exec(). Une fois que le shell de ligne de commande est démarré, il peut exécuter plusieurs commandes, séparées par des caractères " &&". Si un attaquant && del c:\\dbms\\*.*spécifie la chaîne " " comme paramètre , l'application supprimera le répertoire spécifié.



Conseils aux développeurs:



  • Ne laissez pas les utilisateurs avoir un contrĂ´le direct sur les commandes exĂ©cutĂ©es par l'application. Si le comportement de l'application doit dĂ©pendre des donnĂ©es saisies par l'utilisateur, offrez Ă  l'utilisateur un choix parmi une certaine liste de commandes autorisĂ©es.
  • , . , . , .
  • , , . . .


Téléchargement de fichiers non sécurisé. Dans ce cas, non seulement les données individuelles proviennent d'une source non fiable, mais le fichier entier. Ainsi, un attaquant peut télécharger des données ou du code malveillant sur le serveur cible. Par exemple, si les utilisateurs d'un réseau d'entreprise sont autorisés à télécharger des fichiers vers des répertoires accessibles au public, un pirate informatique peut exécuter à distance un code malveillant sur le serveur de l'entreprise.



Inclusion non sécurisée d'un fichier externe en HTML.Des vulnérabilités d'inclusion de fichiers se produisent lorsque l'utilisateur entre le chemin d'accès à un fichier inclus. Le fait est que les langages de script modernes vous permettent de lier dynamiquement du code à partir de fichiers tiers afin de le réutiliser. Ce mécanisme est utilisé pour un aspect uniforme des pages ou pour diviser le code en petits modules. Cependant, cette inclusion peut être exploitée par un attaquant en modifiant le chemin et en connectant son fichier.



Nous recommandons aux professionnels de la sécurité des informations d'entreprise de créer une «liste blanche» de chemins de connexion de fichiers valides afin que les employés puissent ajouter des fichiers uniquement à l'aide de scripts de cette liste.



Favoris



Les signets sont des parties qui sont intentionnellement introduites dans le code de l'application, à l'aide desquelles, sous certaines conditions, vous pouvez effectuer des actions non incluses dans l'application. Considérons les types de signets les plus courants.



Comptes spéciaux. Si l'application compare la valeur d'un mot de passe ou d'une variable de connexion à une valeur inchangée, attention: ce compte peut faire partie d'un signet. Voyons comment cela se produit.







Le développeur de l'application utilise un compte spécial (éventuellement avec des privilèges élevés) lors du débogage et laisse les sections correspondantes du code dans la version finale, en conservant l'accès à l'application. Un attaquant peut restaurer le code d'origine de l'application, extraire les valeurs constantes du compte spécial et accéder à l'application.

Il est catégoriquement impossible de stocker les identifiants, les mots de passe, les clés dans le code source de l'application.
Fonctionnalité cachée (NDV). Le code de fonctionnalité masqué est exécuté lorsqu'un certain déclencheur se déclenche. Dans les applications Web, le déclencheur est souvent un paramètre de requête "invisible". Parfois, en plus, un contrôle est effectué à partir de l'IP d'où provient la requête avec le déclencheur, afin que seul son auteur puisse activer le signet. Ces vérifications servent de signal pour d'éventuels signets.



Activité réseau non documentée. Ce type d'activité comprend: la connexion à des ressources tierces en arrière-plan, l'écoute de ports non documentés, le transfert d'informations à l'aide des protocoles SMTP, HTTP, UDP, ICMP.

Si vous trouvez une connexion suspecte dans le code avec une adresse qui ne figure pas dans la liste des adresses sûres connues, nous vous recommandons fortement de la supprimer.

Modifiez les paramètres de sécurité . L'application contient du code qui modifie la valeur de la variable qui stocke le succès de l'authentification. Une erreur courante consiste à utiliser l'affectation (=) au lieu de la comparaison (==). Dans les méthodes d'authentification, c'est particulièrement dangereux car il peut faire partie d'une porte dérobée:



if (isAuthenticated = true)
{
    someDangerousAction();
}


Déclenchement temporel (bombe à retardement). Un signet qui se déclenche à un moment précis. L'application compare la date du jour à une année, un mois et un jour précis: au 1er janvier 2021, une surprise attend tout le monde:



Date now = java.util.Date();    // current time
if ((now.getYear() == 2021) && (now.getMonth() == 1) && (now.getDate() == 1))
{
    activateNewYearBackdoor();
}


Ou peut-être pas ... En pratique, lors de la recherche de déclencheurs temporaires, des faux positifs se produisent souvent. Par exemple, si l'API time est utilisée aux fins prévues: journalisation, calcul du temps d'exécution, horodatage des réponses du serveur aux requêtes HTTP.



Mais! Nous vous recommandons tout de même de ne pas fermer les yeux sur toutes ces alarmes, car nous connaissons de vrais exemples de telles vulnérabilités.



Code mort. Des morceaux de code injecté qui ne font rien d'utile. Le code mort lui-même n'est pas dangereux, mais il peut faire partie d'un signet qui a été réparti sur plusieurs fichiers. Ou, le déclencheur de signet est prévu pour être implémenté plus tard. Dans tous les cas, le code mort doit être suspect.



Manque de cryptage et utilisation d'algorithmes de cryptage faibles



Les principaux problèmes avec le chiffrement sont qu'il n'est pas du tout utilisé, ou que des algorithmes faibles sont utilisés, et les clés et le sel sont trop simples ou stockés de manière non sécurisée. La conséquence de toutes ces vulnérabilités est la même: il est plus facile de voler des données confidentielles.



L'exemple montre l'initialisation du chiffrement Ă  l'aide de l'ancien algorithme DES:



Cipher cipher = Cipher.getInstance("DES");


Exemples d'algorithmes de chiffrement vulnérables: RC2, RC4, DES. Option sûre:



Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");


Selon la classification internationale OWASP , les vulnérabilités telles que les «fuites de données confidentielles» sont classées troisième en termes de gravité des menaces de sécurité des applications Web.



Notre recommandation aux développeurs: assurez-vous d'utiliser le cryptage en gardant à l'esprit la sécurité.



L'utilisation du protocole HTTP non sécurisé au lieu de HTTPS est lourde d'une attaque de type Man in the middle.



Le protocole HTTPS sécurisé est basé sur HTTP, mais prend également en charge le cryptage via les protocoles cryptographiques SSL / TLS. HTTPS crypte toutes les données qui lui sont transmises, en particulier les pages de connexion et de saisie de mot de passe ou les données de la carte bancaire des utilisateurs, les protégeant contre les accès et les modifications non autorisés. Contrairement à HTTP, qui ne protège pas les données transmises. En conséquence, un attaquant peut usurper un site Web d'information via HTTP et forcer l'utilisateur à saisir des données sur une fausse page (attaque de phishing).



La clé de chiffrement est spécifiée dans le code source . En conséquence, ces clés sont disponibles pour tous les développeurs d'applications. De plus, après l'installation de l'application, vous ne pouvez supprimer la clé du code qu'à l'aide d'une mise à jour.



En général, les chaînes constantes sont facilement extraites d'un fichier exécutable à l'aide d'un programme de récupération de code source (décompilateur). Par conséquent, un attaquant n'a pas besoin d'avoir accès au code source pour connaître la valeur de la clé utilisée. Dans notre pratique, nous rencontrons souvent des cas où les développeurs spécifient nullsoit une chaîne vide comme valeur de clé , ce qui est tout simplement inacceptable.



Notre conseil: générez des clés avec des générateurs de nombres pseudo-aléatoires (PRNG) cryptographiquement puissants et stockez-les à l'aide de modules spéciaux.



Algorithme de remplissage non sécurisé pour le chiffrement . Si l'algorithme de chiffrement RSA est utilisé sans le remplissage OAEP, les données chiffrées deviennent vulnérables .



L'algorithme OAEP est nécessaire pour traiter les messages avant d'utiliser RSA. Le message est d'abord complété à une longueur fixe à l'aide d'OAEP, puis chiffré à l'aide de RSA. Ce schéma de cryptage est appelé RSA-OAEP et fait partie de la norme actuelle .



Voici un exemple d'initialisation du cryptage RSA sans remplissage:



rsa = javax.crypto.Cipher.getInstance("RSA/NONE/NoPadding");


Option sûre:



rsa = javax.crypto.Cipher.getInstance("RSA/ECB/OAEPWithMD5AndMGF1Padding");


Taille de clé de chiffrement insuffisante . Si vous utilisez une clé courte, ce chiffrement est vulnérable aux attaques par force brute.



La cryptanalyse ne s'arrête pas, de nouveaux algorithmes d'attaque émergent constamment, les ordinateurs gagnent en puissance. Les paramètres de chiffrement qui étaient auparavant considérés comme sécurisés sont obsolètes et son utilisation n'est plus recommandée. Ainsi, RSA avec une longueur de clé de 1024 bits n'était plus considéré comme sécurisé en 2010-2015.



Algorithme de hachage faible . Pour les raisons décrites dans le paragraphe précédent, les fonctions de hachage MD2, MD5, SHA1 ne sont pas sécurisées. Pour trouver des collisions pour les fonctions MD2 et MD5, aucune ressource significative n'est requise.



Pour SHA1, il existe des exemples de deux fichiers différents avec les mêmes hachages. Algorithme de piratage suggéréemployés de Google et du Center for Mathematics and Computer Science à Amsterdam.







Si les mots de passe des utilisateurs sont stockés sous forme de hachage, mais en utilisant une fonction de hachage non sécurisée, un attaquant pourrait facilement y accéder en mettant en œuvre le scénario suivant. Connaissant le hachage du mot de passe et exploitant la vulnérabilité de l'algorithme de hachage, il est possible de calculer une chaîne dont le hachage est le même que pour le mot de passe. L'attaquant s'authentifie à l'aide de la chaîne calculée.



La fonction de hachage pour stocker les mots de passe doit être résistante aux collisions et pas trop rapide pour qu'une attaque par force brute ne puisse pas être mise en œuvre. Les algorithmes sécurisés PBKDF2, bcrypt, scrypt doivent être utilisés.



Quelques chiffres intéressants: avec PBKDF2la vitesse de recherche des clés a été réduite à 70 pièces par seconde pour Intel Core2 et à environ 1 mille pour FPGA Virtex-4 FX60. En comparaison, les fonctions de hachage de mot de passe LANMAN classiques ont une vitesse de recherche d'environ des centaines de millions d'options par seconde.



Faible algorithme de cryptage . Comme pour les algorithmes de hachage, la sécurité d'un algorithme de chiffrement est déterminée par le temps et les ressources qui devront être consacrés à son déchiffrement. RC2, RC4, DES sont considérés comme des algorithmes vulnérables. Ce dernier, en raison de sa petite longueur de clé (56 bits), peut être craqué par force brute.



Un générateur de nombres pseudo-aléatoires faible (PRNG) génère des séquences prévisibles. Un pirate informatique peut contourner l'authentification et détourner la session d'un utilisateur.



Allons un peu plus loin dans la nature des PRNG. Ils génèrent des chaînes de nombres en fonction de la valeur initiale du paramètre seed. Il existe deux types de PRNG: statistiques et cryptographiques.



Les PRNG statistiques génèrent des séquences prévisibles qui sont statistiquement similaires aux séquences aléatoires. Ils ne peuvent pas être utilisés à des fins de sécurité.



Le résultat du fonctionnement des PRNG cryptographiques, au contraire, ne peut pas être prédit si la valeur du paramètre est seedobtenue à partir d'une source à forte entropie. La valeur de temps actuelle a peu d'entropie et est également de qualité dangereuse seed. En Java, PRNGs des classes java.util.Randomet java.lang.Mathgénèrent des séquences prévisibles et ne doivent pas être utilisés à des fins de sécurité de l' information.



Graine faible d'un générateur de nombres pseudo-aléatoires . Il n'est seedpas sûr d' utiliser une valeur provenant d'une source non approuvée car elle génère une séquence prévisible.



Le travail de nombreux algorithmes cryptographiques repose sur l'utilisation d'un PRNG résistant à la cryptanalyse. Certains algorithmes peuvent prendre une valeur comme argument supplémentaire seedet générer une séquence prévisible pour chaque valeur de ce paramètre. Dans ce cas, la sécurité du système est basée sur l'hypothèse que les valeurs seedseront imprévisibles.



Le sel est spécifié dans le code source... Souvenons-nous à quoi sert le sel. Pour déchiffrer un mot de passe par la méthode de la force brute, des tables pré-compilées avec des valeurs de fonctions de hachage de mots de passe courants sont utilisées. Salt est une chaîne arbitraire qui est fournie à l'entrée de la fonction de hachage avec le mot de passe pour rendre une telle attaque plus difficile.



Si le sel est stocké dans le code source, exactement les mêmes problèmes se posent que pour les mots de passe et les clés. La valeur de salt est disponible pour les développeurs et peut facilement être obtenue par des attaquants, et salt ne peut être supprimé de la version finale de l'application qu'avec la prochaine mise à jour de l'application.



Manipulation avec les logs



Diverses erreurs dans les journaux entraînent l'introduction de codes malveillants dans les applications. Les vulnérabilités les plus courantes associées à la journalisation sont la falsification des fichiers journaux et la journalisation non structurée.



La falsification du fichier journal se produit lorsqu'une application écrit des données non approuvées dans le journal des événements (journal). Un pirate informatique peut fausser les entrées de journal ou y injecter du code malveillant.



En règle générale, les applications consignent l'historique des transactions pour un traitement ultérieur, un débogage ou une collecte de statistiques. Les journaux peuvent être analysés manuellement ou automatiquement.

Si les données sont écrites dans le journal "telles quelles", un attaquant peut injecter de faux enregistrements dans le journal, violer la structure du fichier provoquant l'échec du processeur de journal ou injecter un code malveillant exploitant les vulnérabilités connues du processeur.



Dans cet exemple, une application Web tente de lire une valeur entière à partir d'un paramètre de demande. Si la valeur saisie n'a pas pu être convertie en un entier, l'application enregistre cette valeur avec un message d'erreur:



String val = request.getParameter("val");
try {
    int value = Integer.parseInt(val);
}
catch (NumberFormatException nfe) {
    log.info("Failed to parse val = " + val);
}


Un attaquant peut ajouter une entrée arbitraire au journal, par exemple, la ligne twenty-one%0a%0aINFO:+User+logged+out%3dbadguysera reflétée dans le journal comme suit:



INFO: Failed to parse val=twenty-one
INFO: User logged out=badguy


De même, des enregistrements arbitraires peuvent être incorporés dans le journal.



Option sûre (utilise NumberFormatException):



public static final String NFE = "Failed to parse val. The input is required to be an integer value."

String val = request.getParameter("val");
try {
    int value = Integer.parseInt(val);
}
catch (NumberFormatException nfe) {
    log.info(NFE);
}


La journalisation non structurée , c'est-à-dire l'impression de messages d'erreur sur des flux standard out ou err, est une méthode non sécurisée. Il est recommandé d'utiliser à la place la journalisation structurée. Ce dernier permet de générer un journal avec des niveaux, des horodatages, un formatage standard. Si le programme implémente un mécanisme de journalisation structuré, mais que des messages d'erreur sont émis vers des flux standard, le journal peut ne pas contenir d'informations critiques.

La sortie de messages d'erreur dans des flux standard n'est acceptable qu'aux premiers stades du développement.



Traitement non sécurisé des cookies



Les vulnérabilités associées à la collecte de cookies utilisateurs sont très diverses.



Manipulation non sécurisée des cookies . L'application inclut des données provenant d'une source non approuvée dans le cookie, ce qui peut entraîner un empoisonnement du cache, des attaques XSS (cross-site scripting) et de fractionnement de réponse.



Si un code malveillant (cross-site scripting) est injecté dans une application, un attaquant peut modifier le cookie de l'utilisateur.



Étant donné que les cookies sont définis dans l'en-tête de la réponse HTTP, le fait de ne pas reconnaître les données incluses dans le cookie peut entraîner une attaque de réponse fractionnée. "HTTP response splitting" est une attaque dans laquelle un hacker envoie une telle requête HTTP, dont la réponse sera acceptée par la victime dans deux réponses HTTP (au lieu de la bonne).

Si l'attaquant spécifie une authorchaîne du formulaire comme paramètre Hacker \r\nHTTP/1.1 200 OK\r\n..., la réponse sera scindée en deux comme suit:



HTTP/1.1 200 OK
...
Set-Cookie: author=Hacker

HTTP/1.1 200 OK
...


Le contenu de la deuxième réponse est entièrement sous le contrôle de l'attaquant, ce qui entraîne un empoisonnement du cache, XSS, des redirections malveillantes et d'autres attaques.



Cookies sans HttpOnly . L'application crée des cookies sans indicateur httpOnly. S'il était httpOnlyinclus dans l'en-tête de la réponse http, un attaquant ne serait pas en mesure d'obtenir des cookies en utilisant du code JavaScript. Et si un utilisateur ouvre une page avec une vulnérabilité de script intersite (XSS), le navigateur ne divulguera pas les cookies à des tiers. Si l'indicateur n'est httpOnlypas défini, les cookies (généralement des cookies de session) peuvent être volés à l'aide d'un script.



Un exemple de création d'un cookie sans indicateur httpOnly:



Cookie cookie = new Cookie("emailCookie", email);
response.addCookie(cookie);


Définissez le drapeau httpOnlylors de la création de cookies. Gardez à l'esprit, cependant, qu'il existe des moyens de contourner les attaques, httpOnlyvous devez donc également prendre soin de valider soigneusement l'entrée.



NB Selon la classification internationale OWASP , les vulnérabilités «fuite de données confidentielles» sont classées au troisième rang du niveau de criticité des menaces de sécurité des applications Web.



Cookies pour un domaine trop général . Si le domaine du cookie est trop général (par exemple .example.com), une vulnérabilité dans une application expose d'autres applications du même domaine à des vulnérabilités.



Dans l'exemple suivant, une application Web sécurisée installée à une adresse http://secure.example.comdéfinit un cookie avec une valeur de domaine .example.com:



Cookie cookie = new Cookie("sessionID", sessionID);
cookie.setDomain(".example.com");


Si http://insecure.example.comune application contenant, par exemple, XSS est installée à l'adresse , alors les cookies de l'utilisateur autorisé de l'application sécurisée qui s'est rendu à l'adresse http://insecure.example.compeuvent être compromis.



Un attaquant peut également mener une attaque d'empoisonnement de cookie: les cookies avec un domaine commun créé http://insecure.example.comécraseront le cookie http://secure.example.com.



Option sûre:



Cookie cookie = new Cookie("sessionID", sessionID);
cookie.setDomain("secure.example.com");


Cookies avec paramètre trop généralpath . Si le chemin d'accès dans le cookie est inexact (par exemple, /), le même problème se pose que pour le domaine partagé: une vulnérabilité dans une application met en danger d'autres applications du même domaine.



Dans l'exemple suivant, une application installée sur une URL http://pages.example.com/forumdéfinit un cookie avec le chemin /:



Cookie cookie = new Cookie("sessionID", sessionID);
cookie.setPath("/");


Ensuite, une application malveillante installée à l'adresse http://pages.example.com/evilpeut compromettre les cookies de l'utilisateur. Un attaquant peut également mener une attaque d'empoisonnement de cookie: un cookie avec un chemin commun créé /evilécrasera le cookie /forum.



Option sûre:



Cookie cookie = new Cookie("sessionID", sessionID);
cookie.setPath("/forum");


Les cookies ne sont pas sur SSL . L'application crée des cookies sans définir le drapeau secureégal true. Ces cookies peuvent être transmis non cryptés via HTTP. La vulnérabilité "Utilisation du protocole HTTP non sécurisé" est immédiatement rappelée.



Dans l'exemple suivant, l'application crée des cookies sans indicateur secure:



Cookie cookie = new Cookie("emailCookie", email);
response.addCookie(cookie);


Si l'application utilise à la fois HTTPS et HTTP, alors en l'absence de l'indicateur sécurisé, les cookies créés dans le cadre de la requête HTTPS seront transmis non cryptés dans les requêtes HTTP suivantes, ce qui peut conduire à la compromission de l'application. Ceci est particulièrement dangereux si le cookie contient des données précieuses, en particulier l'ID de session.



Option sûre:



Cookie cookie = new Cookie("emailCookie", email);
cookie.setSecure(true);
response.addCookie(cookie);


Cookies à validité illimitée . Si vous stockez des cookies précieux pendant trop longtemps, un attaquant peut y accéder.



Par défaut, des cookies non persistants (de session) sont utilisés, qui ne sont pas enregistrés sur le disque et sont supprimés après la fermeture du navigateur. Cependant, le développeur de l'application Web peut spécifier la durée de conservation des cookies - dans ce cas, ils seront écrits sur le disque et enregistrés entre les redémarrages du navigateur et les redémarrages de l'ordinateur. Cela laisse à l'attaquant le temps d'élaborer un plan d'attaque.



Recommandations du développeur: assurez-vous que l'application ne crée pas de cookies de longue durée:



Cookie cookie = new Cookie("longCookie", cookie);
cookie.setMaxAge(5*365*24*3600); // 5 !


Fournir un délai maximum raisonnable conformément aux directives de l' OWASP .



Fuite d'informations



Peut-être le type de vulnérabilité le plus sensible pour les utilisateurs d'applications.



Fuite d'informations externes via les pages d'erreur . L'application utilise des pages d'erreur standard, qui peuvent contenir des informations sur la configuration du système.



Les messages d'erreur et les informations de débogage sont écrits dans le journal, affichés sur la console ou transmis à l'utilisateur. À partir des messages d'erreur, un attaquant peut découvrir les vulnérabilités du système, ce qui lui facilitera la vie. Par exemple, une erreur de base de données peut indiquer une insécurité contre l'injection SQL. Les informations sur la version du système d'exploitation, le serveur d'applications et la configuration du système permettront à un pirate informatique de planifier plus facilement une attaque sur une application.



Fuite externe d'informations précieuses... Dans ce cas, nous parlons de la fuite d'informations techniques sur l'application en la transférant sur le réseau vers un autre ordinateur. En général, les fuites externes sont plus dangereuses que les fuites internes.







Fuite interne d'informations précieuses . Le mécanisme de fonctionnement est similaire aux deux types de fuites précédents, mais dans ce cas, les informations sur le système sont écrites dans le journal ou affichées sur l'écran de l'utilisateur.



Fuite de données confidentielles . Les données personnelles précieuses des utilisateurs entrent dans l'application à partir de différentes sources: de l'utilisateur lui-même, de diverses bases de données, de stockages tiers. Parfois, ces données ne sont pas marquées comme confidentielles ou se révèlent précieuses non pas en soi, mais uniquement dans un certain contexte.



C'est le cas même lorsque la sécurité des applications et la confidentialité des données personnelles se contredisent. Pour des raisons de sécurité, il est conseillé d'enregistrer des informations détaillées sur l'activité dans le système afin de détecter les activités malveillantes. Du point de vue de la confidentialité des données, au contraire, lors de l'enregistrement d'informations confidentielles, le risque de fuite est plus grand. En général, garantir la confidentialité des données personnelles des utilisateurs d'applications est une priorité plus élevée.



Épilogue



Les types de vulnérabilités considérés dans cet article couvrent la plupart des lacunes «universelles» des applications écrites dans différents langages de programmation. Cependant, certains langages ont leurs propres vulnérabilités spécifiques. Mais c'est déjà un sujet pour un article séparé. Et enfin, n'oubliez pas: lors de la création d'applications, n'oubliez pas de suivre les recommandations ci-dessus, de lire attentivement la documentation et de vérifier les vulnérabilités des applications à l'aide de logiciels spécialisés.



Auteur: Elizaveta Kharlamova, chef du département d'analyse, Solar appScreener




All Articles