OWASP Dependency Checker

Een flink aantal jaar geleden hoorde ik voor het eerst van OWASP: de Open Web Application Security Project. Ze zijn met name bekend geworden met hun top-10: een lijst met tien risicovolste kwetsbaarheden die in web applicaties aangetroffen worden. Deze lijst heeft tot doel om het bewustzijn te vergroten binnen organisaties en vooral binnen ontwikkelteams. Maar ze doen veel meer dan het publiceren en onderhouden van deze top-10.

Ze ontwikkelen verschillende applicaties en tools op het gebied van security. De OWASP Dependecy Checker is daar een voorbeeld van. Deze stelt je in staat om van alle dependencies van je project te controleren of er kwetsbaarheden bekend zijn in de NVD (Nationale Kwetsbaarheden Database) en wat deze inhouden. En naar welke versie je moet upgraden om er niet meer vatbaar voor te zijn. Tot voor kort heb ik geen inspanning gedaan om de afhankelijkheden van mijn projecten gestructureerd tegen het licht te houden. Het gebruik van dependencies met bekende kwetsbaarheden staat overigens op plek 9 in de OWASP top-10 van 2017.

Tijdens Devoxx Antwerpen afgelopen november zag ik deze presentatie van Julien Topçu getiteld: “Find and Track the hidden vulnerabilities inside your dependencies”. En ik was verkocht. Hoe is het mogelijk dat ik een dergelijke belangrijke tool niet eerder ingezet heb in onze buildstraat? Thuisgekomen ben ik meteen gaan experimenteren met de eenvoudigste, eerste stap: laat de maven plugin maar eens zien welke vulnerabilities er in onze dependencies zitten. Documentatie over de plugin was wat lastig te vinden, maar even doorzetten, en dan vindt je wel het een en ander. Proefondervindelijk kwam ik erachter dat versie 4.x bedoeld is voor gebruik met Java 8 en nieuwer, terwijl 3.x draait op oudere Java versies. En je hebt internet nodig in je buildstraat, want de plugin gaat periodiek de NVD downloaden.

Het inzetten van de plugin blijkt een appeltje en een eitje, het echte werk zit erin om vast te stellen in hoeverre jouw software geraakt wordt door een gevonden veiligheidsprobleem. Je moet de kwetsbaarheid analyseren en inschatten hoe een hacker hier misbruik van kan maken. Het is niet ondenkbaar dat je dit verkeerd inschat. Het heeft daarom mijn voorkeur om elke kwetsbare dependency op te waarderen naar een versie, indien beschikbaar, waarin dit is opgelost. Dit kan aanpassingen aan je eigen code vergen, wanneer de nieuwe versie API wijzigingen heeft.

Dependency checker probeert van elke dependency de naam, leverancier en versie te bepalen. De manier waarop dit gebeurt kan fouten opleveren. Ik heb bij een klant gemerkt dat een aantal bibliotheken, die het bedrijf zelf maakt en alleen intern distribueert, herkent werden als een open source dependency die kwetsbaarheden bevat. Een ‘false positive’ dus. Je kunt aan de maven plugin een lijst met deze ‘false positives’ doorgeven, om het proces te helpen. Via het HTML rapport dat dependency checker oplevert, kun je van een false positive eenvoudig een entry genereren voor deze lijst.

Wanneer je de tool nieuw inzet op een project en je een achterstand hebt weggewerkt aan gevonden kwetsbare dependencies, is het zaak om na te denken hoe je deze tool structureel wilt inzetten in je buildstraat. Hou er rekening mee dat deze plugin bij multi module projecten al snel enkele minuten aan de feedbackloop toe zal voegen. Daarnaast moet je je realiseren dat de aangetroffen kwetsbaarheden niet alleen afhankelijk zijn van de dependencies die het project gebruikt, maar ook van de bugs die in de NVD gepubliceerd worden. Dit kan er voor zorgen dat kwetsbaarheden in legacy applicaties, waar slechts incidenteel onderhoud aan gepleegd wordt, lang onopgemerkt kunnen blijven. Het is daarom raadzaam om de dependency check voor ieder project dagelijks in een eigen job te draaien.

Vooral bij grotere organisaties komt het voor dat de gevonden kwetsbaarheden buiten het ontwikkelteam gerapporteerd moeten worden, bijv. aan een security afdeling. Als het team inschat dat de gevonden kwetsbaarheid in de dependency op geen enkele manier misbruikt kan worden, dan wil de security afdeling deze argumentatie ook weten. Voor deze administratie kan gebruik gemaakt worden van de applicatie Dependency-Track of via een SonarQube plugin. Allebei zijn Open Source projecten van OWASP.

Als jouw project nog geen tooling gebruikt om haar afhankelijkheden te controleren op bekende kwetsbaarheden uit de NVD database, dan raad ik aan om OWASP dependency checker zeker uit te proberen. “Protect yourself at all times”.

