Tabellen uit database verdwenen; SQL-injection?

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • BetuweKees
  • Registratie: Januari 2003
  • Laatst online: 15-07 20:53

BetuweKees

Flipje uit Tiel

Topicstarter
Hi,

Afgelopen weekend kwam ik er achter dat een van mijn sites niet meer naar behoren functioneerde. Enig onderzoek leerde me dat er een aantal tabellen uit de database verdwenen waren, toevalligerwijs de vier tabellen waarin middels PostGIS ook geo-data opgeslagen stond. Erg vervelend allemaal.

Volgens mijn hoster is er waarschijnlijk sprake geweest van een SQL-injection. Ik dacht dat ik me hiervoor door mijn manier van scripten redelijk goed beschermd had, maar toch graag nog een vraag aan jullie, want allicht dat ik toch ergens iets over het hoofd heb gezien. Daar kan ik (en allicht andere ook) dan weer wat van leren.

De flow van de requests verwerkt is ongeveer zo:

1. Er komt een request naar http://mijn.site/de/pagina/die/weergegeven/moet/worden/

2. In .htaccess wordt een lookup gedaan, de url dient een bepaald formaat te hebben (netjes afgetimmerd met formules als ([a-z_-]+), ([0-9]{4}) etc.In geen van de gebruikte urls mogen andere dan alfanumerieke tekens staan, dus geen slashes, quotes, of andere ongein. Wordt de url niet herkend dan volgt een 404.

3. In het PHP script wordt gekeken of de url tidy was (dus via .htaccess binnen is gekomen). Zo niet, dan 404.

4. Er volgt nogmaals een controle op de ingevoerde variabelen volgens dezelfde formule die ook in .htaccess gebruikt wordt. Niet goed? Dan 404.

5. Er wordt gekeken of de gebruiker ingelogd is. Zo niet, dan naar inlog scherm. (403)

6. Pas nu wordt met gecontroleerde variabelen en een ingelogde gebruiker, een sql query gemaakt en in de database gezocht.


Leek mij altijd lastig om daar nog op een of andere manier een injection tussendoor te krijgen, of zit ik mis?

Through meditation I program my heart to beat breakbeats and hum basslines on exhalation -Blackalicious || *BetuweKees was AFK; op de fiets richting China en verder


Acties:
  • 0 Henk 'm!

Verwijderd

Misschien heb je op je website ergens een formulier staan dat data via POST verzend en dat niet goed beveiligd is? (bvb escapen van input)

[ Voor 30% gewijzigd door Verwijderd op 13-09-2011 10:02 ]


Acties:
  • 0 Henk 'm!

  • Fish
  • Registratie: Juli 2002
  • Niet online

Fish

How much is the fish

Ik mis dit soort termen of vergelijkbare in dit topic http://php.net/manual/en/...ql-real-escape-string.php

Iperf


Acties:
  • 0 Henk 'm!

  • TJHeuvel
  • Registratie: Mei 2008
  • Niet online
Wellicht kan je eerst verifieren dat er inderdaad sprake was van SQL injection. Heb je geen SQL query log of iets dergelijks? Of anders een access log, hier staan misschien clues in wat er gebeurt kan zijn.

[ Voor 24% gewijzigd door TJHeuvel op 12-09-2011 22:33 ]

Freelance Unity3D developer


Acties:
  • 0 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
BetuweKees schreef op maandag 12 september 2011 @ 22:14:
Leek mij altijd lastig om daar nog op een of andere manier een injection tussendoor te krijgen, of zit ik mis?
Ja. Je hebt namelijk 0 escapes toegepast voor een sql context. Als je je queries met het handje maakt ben je gegarandeerd gevoelig voor sql injection.

Iets wat ik in ik denk tientallen topics per jaar zeg: Escapen doe je voor een bepaalde context. Er is geen magic bullet, en je moet op elke punt van alles bewust zijn. Voor wat betreft SQL schelen parameterized queries al een hele hoop.

Dat je wellicht gevoelig bent voor sql injection betekent overigens nog niet dat het is gebeurd: nofi, maar als dit al je beveiligingskennis is, zou iemand ook zo maar een willekeurig script kunnen laten uitvoeren. Maar goed, leren gaat stukje voor stukje, lees maar eerst meer over sql injection en escaping.

{signature}


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Waar hoort mijn topic?
WEB >> PRG

Verder met alle posters hierboven: Er is in je TS niets terug te lezen over POST en, way worse, al helemaal niets over het escapen van values. Doe je dat laatste niet dan kan je "6 stappenplan beveiliging" enkel de meest voor de hand liggende zaken misschien nog vangen maar dat is een disaster waiting to happen. Ongeacht wat je allemaal knutselt met .htaccessen, validatie van input etc. dien je gewoon per definitie te escapen (zoals hierboven gezegd: mits nodig en in de juiste context). Overweeg ook eens Parametrized Queries.
edit:
Oh, en zelfs dat laatste was al genoemd :P /laaaaaaaat

[ Voor 78% gewijzigd door RobIII op 12-09-2011 23:37 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
Wat voor soort hosting is het?

Want ik kan spuit11 spelen qua ontopic gehalte. Of ik kan je proberen te wijzen dat een sql-injection niet altijd van jouw afkomstig moet zijn als je shared hosting bij een crappy provider hebt.

Acties:
  • 0 Henk 'm!

  • Wijnbo
  • Registratie: December 2002
  • Laatst online: 06-09 20:35

Wijnbo

Electronica werkt op rook.

Nofi, maar dit klinkt een beetje alsof je het stukje hebt gemist dat SQL injection ook prima via invoervelden kan i.p.v. alleen via HTTP requests. (Wat overigens ook kan natuurlijk).

En zo zijn er nog een heleboel mogelijkheden.

Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 09:39

Janoz

Moderator Devschuur®

!litemod

@Wijnbo wat is er zo anders aan een invoerveld in vergelijking met een http request?

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

Verwijderd

Volgens mij bedoelt Wijnbo dat er nu enkel gecontroleerd wordt d.m.v een check op de url (HTTP-request, GET). Invoervelden kan je inderdaad ook doorsturen via een GET, maar ook via een POST. Het grote verschil is natuurlijk dat je via GET gewoon de url kan gaat hacken, terwijl je bij POST de invoervelden zal moeten aanpakken.

Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 09:39

Janoz

Moderator Devschuur®

!litemod

Maar een POST request is ook gewoon een http request ;)

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
Verwijderd schreef op dinsdag 13 september 2011 @ 10:04:
Het grote verschil is natuurlijk dat je via GET gewoon de url kan gaat hacken, terwijl je bij POST de invoervelden zal moeten aanpakken.
Het grote verschil? Scheelt max 2 seconden als je het met het handje doet (bv firebug) of uiteraard 0s als je het scripted doet.

{signature}


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Los van dit alles begrijp ik niet hoe je een tabel compleet kan verwijderen. Gezien het feit dat de topicstarter PHP gebruikt ga ik voor het gemak even uit van MySQL. Voor zover ik weet kun je met de standaardinstellingen maar één query per mysql_query-call doen. Dus tenzij er al een DROP-query in de site stond verdenk ik geen SQL-injectie maar script-injectie. :)

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • Spaceman Spiff
  • Registratie: Juli 2002
  • Laatst online: 19-12-2024
