Hacken doe je zo

PDF Versie

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.

Meer weten over de wondere wereld van ICT 
in Jip en Janneke taal? Ga dan naar de
knipselkrant van Chris Verhoef

Deze tekst is copyright SDU.  Niets van deze uitgave 
mag zonder schriftelijke toestemming van de uitgever
worden overgenomen of worden gepubliceerd.