XB4J: de Kadaster casus

Het moet een late vrijdagmiddag zijn geweest, eind augustus 2017. De exacte datum weet ik niet meer. Ik zit naast Mando, de consultant die we hebben ingehuurd om onze JAXB-kennis te versterken. Ik kijk toe hoe hij behendig met zijn debugger door de JAXB-broncode stapt. We onderzoeken al de hele middag hoe we om de bug heen kunnen werken. Verschillende ideeën zijn opgekomen, maar niet één die ons heeft overtuigt de juiste te zijn. Eigenlijk geloof ik er niet meer in dat JAXB voor dit project de juiste oplossing is. Niet met de voorwaarden die we hebben gesteld: geen code duplicatie. Niet in de gegenereerde Java klassen, maar ook niet in de Java code die de transformatie verzorgt.

Mijn geloof zit deze week in een vrije val. Begin november stopt het Kadaster met de levering van hun SOAP bericht Kik-inzage versie 4.7. We hebben nog maar twee maanden om onze software om te schrijven en hun nieuwe versie 5.1 te gebruiken. Nog twee maanden! We zijn nu twee maanden bezig en maken veel te weinig voortgang; we hebben een technologische keuze gemaakt (JAXB versus XSLT), en zijn begonnen met de implementatie. That’s it. En dan lopen we ook nog tegen die blokkerende bug aan in JAXB. Lukt het niet om begin november klaar te zijn, dan zullen de Gemeentelijke Sociale Diensten, onze klanten, geen kadastrale gegevens van ons krijgen, die ze nodig hebben voor de beoordeling van aanvragen voor bijstandsuitkeringen. Het zou een groot gezichtsverlies betekenen voor ons bedrijf.

Ik zucht en haal nog een rondje koffie. Als iedereen zijn drankje heeft, keer ik achter mijn eigen bureau terug. Ik mompel tegen Mando dat ik nog even iets wil uitzoeken. In werkelijkheid wil ik verder met mijn proof of concept waar ik een paar dagen geleden aan begonnen ben. Voor het Kik-inzage bericht, maar dan met een andere techniek: XB4J. Een kleine, open source bibliotheek die net als JAXB bedoeld is om XML naar Java om te zetten en vice versa. Ik heb het een aantal jaar geleden zelf ontwikkeld. Het is gespecialiseerd in de problematiek waar we nu met JAXB door een bug gestopt worden. Ik weet dat het met XB4J moet kunnen, maar ik weet ook dat er tijd in geïnvesteerd moet worden, zodat het de complexiteit van het Kadaster bericht ondersteunt. En ik was er niet aan toe om mijn vrije tijd hieraan te wijden. Maar ik zie geen alternatieven meer.

Het duurt niet lang of ik zit in een flow. In Eclipse heb ik de Java klasse openstaan waarin ik programmeer hoe XB4J de Java representatie koppelt aan de XML-representatie, het zogenaamde ‘binding model’. Veel informatie die we van Kadaster geleverd krijgen, gebruiken we niet. Met een Ignore-binding vertel ik dit aan XB4J. Voor de proof of concept gebruik ik voor elke XML-entiteit even de Ignore-binding, om de structuur snel gemodelleerd te hebben. Daarna kan ik verfijning aanbrengen en één voor één de entiteiten die we nodig hebben aan Java representaties van de XML koppelen. Het is een monnikenwerk en ik begrijp de charme van JAXB wel. Voor de drie Kadaster operaties heeft JAXB binnen drie seconden de meer dan 1500 klassen gegenereerd die het denkt nodig te hebben. JAXB genereert veel klassen dubbel vanwege de manier waarop het Kadaster met zijn XML namespaces omgaat. Door de bug in JAXB lukt het niet om in alle constructies die Kadaster hanteert, de dubbelen betrouwbaar terug te brengen. Met als resultaat dat tijdens het ummarshallen van een bericht gegevens verloren gaan, zonder dat er een foutmelding optreedt.

Ik denk dat we met XB4J slechts een vuistvol Java klassen nodig hebben om de informatie vast te leggen die we van het Kadaster nodig hebben. XB4J genereert ze niet, als ontwikkelaar moet je die zelf schrijven. Voor de proof of concept wil ik de NatuurlijkPersoon klasse schrijven en deze koppelen aan de twee XML-representaties die in de eerste operatie van het Kadaster-bericht voorkomen. Ze komen ook nog twee keer voor in de twee andere operaties, maar daar hergebruik ik dezelfde NatuurlijkPersoon klasse. We moeten wel telkens weer de bindingmodel vertellen dat deze Java klassen ook gekoppeld moeten worden aan elementen in andere XML namespaces. Het zou lekker zijn als er tooling was, die ondersteunde bij het maken van het binding model. Een tool die de WSDL of XML-schema zou lezen en waarmee je via een GUI kunt aangeven hoe de XML elementen gekoppeld moeten worden aan welke Java klassen en attributen. Dat zou het werken met XB4J een stuk prettiger maken. Maar die tooling moet nog geschreven worden.