Buiten de vraag wel of geen SQL-injection om.
Heeft de database connectie (user) die de webserver maakt überhaupt rechten om DDL statements (drop table) uit te voeren?

Acties:
  • 0 Henk 'm!

  • Thralas
  • Registratie: December 2002
  • Laatst online: 14:27
NMe schreef op dinsdag 13 september 2011 @ 10:20:
Los van dit alles begrijp ik niet hoe je een tabel compleet kan verwijderen. Gezien het feit dat de topicstarter PHP gebruikt ga ik voor het gemak even uit van MySQL. Voor zover ik weet kun je met de standaardinstellingen maar één query per mysql_query-call doen. Dus tenzij er al een DROP-query in de site stond verdenk ik geen SQL-injectie maar script-injectie. :)
TS noemt PostGIS, dus dan zal 'ie wel PostgreSQL gebruiken ;)
Spaceman Spiff schreef op dinsdag 13 september 2011 @ 10:21:
Buiten de vraag wel of geen SQL-injection om.
Heeft de database connectie (user) die de webserver maakt überhaupt rechten om DDL statements (drop table) uit te voeren?
En zoja, waarom? :X

Acties:
  • 0 Henk 'm!

  • J2pc
  • Registratie: Oktober 2002
  • Niet online

J2pc

