Hacken doe je zo!
Omdat inbreken op computers via e-mail steeds lastiger wordt, proberen hackers het tegenwoordig meer en meer via het web door middel van zogenaamde SQL injection attacks. De auteur laat zien hoe eenvoudig dergelijke aanvallen uit te voeren zijn.
Tegenwoordig komen we niet zomaar meer via het e-mailsysteem binnen op een computer. Dat wil zeggen dat we geen gekke e-mailtjes meer kunnen sturen om daarmee in te breken op een computer. Daarom probeert men het tegenwoordig meer en meer via het web. Een hiervoor gebruikte techniek die verbazend eenvoudig is, gaat schuil achter de illustere naam SQL injection attack. En deze techniek werkt ook als systeembeheerders elke security-patch meteen implementeren, de nieuwste versies van de onderliggende databasesysteemsoftware hebben, enzovoort. Dit komt omdat men tegenwoordig niet meer probeert via lekken in een databasemanagementsysteem of besturingssysteem binnen te komen, maar via de voordeur: de webapplicatie zelf.
Wat is er zoal nodig voor een SQL injection attack? Ten eerste een willekeurige webbrowser. En ten tweede verstand van gegevensverwerking op elke universiteit te bekomen. Hier volgt een spoedcursus.
SQL betekent Standard Query Language; het is een taal waarmee we alles met gegevens kunnen doen: gegevens creeren, opvragen, manipuleren en weggooien. Hacken klinkt als een soort zwarte magie, alleen weggelegd voor diegenen die de diepste diepten van een computer kunnen beroeren. Vandaar wat 'hacksuele' voorlichting. Het woord injection staat voor het zelf inbrengen van SQL-commando's door gebruik te maken van een onachtzaam gebouwde webapplicatie.
Een attack uitvoeren Laten we eens kijken naar de magie van het inloggen; de realiteit is veel simpeler dan u durft te vermoeden. Op vrijwel elke website zijn tegenwoordig logindialogen te vinden. Gelukkig hebben we bij slechte software helemaal geen login nodig om binnen te komen. Het eerste wat we doen, is checken of de website slecht ontworpen is. Dat is te testen door een apostrof of het woord OR in te tikken en dan te kijken wat er gebeurt. Als er dan een foutmelding verschijnt die door het databasemanagementsysteem is gegenereerd, is de applicatie mogelijk kwetsbaar. De foutmelding geeft namelijk aan dat een SQL-commando incorrect was en is zo vriendelijk ons daarop te wijzen: Unclosed quotation mark before character string ")'.
We weten nu twee dingen: ten eerste dat we een SQL-commando hebben kunnen geven, dus onze eerste SQL-injection is een feit; ten tweede dat het een incorrect commando was, met een vriendelijke suggestie dat we voortaan wel een afsluitend aanhalingsteken moeten gebruiken. Al doende kunnen we dan allerlei SQL-commando's gaan injecteren.
Inloggen zonder wachtwoord Stel dat we voorbij een loginprocedure willen komen. De simpelste methode, die verbazingwekkend vaak werkt, gaat als volgt. Neem zowel voor de loginnaam als het wachtwoord deze incantatie: ` OR "1=1' (of een variant daarvan). Als we geluk hebben, zijn we dan al binnen. Hoe? De webapplicatie test normaliter of de loginnaam klopt en bij het wachtwoord hoort. Alleen nu hebben we wat extra SQL geinjecteerd zodat de applicatie een andere query uitvoert dan die de amateur bijvoorbeeld met de volgende code heeft bedoeld:
SELECT LoginName FROM Users WHERE LoginName = ` " & strLoginName & " ` AND Password = ` " & strPassword & " ` "
De variabelen strLoginName en strPassword worden vervangen door onze toverformule, wat leidt tot het volgende SQL-commando dat zal worden uitgevoerd:
SELECT LoginName FROM Users WHERE LoginName = `' OR `'1=1'' AND Password = `' OR `'1=1''
Dit betekent dat de WHERE-conditie altijd WAAR is. Kijk maar: de LoginName wordt vergeleken met een lege string die wordt gerepresenteerd door twee aanhalingstekens, niet WAAR dus. Maar we hebben ook een altijd ware bewering geinjecteerd: 1=1. En de OR is inclusief, wat zoveel betekent dat als een van de twee beweringen WAAR is, het geheel WAAR is. Dus de tweede regel code levert WAAR op. Idem voor de vierde regel code, en WAAR AND WAAR is weer WAAR. Dus de test om in te loggen is geslaagd, ondanks het feit dat we geen enkele loginnaam of wachtwoord hebben ingetoetst. Nu hebben we dus toegang tot het beschermde gedeelte van de website.
Toegang tot alle gegevens Laten we de zaak iets ingewikkelder maken. We willen toegang tot alle gegevens en bij onachtzaam gemaakte applicaties is dat een kwestie van even doorwerken. Tegenwoordig zien we allerlei ingewikkelde webadressen met vraagtekens en cijfercodes erin, adressen die eindigen op bijvoorbeeld default.asp?id=10. Bij slecht ontworpen software kunnen we daarachter gemakkelijk onze eigen commando's toevoegen. Na de 10 in het webadres voeren we in: UNION SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLES. Een hele mond vol, maar dit betekent niets anders dan: voer het bedoelde commando met het getal 10 gewoon uit, maar combineer dat met ons commando dat de eerste naam van de tabel moet geven die op de daarvoor bestemde plek staat van elk gegevensverwerkend systeem. Handig, die open standaarden! Dit geeft vrijwel zeker weer een foutmelding, maar in die foutmelding staat wel de gevraagde tabelnaam.
Hoe zit dat? Ons commando hoest de naam van de tabel gewoon op, maar die naam is geen getal, dus als SQL dat combineert (via UNION) met het getal 10, zijn we appels met peren aan het vergelijken en dat is fout. Er volgt een foutmelding die ons daarop wijst: Syntax error converting the nvarchar value `naam' to a column of data type int. En de naam tussen aanhalingstekens is net wat we zochten.
Communicatie via foutmeldingen Van die fout leren we de naam van de eerste tabel van het systeem. Nu de tweede naam. Het is een variatie op hetzelfde thema: voeg aan de bovenstaande UNION nog een extra dosis toe, namelijk "WHERE TABLE_NAME NOT IN (`naam'). Dat geeft weer een foutmelding, want 10 is nog steeds een getal en de volgende tabelnaam is nog steeds geen getal. In de foutmelding vinden we dan de tweede naam. Op die manier kunnen we doorgaan met injecteren tot we alle tabelnamen hebben. Dit simpele trucje heet ook wel database footprinting. Wat u nu in werking ziet, is het principe van communicatie met de webapplicatie via foutmeldingen. Dat is een mooie manier om dingen te weten te komen die anders niet prijsgegeven worden.
Een database is om dingen op te zoeken, ook als je niet helemaal weet hoe alles ook weer gespeld was. We willen bijvoorbeeld een tabel vinden waarin de loginnamen van gebruikers staan. Dan voegen we een ander stukje code, dat omwille van de leesbaarheid iets versimpeld is, aan onze injectie toe: WHERE TABLE_NAME LIKE `login'. Dit zal weer een foutmelding opleveren: Syntax error converting the nvarchar value `admin_login' to a column of data type int. De naam van de tabel waarin hoogstwaarschijnlijk de logingegevens van de gegevensbeheerder staan, is dus admin_login. We dienen weer een SQL-injectie toe: UNION SELECT TOP 1 login_name FROM admin_login. Ook deze zal weer een foutmelding geven, omdat die naam geen getal is: Syntax error converting the nvarchar value `B1FF' to a column of data type int. Er is kennelijk een gegevensbeheerder met loginnaam B1FF.
We zijn nu halverwege, net als de kluizenexpert die laatst een oude kluis van De Nederlandsche Bank in twee rondes wist open te krijgen door te luisteren naar onregelmatigheden in de cijfersloten. Wij luisteren ook naar onregelmatigheden van de webapplicatie door middel van een nieuwe injectie: UNION SELECT TOP 1 password FROM admin_login WHERE login_name='B1FF'. Weer een foutmelding: Syntax error converting the nvarchar value `DEADBEEF' to a column of data type int.
Eigen account maken Nu zouden we kunnen inloggen met de naam B1FF en het wachtwoord DEADBEEF, maar het is niet zo handig om dat te doen. Beter is het om een eigen account aan te maken, want B1FF zal vroeg of laat merken dat er iets aan de hand is. Om een eigen account te maken moeten we weten welke kolommen er in de tabel admin_login zitten. Dat is fase twee van database footprinting: alle kolommen van een tabel boven water krijgen. Injecteer dit: UNION SELECT TOP 1 COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME= `admin_login'. Dat geeft weer een foutmelding: Syntax error converting the nvarchar value `login_id' to a column of data type int. Daarna kunnen we weer de volgende melding genereren door een WHERE-conditie toe te voegen, en zo gaat het verder.
Gewapend met precieze kennis van de databasestructuur van de webapplicatie kunnen we dan met een SQL-injectie een INSERT-commando geven dat ons als gegevensbeheerder toevoegt. En dan kunnen we aan het werk: alle data zijn tot onze beschikking, we kunnen gegevens toevoegen, ophalen, veranderen, weggooien, enzovoort. En dat alles met een willekeurige browser en wat `hacksuele' voorlichting.
De proef op de som Karin Spaink (2005) publiceerde onlangs in de Volkskrant dat ze via SQL injection twee weken lang 1,2 miljoen patientengegevens tot haar beschikking had, zonder dat iemand dat in het ziekenhuis was opgevallen---namen, adressen, telefoonnummers, patientnummers, polisnummers, geslacht, geboortedatum, lengte, gewicht, dood of levend, inclusief een lijst met patienten die een besmettelijke ziekte hadden.
Het echte probleem
Inputvalidatie
Het echte probleem is natuurlijk de webapplicatie en niet de hacker, want zoals u ziet: een kind kan de was doen. Als het nieuwe software betreft, is die gemaakt door mensen die de beginselen van het maken van productiesoftware niet machtig zijn. Bij de absolute basiskennis hoort namelijk dat je altijd alle input moet valideren en alleen die input moet doorlaten waarvan jij wilt dat die doorgelaten wordt. Dat voorkomt crashen, dataverlies en SQL injection attacks.
Maar niet alle software is nieuw. Sterker nog, meer dan 60 procent van alle data die via het web toegankelijk zijn, staan op een mainframe. Die data zijn ook vaak waardevol: meer dan 95 procent van de gegevens in de financiele sector en de verzekeringssector wordt met Cobol en embedded SQL verwerkt. Die software is niet ontworpen om dit soort aanvallen af te slaan. En als men achteraf bedenkt dat alle input nog even moet worden gevalideerd, is het een verloren race, want dat ontwerp je er niet nog even in. Het is dan ook geen verrassing dat we onlangs berichten hoorden van diefstal van miljoenen creditcardgegevens. Nu spreekt hacken tot de verbeelding, maar het echte probleem is dat een groot percentage van de fraude afkomstig is van eigen personeel. Binnen een organisatie heeft men gemakkelijk toegang tot intranetapplicaties en personeel kan via de genoemde SQL-injectionprincipes ongeautoriseerd toegang krijgen tot allerlei gegevens. Vaker nog is de beveiliging intern helemaal afwezig en loopt men dus gewoon binnen bij zo'n systeem. En we weten dat personeel dat data invoert gemakkelijk omkoopbaar is: voor 25 dollar waren jarenlang de complete salarisgegevens van de laatste tien jaar van een toekomstige werknemer op te vragen bij belastingmedewerkers, zodat je heel scherpe salarisonderhandelingen kon voeren.
Besluitvormers Wat zeer verontrustend is aan dit soort zaken is dat besluitvormers elke poging om privacy en security aan de kaak te stellen bagatelliseren (Verhoef, 2005). Zo stuurde het gehackte ziekenhuis voor de evaluatie een systeembeheerder, waar het hoogste management meer op zijn plaats was geweest. Men doet dit af als een computerfoutje dat ZE nog even gaan oplossen. En alle deadlines blijven overeind, want in 99 procent van de gevallen gaat het goed.
Ten eerste: het gaat hier niet om een computerfoutje. We hebben het hier over inherent volkomen verkeerd ontworpen software, door mensen zonder benul van de meest elementaire softwareengineeringprincipes, die bewezen hebben alle elementaire kennis te ontberen die nodig is voor de productie van veilige privacybeschermende gegevensverwerkende systemen. Dat is de fout van de besluitvormers die kiezen voor de laagste prijs en die geen idee hebben van de werkelijke eisen die aan hun systemen gesteld moeten worden.
Ten tweede: ZE gaan helemaal niets oplossen! ZE hebben allereerst uiterst belangrijke ontwerpbeslissingen gemist. En het is schier onmogelijk om dergelijke ingrijpende ontwerpbeslissingen achteraf even weg te poetsen. Laat staan door amateurs. Ga maar na: inputvalidatie komt overal in systemen voor. Tegenwoordig is het merendeel van administratieve systemen gewijd aan de gebruikersinterface en daarin komt input en output van gegevens veelvuldig voor. Op elke plek, in elk veldje, bij elk vraagje dat het systeem zou kunnen stellen aan een gebruiker, moet je iets, en ook nog op plekken waar je dacht dat je niets vroeg. Ergo, het hele ontwerp moet op z'n kop. Dat lukt ZE dus niet. Maar besluitvormers zijn dusdanig amateuristisch dat ze het verschil tussen een beunhaas en een gelicentieerde it-professionali niet zien.
Ten derde: de meeste besluitvormers hebben geen bal verstand van het managen van it. Kijk maar naar de deadlines die ze uitkramen: 1 januari 2006, voor de Kerst, 5 december krijg je een cadeautje. Het gaat altijd om ronde of bijzondere datums. Dat noem ik fantasy deadlines. Als je niet de meest geeigende productiemethode kunt gebruiken, wordt productie altijd duurder en slechter, dat is algemeen bekend. Ook bij it: in 1984 is een wetmatigheid ontdekt die laat zien dat van te veel it-werk in te korte tijd de kosten explosief stijgen en daarmee ook de risico's. Besluitvormers die aan deadlines vasthouden terwijl de hele tent binnenstebuiten moet, weten dat dus niet. De kosten zullen dan enorm stijgen, de kwaliteit keldert, de risico's nemen toe---en dat zien ze niet aankomen. Kortom: amateurs. Wegwezen dus!
Conclusie Productie van software in verkeerde handen is heel gevaarlijk. En omdat onze privacygevoelige gegevens tegenwoordig in allerlei softwaresystemen huizen, moeten we als burgers geen genoegen nemen met amateurs. Het recente voorbeeld van de patientengevens onderstreept dat alleen maar. Alleen gelicentieerde it-professionals die software kunnen produceren, managen en beheren zijn goed genoeg, en de rest: wegwezen.
Chris Verhoef
Literatuur Spaink, K. (2005). Het medisch geheim gehackt. de Volkskrant, 3 september 2005.
Verhoef, C. (2005). Nog even en elke dag is gehackt-dag. de Volkskrant, 10 september 2005.
Prof. dr. Chris Verhoef is hoogleraar Informatica bij de afdeling Informatica van de Vrije Universiteit Amsterdam. E-mail: x@cs.vu.nl.
Samenvatting Een SQL injection attack is een techniek om via het web binnen te komen in computersystemen met behulp van het principe van communicatie met de webapplicatie via foutmeldingen. Het echte probleem is echter niet de hacker maar een onvoldoende inputvalidatie voor de webapplicatie en gebrekkige beveiliging tegen fraude door personeel. Zeer verontrustend is dat besluitvormers deze problemen bagatelliseren.
COPYRIGHT: SDU
|