Dans des articles récents, j'ai expliqué comment vous, en tant que développeur, pouvez développer vos compétences en sécurité en utilisant les fonctionnalités de New Relic. J'ai également approfondi les moyens d'atténuer les risques de sécurité cachés des bibliothèques de logiciels open source. Ces deux articles de blog se sont concentrés sur le code tiers et son impact sur la sécurité de vos applications logicielles. Dans cet article, je me concentrerai sur la sécurité de votre propre code personnalisé, c'est-à-dire le code que vous écrivez vous-même.

En général, il existe différentes méthodes que vous pouvez utiliser pour garantir la sécurité de votre code propriétaire. Une approche courante consiste à utiliser des outils d'analyse de code statique, qui analysent votre code source avant son déploiement dans différents environnements tels que les tests, l'assurance qualité et la production. Cette pratique s'avère utile car elle empêche l'inclusion de secrets codés en dur dans votre référentiel ou vos versions logicielles. Cependant, ces techniques n’offrent qu’un aperçu des aspects statiques de votre application.

Pour remédier à cette limitation, l'industrie s'appuie souvent sur des outils dynamiques de sécurité des applications, qui effectuent des tests en boîte noire en examinant votre application d'un point de vue externe. Si cette approche offre une perspective supplémentaire, elle ne révèle qu’une seule facette de la situation sécuritaire globale. Le cœur du problème est qu’aucune de ces solutions n’offre une vision globale.

Les tests interactifs de sécurité des applications (IAST) de New Relic sont précisément conçus pour résoudre ce problème. Avec IAST, vous pouvez améliorer votre observabilité car les outils New Relic offrent déjà une visibilité exceptionnelle sur les aspects dynamiques de votre application de l'intérieur. Par sa nature, le monitoring des performances des applications (APM) nous permet d'observer le code pendant son exécution sur les systèmes. Cela signifie que nous voyons non seulement les performances et les erreurs, mais aussi quelle version du code a été déployée sur chaque instance du service et quelles méthodes sont réellement déclenchées en fonction de l'activité en temps réel dans l'application elle-même.

Dans l’observation de vos services, les problèmes de sécurité des applications, provenant à la fois de sources propriétaires et tierces, sont de plus en plus cruciaux. New Relic IAST joue un rôle clé dans ce contexte, car il élimine efficacement toute ambiguïté en détectant rapidement les vulnérabilités de vos applications. Il fournit des preuves concluantes des exploitations et leurs emplacements précis dans votre code. De plus, l'outil propose des procédures de test et des mesures d'atténuation exploitables et reproductibles, vous permettant de résoudre efficacement les problèmes de sécurité dans des environnements de pré-production ou de développement avant qu'ils ne deviennent exploitables. Voici un exemple de ce que nous entendons par « exploitable et reproductible » : pour chaque test de sécurité, il existe une commande curl associée (ou une autre forme de script de test) afin que vous puissiez revenir en arrière et re-tester pendant que vous corrigez votre code. Le même script de test peut ensuite être utilisé pour vérifier qu'il est véritablement corrigé sans réexécuter l'ensemble des tests.

En tant que première étape vers une sécurité démontrable, New Relic IAST permet un véritable « virage à gauche » dans la sécurité logicielle en favorisant une collaboration des équipes DevOps et de sécurité pour accélérer les pipelines d'intégration continue et de déploiement continu (CI/CD) en permettant aux organisations de se concentrer sur l'innovation, tout en sécurisant vos applications dès le début du cycle de développement.

Un autre avantage clé de la concentration sur les vulnérabilités exploitables est le fait que les outils de sécurité des applications traditionnels manquent souvent de contexte, ce qui entraîne un nombre écrasant d'alertes qui peut dérouter les équipes DevOps et de sécurité et complique l'identification des risques de sécurité immédiats et la vérification des améliorations de sécurité. Au fond, New Relic IAST élimine le bruit (les faux positifs) trouvé dans de nombreuses autres solutions et fournit une preuve d'exploitation pour validation.