UT Tux Edition

Houd er ook rekening mee dat alles wat je van de client terug krijgt 'verdacht' is.

Ook dat lijstje (html select) wat je zelf hebt samengesteld, cookies of headers zijn zo aangepast (bv met firebug)

En al gebruik je zelf geen post, is het misschien wel mogelijk data te posten?
Gebruik je $_GET of $_REQUEST?
Bij $_REQUEST gaat de post voor de get variabelen (zie ook 'value shadowing').

[ Voor 14% gewijzigd door J2pc op 13-09-2011 10:47 ]

"The computer is incredibly fast, accurate, and stupid. Man is unbelievably slow, inaccurate, and brilliant. The marriage of the two is a challenge and opportunity beyond imagination." © Stuart G. Walesh


Acties:
  • 0 Henk 'm!

Verwijderd

Janoz schreef op dinsdag 13 september 2011 @ 10:07:
Maar een POST request is ook gewoon een http request ;)
Klopt!
Voutloos schreef op dinsdag 13 september 2011 @ 10:11:
[...]
Het grote verschil? Scheelt max 2 seconden als je het met het handje doet (bv firebug) of uiteraard 0s als je het scripted doet.
Zo bedoel ik het niet. Ik bedoel dat de TS zich enkel geconcentreerd heeft op het GET-gedeelte, terwijl beveiliging op POST-niveau uiteraard even belangrijk is!

Acties:
  • 0 Henk 'm!

  • Spiked
  • Registratie: Mei 2008
  • Laatst online: 24-07 14:50
Of misschien heeft de aanvaller een 'standaard' filename kunnen raden: /view/123/ is erg vaak view.php?id=123
Hier helpt je 'beveiliging' via .htaccess rules niet tegen.

Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Thralas schreef op dinsdag 13 september 2011 @ 10:34:
[...]


TS noemt PostGIS, dus dan zal 'ie wel PostgreSQL gebruiken ;)
Volgens mij geldt daar dezelfde beperking van één query per functiecall, toch? En inderdaad, het feit dat de databaseuser van de site een DROP mag doen is vrij knullig.

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Geen parameterized queries gebruiken is ook vrij knullig :P Ik snap niet dat er nog zo veel strings aan elkaar worden geplakt...

Acties:
  • 0 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
Verwijderd schreef op dinsdag 13 september 2011 @ 10:48:
Zo bedoel ik het niet. Ik bedoel dat de TS zich enkel geconcentreerd heeft op het GET-gedeelte, terwijl beveiliging op POST-niveau uiteraard even belangrijk is!
O zo, vergeet COOKIE niet dan. ;)

Maar dan nog: Je moet altijd ook nog in de buurt van je sql specifiek voor je sql escapen. En idem voor alle overige contexten.

{signature}


Acties:
  • 0 Henk 'm!

  • BetuweKees
  • Registratie: Januari 2003
  • Laatst online: 15-07 20:53

BetuweKees

Flipje uit Tiel

Topicstarter
Dank voor de reacties!

@Wijnbo:
* POST heb ik inderdaad niet genoemd in de TS en is uiteraard belangrijk. Invoer via POST wordt op een soortgelijke manier gecontroleerd als invoer via GET. Uiteraard escape ik daar ook in de invoer, heb gekeken naar mysql_real_escape_string(). Maak zelf gebruik van Postgres, maar punt is duidelijk en pg_escape_string() is inderdaad netter dan checken op magic quotes en dan add_slashes() doen.

* Inmiddels ook log files ontvangen, allicht ten overvloede om te melden dat er in de periode waarin de tables verdwenen zijn geen POST requests verwerkt zijn. (tenminste, niet volgens de log dan)