De maandag daarna, op de laatste dag van de sprint, kan ik de proof of concept aan het team presenteren. Ik heb in het weekeinde gewerkt om XB4J aan te passen, zodat de constructie met ‘unbounded choices’ in het kadaster bericht ondersteund wordt. Via een geautomatiseerde test kan ik laten zien dat een XML bericht naar een Java representatie wordt omgezet en weer terug naar XML. Er gaan geen gegevens verloren, zoals dat wel het geval is met JAXB. Mijn beide collega ontwikkelaars zijn kritisch, maar enthousiast. Ook Mando heeft het weekeinde nuttig besteed en heeft een oplossing gevonden waarmee om het probleem in JAXB heen gewerkt kan worden. Zijn aanpak grijpt in op het unmarshall-proces: het verandert de namespace van de XML-elementen die problemen geven, in de namespace variant die voor dat element geen probleem geeft, voordat JAXB ze omzet naar Java instanties. Het vereist het vastleggen in de code van alle namespaces en element combinaties die problemen geven.

‘s Middags bespreken we met het hele team de voor- en nadelen van JAXB en XB4J, en spreken we uit in welke techniek we het meest vertrouwen hebben om het nieuwe Kadaster bericht te implementeren. Na een levendige discussie kan iedereen zich vinden in een keuze voor XB4J. De doorslag wordt gegeven door de volgende argumenten:

  1. XB4J koppelt de Java representatie los van het XML-schema, waardoor hergebruik van de Java code (en alles wat daarvan afhankelijk is, zoals transformaties etc.) makkelijker te realiseren is. Het lijkt daarmee ook een robuustere oplossing, omdat bij toekomstige versies van het Kadaster bericht, de schema wijzigingen in het bindingmodel opgevangen kunnen worden.
  2. Het team schat in dat XB4J een veel lagere leercurve heeft dan JAXB.
  3. Het vertrouwen in JAXB is gedaald: wie weet welke verrassingen ons nog meer te wachten staan?

De komende sprints gaan we met XB4J aan de slag. Mijn collega ontwikkelaars schrijven de binding modellen en de Java klassen, terwijl ik hun verbetervoorstellen in XB4J verwerk en oplossingen implementeer voor de problemen waar ze tegenaan lopen. De product backlog wordt opnieuw ingeschat en er wordt een ‘minimal viable product’ gedefinieerd op basis van informatie van eindgebruikers. Het schrijven van de binding modellen geeft extra werk vergeleken met JAXB, maar ze zijn met een voorspelbaar tempo te implementeren. Van Kadaster komt het bericht dat uitfasering van versie 4.7 uitgesteld wordt. Eerst wordt gesproken over december, daarna geven ze aan dat ze eind januari 2018 een definitieve einddatum zullen communiceren. Het lijkt erop dat we niet de enige afnemer van het bericht zijn die moeite heeft met de integratie van versie 5.1 in haar systemen. Eind september schatten we in dat we onze software tussen half januari en half februari 2018 helemaal aangepast hebben naar de nieuwe berichtversie. Een schatting die we niet meer aan hoeven passen. Ruim op tijd vóór vrijdag 13 april, de datum die het Kadaster definitief heeft vastgesteld als einddatum voor versie 4.7.

Nawoord

De broncode van XB4J staat op Github. Het project kan via Maven Central als afhankelijkheid in je project worden opgenomen. De ervaringen in het team waren overwegend positief. Ontwikkelaars die niet eerder met XB4J gewerkt hebben, waren snel productief. Het was daarbij wel belangrijk dat ze van een voorbeeld af konden kijken. De foutmelding die XB4J geeft, wanneer het binding model de berichtstructuur niet goed beschrijft is cryptisch. Oplossen daarvan kost tijd. Via logging is wel snel duidelijk wat het probleem is, maar de foutmelding moet gewoon beter. En het schrijven van een binding model blijft monnikenwerk. Naar aanleiding van de toepassing van XB4J in dit project heb ik de volgende prioriteiten opgesteld voor de verdere ontwikkeling:

  1. Voeg gebruikersdocumentatie toe met voorbeelden.
  2. Werk aan tooling om de ontwikkelaar te ontlasten bij het schrijven van een binding model.
  3. Verbeter de foutmeldingen wanneer de bindings niet helemaal overeenkomen met de berichtstructuur.
  4. Implementeer alle functionaliteiten die mogelijk zijn volgens de XML-schema specificaties.
  5. Verbeter de API, bijv. door gebruik te maken van builders of een DSL.

Laat me weten wat jouw ervaringen zijn met XB4J.