Controler automatiquement la sécurité de ses dépendances avec SensioLabs security checker, Jenkins et Phing

Aujourd'hui, nous incluons toujours plus de librairies externes dans nos projets. Même si on gagne beaucoup de temps, il n'est pas exclu que nous introduisions des failles de sécurité via ces lib. Ce contrôle n'est malheureusement pas systématique mais surtout rarement automatisé. Depuis quelques temps, SensioLabs propose un service pour réferencer des failles (CVE) dans des librairies ainsi que l'outil Security Checker pour controller les dépendances de son projet via le fichier composer.lock.

Security Checker

On peut trouver cet outil sur Github sous la forme d'un Phar ou en librairie à ajouter à notre projet. Pour l'exemple j'utilise la version Phar que j'ai ajouté dans mon path pour faciliter son utilisation. J'ai créé un projet vide en ajoutant des versions de librairies connues pour avoir une faille. L'utilisation de security checker est simple et le résultat très explicite.

 
~/blog$ security-checker.phar security:check ./composer.lock
 
Security Check Report
~~~~~~~~~~~~~~~~~~~~~
 
Checked file: /home/ulrich/blog/composer.lock
 
 
  [CRITICAL]
  3 packages have known vulnerabilities
 
 
doctrine/doctrine-bundle (v1.2.0)
---------------------------------
 
 * CVE-2015-5723: Security Misconfiguration Vulnerability in various Doctrine projects
   http://www.doctrine-project.org/2015/08/31/security_misconfiguration_vulnerability_in_various_doctrine_projects.html
 
doctrine/orm (v2.3.6)
---------------------
 
 * CVE-2015-5723: Security Misconfiguration Vulnerability in various Doctrine projects
   http://www.doctrine-project.org/2015/08/31/security_misconfiguration_vulnerability_in_various_doctrine_projects.html
 
zendframework/zend-json (2.2.1)
-------------------------------
 
 * Potential XXE/XEE attacks using PHP functions: simplexml_load_*, DOMDocument::loadXML, and xml_parse
   http://framework.zend.com/security/advisory/ZF2014-01
 
             This checker can only detect vulnerabilities that are referenced
 Disclaimer  in the SensioLabs security advisories database. Execute this
             command regularly to check the newly discovered vulnerabilities.
 

 

Automatisation

Comme beaucoup (j'espère) j'utilise un outil d'intégration continue, Jenkins dans mon cas. Et pour builder mon projet j'utilise Phing qui est un super outil, si si, même s'il n'est plus tout jeune. C'est donc l'occasion de parler un peu de Phing et de montrer comment faire une tâche un peu plus "intelligente".

Basiquement je pourrais créer une tâche ainsi:

 
<project name="checksecu" basedir="." default="secu">
    <target name="secu">
        <exec executable="security-checker.phar">
            <arg value="security:check" />
            <arg path="./composer.lock" />
        </exec>
    </target>
</project>
 

Et l'exécution donne:

 
~/blog$ phing.phar -f ../jenkinsbuildconf/checksecu.xml
Buildfile: /home/ulrich/blog/../jenkinsbuildconf/checksecu.xml
 
checksecu > secu:
 
 
BUILD FINISHED
 
Total time: 0.4584 seconds
 

Le problème c'est que, d'une part je n'ai aucun retour, et surtout le build n'est pas considéré comme étant en erreur. Pour traiter le premier problème, il me suffit de renvoyer la sortie du script dans une variable via outputProperty et de l'afficher. Pour le second problème je peux utiliser checkreturn, ce qui me donne:

 
<project name="checksecu" basedir="." default="secu">
    <target name="secu">
        <exec executable="security-checker.phar" outputProperty="output" checkreturn="true">
            <arg value="security:check" />
            <arg path="./composer.lock" />
        </exec>
        <echo message="output: ${output}" />
    </target>
</project>

et mon execution devient:

 
~/blog$ phing.phar -f ../jenkinsbuildconf/checksecu.xml
Buildfile: /home/ulrich/blog/../jenkinsbuildconf/checksecu.xml
 
checksecu > secu:
 
Execution of target "secu" failed for the following reason: /home/ulrich/blog/../jenkinsbuildconf/checksecu.xml:6:60: Task exited with code 1
 
BUILD FAILED
/home/ulrich/blog/../jenkinsbuildconf/checksecu.xml:6:60: Task exited with code 1
Total time: 0.9041 seconds
 

Super mon build failed, mais je n'ai pas la sortie de security-checker.phar ce qui est embettant. Je vais donc remplacer checkreturn par returnProperty pour stocker dans une variable l'exit code de la commande puis le tester avec un if.

 
<project name="checksecu" basedir="." default="secu">
    <target name="secu">
        <exec executable="security-checker.phar" outputProperty="output" returnProperty="return">
            <arg value="security:check" />
            <arg path="./composer.lock" />
        </exec>
        <if>
            <equals arg1="${return}" arg2="1" />
            <then>
                <echo message="output: ${output}" />
                <fail message="Le composer.lock montre que le projet se base sur des libs ayant des CVE." />
            </then>
        </if>
    </target>
</project>

Ce qui me donne à l'exécution:

 
~/blog$ phing.phar -f ../jenkinsbuildconf/checksecu.xml
Buildfile: /home/ulrich/blog/../jenkinsbuildconf/checksecu.xml
 
checksecu > secu:
 
     [echo] output:
Security Check Report
~~~~~~~~~~~~~~~~~~~~~
 
Checked file: /home/ulrich/blog/composer.lock
 
 
  [CRITICAL]
  3 packages have known vulnerabilities
 
 
doctrine/doctrine-bundle (v1.2.0)
---------------------------------
 
 * CVE-2015-5723: Security Misconfiguration Vulnerability in various Doctrine projects
   http://www.doctrine-project.org/2015/08/31/security_misconfiguration_vulnerability_in_various_doctrine_projects.html
 
doctrine/orm (v2.3.6)
---------------------
 
 * CVE-2015-5723: Security Misconfiguration Vulnerability in various Doctrine projects
   http://www.doctrine-project.org/2015/08/31/security_misconfiguration_vulnerability_in_various_doctrine_projects.html
 
zendframework/zend-json (2.2.1)
-------------------------------
 
 * Potential XXE/XEE attacks using PHP functions: simplexml_load_*, DOMDocument::loadXML, and xml_parse
   http://framework.zend.com/security/advisory/ZF2014-01
 
             This checker can only detect vulnerabilities that are referenced
 Disclaimer  in the SensioLabs security advisories database. Execute this
             command regularly to check the newly discovered vulnerabilities.
 
Execution of target "secu" failed for the following reason: /home/ulrich/blog/../jenkinsbuildconf/checksecu.xml:11:12: /home/ulrich/blog/../jenkinsbuildconf/checksecu.xml:15:30: Le composer.lock montre que le projet se base sur des libs ayant des CVE.
 
BUILD FAILED
/home/ulrich/blog/../jenkinsbuildconf/checksecu.xml:11:12: /home/ulrich/blog/../jenkinsbuildconf/checksecu.xml:15:30: Le composer.lock montre que le projet se base sur des libs ayant des CVE.
Total time: 0.4784 seconds
 

Et voilà! Il ne me reste plus qu'a ajouter cette tâche dans mon build général de phing pour que Jenkins teste systèmatiquement si mon projet se base sur une version ayant une CVE connue. Pour ceux qui prèfere Ant à Phing, je pense que cette tache peut être très facilement transposable si pas réutilisable tel quel.

Il n'y aucun commentaire