@Voutloos:
* Ik snap je punt over escapen. Echter, als ik de input tegen een regexpr als "/^[a-zA-Z0-9\/_\-]+$/" check, hoe kunnen er dan 'gevaarlijke tekens' binnen komen? Als er input volgt met (bijvoorbeeld) een ' dan is die toch al per definitie afgekeurd?

@Spided:
* Zoals aangegeven in de TS controleer ik daar ook tegen; een request naar file.php?var=123 wordt via een check in file.php afgekeurd (er volgt een 404).

@Gomez12:
* Ik zal eens kijken hoe dat zit met toegang van andere gebruikers tot mijn database. Heb zojuist de http logs doorgespit, daarin trouwens geen duidelijke aanwijzingen voor SQL injections (rare urls, requests die niet kloppen, oid). Eens kijken hoe het met de database logs zit. Idem voor rechten op 'DROP' statements.

Through meditation I program my heart to beat breakbeats and hum basslines on exhalation -Blackalicious || *BetuweKees was AFK; op de fiets richting China en verder


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
BetuweKees schreef op dinsdag 13 september 2011 @ 20:04:
@Voutloos:
* Ik snap je punt over escapen. Echter...
Er is geen "echter...". Al heb je 400x gecontroleerd dat er een 'veilige string' (zeg /[0-9]{4}\s?[a-z]{2}/i voor een postcode a-la 1234AB) in je variabele zit dan nog moet je escapen (als je geen parameterized queries gebruikt) in je DAL. Al is het maar omdat je de "SaveAddress()" functie nu misschien alleen maar vanuit die ene plek aanroept maar die later ook op 12 andere plaatsen gaat gebruiken en je hoeft daar maar 1 keer ergens een check te vergeten en je gaat nat.
Net zoals je SQL query values escaped in queries dien je ook HTML te escapen bij output (htmlentities / htmlspecialchars bijv.) om bijv. XSS te voorkomen. En zo dien je ook rekening te houden met 't feit dat je komma's in een string moet "escapen" als je CSV files uitpoept en moet je ook een quote escapen als je code schrijft:
PHP:
1
myvar = 'That\'s all folks!';

En zo escape je ook weer fieldnames in een query:
SQL:
1
2
3
select `log_id`, `date` from `mylogtable`; --MySQL
select [log_id], [date] from [mylogtable]; --MSSQL
...etc


Wanneer je met verschillende contexten omgaat dien je voor élk van die verschillende contexten na te gaan wanneer je wat hoe escaped. Doe je dat niet dan ga je vroeger of later met de billen bloot.

[ Voor 46% gewijzigd door RobIII op 13-09-2011 20:23 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
Voutloos schreef op dinsdag 13 september 2011 @ 13:37:
[...]
Maar dan nog: Je moet altijd ook nog in de buurt van je sql specifiek voor je sql escapen.
Hmmm, goede tip.

Note to self : Altijd een dummy string toevoegen, deze kan je dan sql-escapen op de regel boven of onder je sql zelf dan moet het veiliger zijn ;)

Acties:
  • 0 Henk 'm!

  • cariolive23
  • Registratie: Januari 2007
  • Laatst online: 18-10-2024
NMe schreef op dinsdag 13 september 2011 @ 11:53:
[...]

Volgens mij geldt daar dezelfde beperking van één query per functiecall, toch? En inderdaad, het feit dat de databaseuser van de site een DROP mag doen is vrij knullig.
Nee, je kunt meerdere queries in één keer laten uitvoeren met bv. pg_query() in PHP. En dat is handig, maar soms ook iets minder handig... :?

Maar, hier wordt PostgreSQL en PHP gebruikt, waarom wordt er dan in hemelsnaam geen pg_query_params() gebruikt? Daarmee is het kinderachtig eenvoudig om SQL-injection voor eens en voor altijd uit te bannen, wordt technisch compleet onmogelijk om SQL-injection uit te voeren. En je kunt GET, POST en COOKIE variabelen zonder enig gevaar zo als parameter opgeven in deze functie.

Uiteraard kun je ook met pg_escape_string() alle input apart gaan escapen, maar dat kost je wel meer werk.
Pagina: 1