J'ai parlé longuement, alors laissez-moi maintenant vous montrer comment fonctionne New Relic IAST en pratique.

Remarque : avant de poursuivre et de vous expliquer comment démarrer avec New Relic IAST, je souhaite souligner un aspect important. New Relic IAST simule une batterie d'attaques réelles au sein de votre application. Cela signifie que des données de test seront utilisées pour simuler et tester des vulnérabilités exploitables. Pour cette raison, New Relic IAST doit être utilisé uniquement dans des environnements de pré-production.

Agents de langage New Relic

Les agents New Relic APM les plus récents incluent désormais la fonctionnalité IAST. Nous savons tous à quel point il est facile d'ajouter des agents APM à une application pour identifier les bugs et les problèmes de performances. Jetez un œil à cet exemple intuitif pour un environnement .NET. Désormais, sans effort supplémentaire, nous pouvons également tester votre code personnalisé pour détecter les 10 principales vulnérabilités exploitables d'OWASP, telles que les attaques par injection.  À mon avis, il s’agit d’un avantage incroyable de New Relic IAST que de nombreuses parties prenantes vont adorer :

  • Les équipes IT, car elles n'ont pas besoin de déployer un énième agent.
  • Les équipes de sécurité, car cela donne aux équipes de développement des moyens de renforcer la sécurité.
  • Vous en tant que développeur, car cela fait déjà partie de la chaîne d'outils que vous utilisez déjà.

Cette fonctionnalité est très simple à implémenter. Dans mon exemple, j'utilise à nouveau l'application OWASP Juice Shop comme environnement de démonstration.

Juice Shop est construite avec Node.js et j'ajoute donc le dernier agent New Relic Node.js (IAST a été ajouté dans la version v10.3.0) à mon application.

Nous suivons l'approche bien connue consistant à exécuter la commande suivante dans notre référentiel

npm install newrelic

Cela installe la bibliothèque d'agents New Relic dans notre application. Le moyen le plus simple de configurer l'agent consiste à définir ces variables d'environnement :

NEW_RELIC_APP_NAME=juice-shop-mysql 
 NEW_RELIC_LICENSE_KEY=<your New Relic license key>

Vous pouvez maintenant installer le reste des dépendances de Juice Shop avec npm install et exécuter l'application via npm start. Après un court instant, les données apparaîtront dans votre compte New Relic dans l'expérience familière organisée pour APM.

Sans aucune configuration supplémentaire, l'agent capturera toutes les bibliothèques utilisées dans votre application et recherchera les vulnérabilités connues. Ces données sont publiées dans la section Gestion des vulnérabilités de votre service dans New Relic.

Activation de New Relic IAST

Maintenant que l'agent est opérationnel et qu'il signale déjà les vulnérabilités des bibliothèques tierces, passons à l'activation des fonctionnalités IAST.

J'arrête l'application et je vais ajouter deux variables d'environnement supplémentaires :

NEW_RELIC_SECURITY_ENABLED=true 
 NEW_RELIC_SECURITY_AGENT_ENABLED=true

La première variable d'environnement détermine si les données de sécurité sont envoyées ou non à New Relic. Lorsque celle-ci est désactivée et que NEW_RELIC_SECURITY_AGENT_ENABLED est vraie, le module de sécurité s'exécutera mais les données ne seront pas envoyées. La seconde vous permet d'activer ou de désactiver toutes les fonctionnalités de sécurité en général.

Une fois que ces variables sont définies, nous n’avons plus rien d’autre à configurer. L’agent s’occupera du reste à la prochaine exécution de l’application.

Simulation d'attaques réelles

