J2EE Beveiligingsvalkuilen 18-11-2005

Beveiliging aan de bron

door Jan Kampherbeek

Gebruikersnaam invullen, wachtwoord intoetsen en op enter drukken. Het is de meest gebruikelijke, bekende en eenvoudige vorm van applicatiebeveiliging. En eenmaal in het systeem aangekomen, is het van absoluut belang ook paden van gebruikers vakkundig af te bakenen. Voorkom bijvoorbeeld dat zij inzicht krijgen in elkaars sessies en maak het onmogelijk vaste databasestructuren te bewerken. Authenticatie en authorisatie: een onderdeel waarin J2EE verscheidene technieken kent om een zekere veiligheid te garanderen. Maar waarbij de database zelf - waar het eigenlijk om gaat – helaas nog vaak onvoldoende beschermd blijkt. Een verhandeling over valkuilen en risicovermindering bij het implementeren van betrouwbare J2EE-security.

Declaratieve en programmatische authorisatie
In J2EE bevinden zich een flinke hoeveelheid technieken voor beveiliging. Het is bijvoorbeeld vrij eenvoudig de authenticiteit (wie is ingelogd) tijdens sessies te bewaren, en relatief simpel om vast te leggen wat deze medewerker wel en niet mag doen (de authorisatie). Ook afdwingen dat alle onderdelen van een applicatie zich aan de beveiligingsregels conformeren, is snel te realiseren. J2EE gebruikt daarvoor de zogenoemde declaratieve authorisatie. De ‘container’ zorgt er daarbij voor dat alle objecten in een bepaald domein de ingestelde beveiliging hanteren. En de domeinen zijn op hun beurt – samen met de bijbehorende beveiliging – weer af te bakenen in een xml-bestand: de deployment descriptor. Belangrijk is hier de declaratieve authorisatie te gebruiken. Deze vormt de basis voor de beveiliging van een domein, óók als nieuwe objecten worden toegevoegd, zodat de beveiliging intact blijft.

J2EE maakt verder óók gebruik van programmatische authorisatie, de programmeur legt hierbij de regels zelf vast. Breekpunt is wel dat de beveiliging valt of staat met de zorgvuldigheid van de programmeur. Het is daarom veiliger uit te gaan van de declaratieve authorisatie en de programmatische authorisatie alleen te gebruiken als aanvulling.

J2EE biedt op het eerste oog zo voldoende mogelijkheden voor het implementeren van betrouwbare security. Waar zit nu het probleem?

Grenzen aan de beveiliging
Een J2EE-applicatie 'leeft' in een container. Een container is de kern van een applicatieserver. Deze server controleert wat in de container gebeurt en zorgt voor ondersteuning van allerlei processen. Ook zorgt de container voor het toepassen van declaratieve authorisatie. So far, so good. Maar de container bepaalt ook de grenzen van de applicatie en daarmee de grenzen van de beveiliging. Sterker, in de J2EE-specificaties is vastgesteld dat de container de grens vormt voor het gebied waarvoor de authenticatie geldt. De beveiliging blijft dus beperkt tot binnen de container, terwijl daarbuiten zich de resources bevinden die we zouden willen beveiligen. Waaronder de belangrijkste resource: de database.

Database en J2EE
Databases hebben prima beveiligingsstructuren. Oracle kent als geen ander een goede ondersteuning voor authenticatie, rollen en rechten. Een J2EE-omgeving maakt daar alleen zelden tot geen gebruik van. Dat komt niet in de laatste plaats omdat iemand die bekend is in J2EE, in de regel niet bekend is in de Oracle-omgeving. In de J2EE-omgeving zijn namelijk doorgaans de authenticatiegegevens van één 'virtuele' Oracle user opgeslagen, samen met het adres van de Oracle-database (bijvoorbeeld in het bestand datasource.xml). De applicatie gebruikt deze gegevens om in te loggen op de database. Waarbij die virtuele inlog dan niet voor een persoon staat, maar uitsluitend wordt gebruikt om contact te kunnen leggen met die database.