Maintenant que l'application est à nouveau exécutée (en exécutant à nouveau npm start ), nous pouvons exécuter nos tests unitaires habituels. Dans le référentiel Juice Shop, tous les tests unitaires se trouvent dans le dossier test . Ainsi, vous pouvez exécuter les tests de l'API en exécutant npm run test:api. Rien qu'en déclenchant ces tests, l'agent va identifier le contexte de la requête ; c'est-à-dire une transaction dans le contexte New Relic, comprenant tous les détails des paramètres, de la charge utile, etc.

Par exemple, notre Juice Shop comprend une API pour connecter les utilisateurs de l'application. Ce point de terminaison reçoit une partie de la charge, notamment les informations d'identification de l'utilisateur pour l'authentification de l'utilisateur.

Utilisons l'application et essayons de nous connecter à l'application avec un utilisateur existant.

Après un court instant, vous verrez une activité de notre agent toucher votre application. Si un problème est identifié par l'agent, il ajoutera une vulnérabilité à la section New Relic Vulnerability Management. La grande différence est qu’il ne le fera que si la vulnérabilité est réellement exploitable.

Étudions un exemple.

Vous pouvez identifier les vulnérabilités exploitables avec un point d'exclamation dans la colonne Exploitable . Cela signifie que nous avons non seulement trouvé un problème, mais que nous avons également identifié une preuve d'exploitation pour celui-ci. Un autre aspect clé lors de l’analyse des vulnérabilités est que cette liste de vulnérabilités est hiérarchisée en fonction de leur gravité.

Vous cliquez sur le problème injection SQL (SQL injection) pour en savoir plus sur le problème et sur la capacité unique de New Relic à fournir une preuve d'exploitabilité. Ici, les utilisateurs trouveront une description détaillée de la vulnérabilité et des instances spécifiques de ce problème dans votre code propriétaire.

En cliquant sur l'une des instances d'injection SQL, vous obtiendrez plus d'informations sur l'emplacement dans votre code source et la façon de résoudre le problème.

Correction d'une vulnérabilité exploitable

L'une des fonctionnalités clés de New Relic IAST est le test de replay fourni par New Relic. Dans la section Test de l'écran, vous trouverez un script de test que vous pouvez utiliser pour prouver l'exploitabilité. Dans notre cas, nous exécuterons ce script pour prouver que l'injection SQL est en réalité un problème réel et exploitable dans Juice Shop.

Ouvrons un terminal et exécutons la commande suivante que nous copions depuis l'interface utilisateur de New Relic. Notez que j'ai ajouté l'URL complète dans la première ligne du script. J'ai également légèrement ajusté le paramètre data-raw .

curl --location --request POST 'https://wxmqzkpgeu.us-east-1.awsapprunner.com/rest/user/login' \ 
 --header 'x-forwarded-proto:https' \ 
 --header 'user-agent:Mozilla/5.0 (Macintosh;Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 Edg/114.0.1823.67;' \
--header 'accept:application/json, text/plain, */*' \
--header 'sec-ch-ua-platform:"macOS"' \
--header 'sec-ch-ua-mobile:?0' \
--header 'sec-fetch-site:same-origin' \
--header 'accept-encoding:gzip, deflate, br' \
--header 'accept-language:de,de-DE;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6;' \
--header 'host:wxmqzkpgeu.us-east-1.awsapprunner.com' \
--header 'cookie:language=en;welcomebanner_status=dismiss;cookieconsent_status=dismiss;' \
--header 'origin:https://wxmqzkpgeu.us-east-1.awsapprunner.com' \
--header 'x-envoy-expected-rq-timeout-ms:120000' \
--header 'content-type:application/json' \
--header 'sec-fetch-dest:empty' \
--header 'x-request-id:dfc1b83b-5e24-4cb6-877b-20913a9cd54f' \
--header 'sec-ch-ua:"Not.A/Brand";v="8", "Chromium";v="114", "Microsoft Edge";v="114";' \
--header 'sec-fetch-mode:cors' \
--header 'x-forwarded-for:79.252.203.104' \
--header 'referer:https://wxmqzkpgeu.us-east-1.awsapprunner.com/' \
--header 'x-envoy-external-address:79.252.203.104' \
--data-raw '{"email": "1'"'"' OR TRUE; #","password":"12345"}'

Une fois ce script exécuté, vous remarquerez que nous récupérons des données JSON avec des informations de l'utilisateur admin de Juice Shop. Ce n’est bien sûr pas ce que l’application devrait fournir et cela prouve que nous avons réellement un problème critique et un risque qui y est associé.

L'emplacement de la vulnérabilité fourni par New Relic IAST nous montre que l'un des problèmes d'injection SQL se trouve dans `/rest/user/login`.

Jetons un coup d'œil au code source de l'application et ouvrons le fichier `server.ts` (à la racine du référentiel). Quelque part autour de la ligne 543, vous verrez quelle méthode est réellement appelée lorsque quelqu'un atteint le point de terminaison `/rest/user/login`. La méthode `login()` est exécutée et elle se trouve dans `/routes/login.ts`. En tant que développeur, je peux voir la requête SQL concaténée en ajoutant l'entrée utilisateur directement dans l'instruction SQL (ligne 36).

models.sequelize.query(`SELECT * FROM Users WHERE email = '${req.body.email || ''}' AND password = '${security.hash(req.body.password || '')}' AND deletedAt IS NULL`, { model: UserModel, plain: true })

Il ne s'agit absolument pas d'une bonne pratique et les développeurs doivent éviter de créer des requêtes SQL de cette façon.

Dans l'idéal, vous utiliserez des requêtes paramétrées. Dans le cadre « sequelize », on appelle cela des remplacements. Donc, idéalement, nous devrions utiliser des paramètres dans la requête elle-même et les remplacer par le contenu en utilisant le concept de remplacement. Le code mis à jour devrait ressembler à ceci :

models.sequelize.query(`SELECT * FROM Users WHERE email = :email AND password = :password AND deletedAt IS NULL`,
      {
        model: UserModel,
        plain: true,
        replacements: {
          email: req.body.email || '',
          password: security.hash(req.body.password || '')
        }
      })

À présent, résolvez ce problème de code et redéployez l'application. Maintenant que notre nouvelle version de notre application est opérationnelle et que les données sont rapportées dans New Relic, nous pouvons réexécuter notre script curl de test.

Une fois l'exécution terminée, nous n'obtenons plus le même résultat qu'avant, c'est-à-dire les informations d'identification de l'utilisateur admin de Juice Shop. Nous recevons cette fois un message indiquant que nous avons fourni un e-mail ou mot de passe non valide. C'est en fait ce à quoi nous nous attendons et cela prouve que notre correctif dans notre code source propriétaire a effectivement corrigé le bug.

Si nous revenons maintenant à notre interface utilisateur New Relic et que nous parcourons la section Gestion des vulnérabilités de notre application, vous remarquerez que nous identifions toujours les deux vulnérabilités exploitables. Cependant, nous remarquons également que le problème d'injection SQL a été détecté pour la dernière fois il y a quatre heures environ, mais le problème Reflected XSS existe toujours puisqu'il a de nouveau été signalé après notre déploiement.

Conclusion

Ce que je vous ai montré dans cet exemple est un cycle complet d'exécution d'une analyse interactive de la sécurité des applications en examinant votre application et en exécutant des tests pour trouver des vulnérabilités exploitables.

Non seulement nous avons identifié un problème, mais nous avons également reçu certaines instances contenant des scripts de test que nous avons pu réexécuter pour prouver que les problèmes identifiés sont effectivement exploitables. Après avoir résolu le problème dans notre code propriétaire, nous avons créé une nouvelle version de notre application et l'avons déployée. Cette fois, les tests de notre agent New Relic IAST n'ont pas pu s'exécuter avec succès pour cette zone spécifique de notre application. J'ai pu prouver le succès du correctif en exécutant le même script de test et valider que ce n'est plus un problème dans notre application.