Een voorbeeld:
Accountmanager Jelle wil een overzicht van alle medewerkers. De gegevens bereikt hij via de J2EE-applicatie HR-management. Deze applicatie gebruikt een Oracle-database waarin de op te vragen gegevens staan. In Oracle zijn die gegevens opgeslagen binnen het schema (werkgebied) HR-user.
Jelle meldt zich via z’n webbrowser aan bij HR-management als 'Jelle' en zijn persoonlijke wachtwoord 'geheim'. Omdat zijn naam en wachtwoord bekend zijn, verloopt het inloggen uitstekend. Jelle is nu door de authenticatie heen. Als hij de menufunctie 'Overzicht medewerkers' aanklikt, gaat dat ook goed, hij is geautoriseerd tot deze handeling.

De J2EE-applicatie haalt nu de gegevens uit de database op. Om toegang te krijgen, haalt de applicatieserver gegevens over de 'datasource' op waarin de naam en locatie van de Oracle-database, de inlognaam en het wachtwoord staan. De applicatie vindt daar de naam 'HR-user' en het wachtwoord 'secret'. Daarmee komt een verbinding tot stand met de Oracle-database. Jelle logt dus feitelijk als ‘Jelle’ aan op de J2EE-omgeving en – indirect – als ‘HR-user’ op de database.

Risico
De zorgvuldig opgebouwde beveiligingsstructuur rondom Jelle in de in de Oracle-database (het MT wil hem geen inzicht in de medewerkers geven), is wegens onwetendheid van de programmeur binnen de J2EE-applicatie in dit voorbeeld onbekend. En aangezien de inlognaam tot de database (HR-user) voor meerdere of zelfs alle medewerkers die inloggen op de J2EE-applicatie gelijk is, passeert hij nu de voorzieningen die tegen hem getroffen zijn.

Slordige programmeurs en alternatieve routes
Niets menselijks is ze vreemd: ook programmeurs kúnnen fouten maken. Door bijvoorbeeld een verkeerde tabel gebruiken, kan gevoelige (bedrijfskritische) informatie onbedoeld zichtbaar zijn. En door onwetendheid zoals in boven geschetst voorbeeld, kan de database via de authenticatie voor een virtuele HR-user, allerhande – voor één specifieke user afgeschermde – informatie toch prijsgeven. Minstens zo gevaarlijk als nalatigheid in programmeerwerk binnen J2EE, zijn bovendien de alternatieve routes naar de database. Je kunt de database met J2EE benaderen, maar hij is bijvoorbeeld ook te benaderen via SQL*Plus, of via een andere omgeving die je met PHP zeer snel kunt opzetten. Het enige wat je hoeft te weten, zijn de naam en locatie van de database, de naam ‘HR-user’ en het wachtwoord. En die zijn eenvoudig te vinden in een xml-bestand (bijvoorbeeld datasource.xml) dat elke programmeur op zijn/haar computer heeft staan.

De alternatieve routes zijn het grootste gevaar. Een hacker zal niet veel moeite hebben de benodigde informatie te vinden. Basiskennis via SQL is dan voldoende om de data in de database te benaderen.

Checklist: verminderen van risico
Risico's zijn sterk te minimaliseren. Aan de hand van onderstaande checklist ben je zeker van dat aan alle basisveiligheidseisen is voldaan.

- Een Oracle-user die een tabel maakt, is 'owner' en heeft automatisch alle rechten voor die tabel. Zorg dat de owner nooit wordt gebruikt om toegang te krijgen vanuit de J2EE-omgeving. Laat de owner beperkte rechten toekennen (grant) aan de HR-user.

- Koppel aan de virtuele inlog uitsluitend de relevante rechten op de juiste tabellen. Vaak zijn dat alleen lees-rechten.

- Gebruik voor de owner en de virtuele inlog(s) verschillende wachtwoorden.

- Overweeg meerdere virtuele inlogs - en schema's - aan te maken. Dat is vooral belangrijk als er duidelijk te onderscheiden rollen zijn.

- Wees voorzichtig met de namen en wachtwoorden van de virtuele inlogs. Zorg dat deze in de ontwikkelomgeving en de productieomgeving verschillend zijn. Anders is er een te grote groep mensen die een groot deel van de database kunnen benaderen.

- Beperk de fysieke toegang tot de databaseserver. Denk aan een afgesloten serverruimte en een goede inzet van een firewall.

Tot besluit: als je de J2EE-omgeving combineert met een Oracle Database kun je overwegen een Virtual Private Database (VPD) te gebruiken. De beveiligingsnadelen en risico's die ik in dit artikel schets, zijn daarmee voor een groot deel opgelost.

 
< Prev   Next >