Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

Quotes/html verwerken in database & parsen op site

Pagina: 1
Acties:

  • Demonitzu
  • Registratie: Augustus 2012
  • Niet online

Demonitzu

Incidentele gebruiker

Topicstarter
Hallo,

Ik heb een klein dilemma rondom het verwerken van quotes/html in een MySQLi database en Google geeft mij nog teveel uiteenlopende antwoorden. In feite is het gewoon het aanmaken van een bericht met de mogelijkheid om quotes te gebruiken en html codes met anderen te delen, de html codes moeten uiteraard niet geparsed worden, maar ik wil de mogelijkheid open houden om men dergelijke teksten met elkaar te laten delen. Dit is wat ik voor ogen heb:

Voorbeeld van input voor de database:
HTML:
1
Dit is mijn bericht met wat "quotes" en een HTML code zoals <a href="#">link</a>


Gebruik van htmlentities() of htmlspecialchars() om SQL injection te voorkomen, waarmee de HTML code ook gelijk unparsed opgeslagen wordt. De data zou dan zo direct geechoed kunnen worden op een pagina. Ben er niet helemaal uit of real_escape_string() in dit geval nog steeds nodig is..? In ieder geval zou het dan zo opgeslagen worden als:
HTML:
1
Dit is mijn bericht met wat &quot;quotes&quot; en een HTML code zoals &lt;a href=&quot;#&quot;&gt;link&lt;/a&gt;


Echter wil ik een grote hoeveelheid oude berichten uit een bestaande applicatie erin importeren die slaat de berichten ongecodeerd op zonder dat SQL injection mogelijk is. Het is mij niet helemaal duidelijk hoe die software dat verwerkt. Het staat als volgt opgeslagen in de database:
HTML:
1
Dit is mijn bericht met wat "quotes" en een HTML code zoals <a href="#">link</a>


Dus ik vraag mij af of:
1. deze aanpak in principe goed genoeg is tot aan het kopje "Echter"?
2. of ik ter behoeve van de import van de oude berichten beter een methode kan gebruiken die de data ongecodeerd (met quotes en html) opslaat in de database, waarbij de data vervolgens pas gecodeerd wordt wanneer deze geprint moet worden? Zo ja, is een prepared statement dan de uitkomst voor de databaseverwerking?

Danku :)

TekkenZone - Dutch Tekken Community


  • _Thanatos_
  • Registratie: Januari 2001
  • Laatst online: 05-09 14:39

_Thanatos_

Ja, en kaal

Ik begrijp niet helemaal het probleem als de berichten al precies zo zijn als je wilt (voorbeeld 1 & 3). Wat ik je wel kan vertellen, is dat je in geen geval je berichten als voorbeeld 2 moet opslaan. Zo poep je ze uit naar de browser (of niet, zelf weten). De database heeft helemaal geen last van wat html.

Los daarvan, html is de database is niet handig. Straks wil je iets wijzigen, en dan zit je weer met nieuwe html en oude prut.

日本!🎌


  • martijnve
  • Registratie: December 2004
  • Laatst online: 20:53
Eens met Thanatos maar wat aanvulling,

In je database staat het bericht as-is zonder aanpassingen voor dat ene specifieke weergave-probleem, dus als het even kan helemaal geen html (afhankelijk van de case kan het toch nodig zijn html op te slaan) maar in ieder geval geen html-encoded karakters. Het omzetten naar html-chars is een implementatie-detail van de client en doe je bij voorkeur zo laat mogelijk bij het tonen maar iig nooit al bij het schrijven naar de database. Wat als je ooit nog een andere client maakt die geen webapp is of die een framework gebruikt wat dit voor je afhandeld?

Behalve onhandig is het ook nog eens heel gevaarlijk: mysqlspechialchars is nooit een goed idee als beveiliging tegen sql-injection. Het begint al met het feit dat die functie daar helemaal niet voor gemaakt is dus misschien zijn er wel characters die injecties mogelijk maken die helemaal niet afgevangen worden. Maar belangrijker nog: wat als je het in één specifiek geval voor ook maar één variabele vergeet? (en vroeg of laat gebeurt dat een keer). Altijd gebruik maken van prepared statements lost het probleem structureel op. Zie deze link voor een goede uitleg:

http://stackoverflow.com/...ection-in-php/60496#60496

[ Voor 13% gewijzigd door martijnve op 10-03-2014 01:55 ]

Mini-ITX GamePC: Core i5 3470 | 16GB DDR3 | GTX 970 4GB | Samsung 830 128GB | Dell u2711 (27", IPS,1440p), 2343BW


  • Bosmonster
  • Registratie: Juni 2001
  • Laatst online: 19-11 09:49

Bosmonster

*zucht*

_Thanatos_ schreef op maandag 10 maart 2014 @ 01:25:

Los daarvan, html is de database is niet handig. Straks wil je iets wijzigen, en dan zit je weer met nieuwe html en oude prut.
Bij een CMS heb je bijna altijd een wysiwyg-editor die helaas gewoon html uitpoept, dus dat zal toch opgeslagen moeten worden.

Ik ben een groot voorstander om daar bijvoorbeeld een markdown-editor voor te gebruiken, maar dat is erg moeilijk te verkopen aan een klant.

  • _Thanatos_
  • Registratie: Januari 2001
  • Laatst online: 05-09 14:39

_Thanatos_

Ja, en kaal

Bosmonster schreef op maandag 10 maart 2014 @ 09:45:
[...]


Bij een CMS heb je bijna altijd een wysiwyg-editor die helaas gewoon html uitpoept, dus dat zal toch opgeslagen moeten worden.

Ik ben een groot voorstander om daar bijvoorbeeld een markdown-editor voor te gebruiken, maar dat is erg moeilijk te verkopen aan een klant.
Markdown kan prima wysiwyg zijn ;)
Dat die editors niet zo makkelijk voorhanden zijn als html-based editors, is een ander verhaal. Plus dat je de klant moet laten begrijpen dat het juist een vóórdeel is om niet een halve kermis in een document te kunnen maken met die html-editors. Klant willen = beter uitleggen :)
martijnve schreef op maandag 10 maart 2014 @ 01:47:
Altijd gebruik maken van prepared statements lost het probleem structureel op. Zie deze link voor een goede uitleg:

http://stackoverflow.com/...ection-in-php/60496#60496
Dat is absoluut beter, alleen mijn bedenkingen daarbij zijn dan altijd dan ook dié functionaliteit uiteindelijk toch ooit ook je values zal moeten escapen. Dat gebeurt dan misschien op een andere plek of op een andere manier, maar hoe je het ook wendt of keert, je values moeten een *keer*, door *iemand*, *ergens* escaped worden. De kunst is dan alleen om de netste optie daarvoor te kiezen.

Wat ik hiermee probeer te zeggen, is dat prepared statements geen alternatief is voor proper escapen. Het gebeurt nog steeds, alleen roep je het niet expliciet aan. In dat opzicht is dingen expliciet doen misschien wel beter. Maarja, wie ben ik.

[ Voor 64% gewijzigd door _Thanatos_ op 10-03-2014 17:04 ]

日本!🎌


  • NMe
  • Registratie: Februari 2004
  • Laatst online: 20-11 11:59

NMe

Quia Ego Sic Dico.

Toshin schreef op zondag 09 maart 2014 @ 22:53:
Gebruik van htmlentities() of htmlspecialchars() om SQL injection te voorkomen, waarmee de HTML code ook gelijk unparsed opgeslagen wordt.
HTML-entities omzetten heeft niks met SQL-injectie te maken en als dat je doel is ben je het verkeerde probleem op de verkeerde manier op aan het lossen. ;)

'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.


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
_Thanatos_ schreef op maandag 10 maart 2014 @ 16:58:
Dat is absoluut beter, alleen mijn bedenkingen daarbij zijn dan altijd dan ook dié functionaliteit uiteindelijk toch ooit ook je values zal moeten escapen. Dat gebeurt dan misschien op een andere plek of op een andere manier, maar hoe je het ook wendt of keert, je values moeten een *keer*, door *iemand*, *ergens* escaped worden. De kunst is dan alleen om de netste optie daarvoor te kiezen.
Dan begrijp je niet hoe prepared statements werken ;) Het is niet alsof de driver (of het RDBMS for that matter) alsnog de string "insert into foo (a, b, c) values (:name, :lastname, :birthdate)" gaat liggen om-fröbelen naar "insert into foo (a, b, c) values ('jantje', 'janssen', '1977-12-02')" zodat de parser het kan parsen. De values (jantje, janssen en 2 dec. '77) worden apart van de statement zelf in een datastructuur (bijvoorbeeld een array) naar de DB verstuurd. Het RDBMS zal op zijn beurt, wanneer deze een delimiter (zoals in dit voorbeeld ":name" etc.) tegenkomt in die statement, de waarde die opgeslagen dient te worden uit de values van de datastructuur die het ontvangen heeft plukken. Daar komt geen escaping meer aan te pas nee. En dat is ook de reden waarom je je, zoals in dit voorbeeld, bijvoorbeeld niet meer hoeft te bekommeren om welke datetime format (dd-mm-yyyy, mm-dd-yyyy, yyyy-mm-dd etc. ) je moet gebruiken; als je een datetime variabele hebt (in strong typed talen als C# bijvoorbeeld) pass je gewoon een datetime variabele; de driver zal er dan voor zorgen dat de waarde op de juiste manier bij het RDBMS aankomt, ongeacht locale settings e.d. Hoe die driver het dan intern oplost is niet boeiend; de waarde wordt in een native formaat aan het RDBMS aangeleverd, niet als string. Idem voor ints en andere native types die een RDBMS ondersteunt. De waarde '123' gaat dan, in essentie, als 1 byte (011110112) over de lijn (most likely gewoon als D/QWord though i.v.m. padding e.d.) en niet als de string "123" (ofwel 3 bytes met ASCII values 49, 50, 51).

En omdat plaatjes meer zeggen dan woorden:

"Gewone" query:
Afbeeldingslocatie: http://i.stack.imgur.com/niZ7j.png

Prepared statement:
Afbeeldingslocatie: http://i.stack.imgur.com/M7PXp.png
Bron: Deze Stackoverflow post
Meer info op Wikipedia

Om 't nog wat meer te illustreren met Bobby tables: escapen is érg balangrijk inderdaad als je strings aan elkaar gaat lopen plakken en naar 't RDBMS stuurt. Als je dan niet correct escaped heb je een probleem. Bij een prepared statement daarentegen gebeurt er, in essentie, iets als:

statementinsert into students (`studentnr`, `firstname`, `lastname`) values (:studentnr, :firstname, :lastname)
:studentnr43400
:firstnameRobert'); DROP table students;--
:lastnameJanssen

Sql krijgt deze datastructuur binnen, "compileert" de query en maakt er iets van als:
queryplan(lees dit in "machine-taal":)

"*bliep* *bloep* *bidibidibidi*
hmmm, ik moet in tabel students <pointer naar tabel> een value gaan inserten in veld <studentnr> <pointer naar value>, <firstname> <pointer naar value> en <lastname> <pointer naar value>
)
94ab5b4e43400
94ab5b56Robert'); DROP table students;--
94ab5b78Janssen

Op 't moment dat het RDBMS de daadwerkelijke value gaat schrijven gaat 't gewoon in de "lookup tabel" de waarde opzoeken. Bij een "gewone" query moet de parser eerst de DML van de data proberen te onderscheiden en, als daar dus ambiguïteit ontstaat doordat er niet of verkeerd is ge-escaped, dan heb je de poppen aan 't dansen.
_Thanatos_ schreef op maandag 10 maart 2014 @ 16:58:
Wat ik hiermee probeer te zeggen, is dat prepared statements geen alternatief is voor proper escapen. Het gebeurt nog steeds, alleen roep je het niet expliciet aan. In dat opzicht is dingen expliciet doen misschien wel beter. Maarja, wie ben ik.
Prepared statements zijn wel degelijk een (beter) alternatief voor proper escapen dus. Ik hoop dat je dat na mijn verhaal en linkjes ook inziet ;) Zo niet dan zal ik 't nog eens moeten uitleggen nadat ik heb verzonnen hoe ik 't goed kan uitleggen :+

@TS: Je kunt de invoer wel als "HTML" opslaan o.i.d. (want dat doe je in essentie als je HTMLEntities en consorten gebruikt), maar vraag je eens af wat er dan gebeurt als je een PDF wil printen? Of een RTF/.Doc bestand wil genereren? Daar betekenen zaken als &amp; en &quot; helemaal niets dus dan kom je eerst weer aan 't "decoden". In principe wil je je data altijd "rauw" in de DB hebben staan, dat biedt altijd de beste opties om te converteren naar 't "formaat" waar je op dat moment mee bezig bent. Het is dan ook "het probleem van de VIEW" (als je een MVC achtige structuur gebruikt) om ervoor te zorgen dat de data op dat moment correct encoded/escaped wordt; een HTML view zal dus HTMLEntities gebruiken en een PDF generator zal op dat moment weer andere functies gebruiken. Having said that: als je, zoals Bosmonster al aangaf, al HTML "binnen krijgt" van een WYSIWYG-editor o.i.d. dan is het opslaan van die "invoer" (dus gewoon de HTML die 't ding "uitpoept") the next best thing. Je wil zo dicht mogelijk tegen de originele "invoer" aan blijven zitten (lees: niet aankomen) om zo heen-en-weer-conversies (met doorgaans allerlei "verlies" of andere vage zaken zoals een \r\n die opeens een \r\n\r\n wordt na opslaan en \r\n\r\n\r\n\r\n wordt na 2 keer opslaan) te voorkomen.

[ Voor 61% gewijzigd door RobIII op 10-03-2014 19:27 ]

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


  • Barryvdh
  • Registratie: Juni 2003
  • Laatst online: 21-11 14:12
Ik denk dat Thanatos bedoeld dat je het voordat je het op de website toont, moet escapen, niet voordat ze de database ingaan. En dat klopt ook wel, maar dan is de 'netste optie' dus op het moment van weergeven, omdat de manier van escapen afhankelijk is van waar je het weergeeft (html, js, PDF, json, email etc.), soaps Rob al zegt.

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Barryvdh schreef op maandag 10 maart 2014 @ 20:36:
Ik denk dat Thanatos bedoeld dat je het voordat je het op de website toont, moet escapen, niet voordat ze de database ingaan
Zo lees ik _Thanatos_' post anders niet; hij doelt expliciet op 't escapen van values i.v.m. parameterized queries in een context van SQL. Ik kan daar echt niets anders in lezen en hence mijn verhaal ;)

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


  • Demonitzu
  • Registratie: Augustus 2012
  • Niet online

Demonitzu

Incidentele gebruiker

Topicstarter
martijnve schreef op maandag 10 maart 2014 @ 01:47:
Eens met Thanatos maar wat aanvulling,

In je database staat het bericht as-is zonder aanpassingen voor dat ene specifieke weergave-probleem, dus als het even kan helemaal geen html (afhankelijk van de case kan het toch nodig zijn html op te slaan) maar in ieder geval geen html-encoded karakters. Het omzetten naar html-chars is een implementatie-detail van de client en doe je bij voorkeur zo laat mogelijk bij het tonen maar iig nooit al bij het schrijven naar de database. Wat als je ooit nog een andere client maakt die geen webapp is of die een framework gebruikt wat dit voor je afhandeld?

Behalve onhandig is het ook nog eens heel gevaarlijk: mysqlspechialchars is nooit een goed idee als beveiliging tegen sql-injection. Het begint al met het feit dat die functie daar helemaal niet voor gemaakt is dus misschien zijn er wel characters die injecties mogelijk maken die helemaal niet afgevangen worden. Maar belangrijker nog: wat als je het in één specifiek geval voor ook maar één variabele vergeet? (en vroeg of laat gebeurt dat een keer). Altijd gebruik maken van prepared statements lost het probleem structureel op. Zie deze link voor een goede uitleg:

http://stackoverflow.com/...ection-in-php/60496#60496
Bedankt voor de reacties, Ik heb inmiddels uitgebreid getest en prepared statements lost inderdaad het probleem structureel op in combinatie met htmlspecialchars() en nl2br() om het te parsen. Ik twijfelde in eerste instantie omdat ik bij een aantal CMS'en zag dat posts als HTML opgeslagen werden, maar as-in opslaan heeft nu zeker mijn voorkeur.

Ik gebruik nu onder andere:
PHP:
1
2
3
4
5
6
7
8
9
if ($statement = $mysqli->prepare("UPDATE articles SET title = ?, pubdate = ?, message = ? WHERE id = ?")) {
    $statement->bind_param("sssi", $_POST['title'], $_POST['pubdate'], $_POST['message'],  $_GET['id']);
    $statement->execute();
    $statement->close();
    // echo 'Succesvol toegevoegd aan database!';
}
else {
    // echo 'Query mislukt...';
}

TekkenZone - Dutch Tekken Community


  • _Thanatos_
  • Registratie: Januari 2001
  • Laatst online: 05-09 14:39

_Thanatos_

Ja, en kaal

RobIII schreef op maandag 10 maart 2014 @ 20:45:
[...]

Zo lees ik _Thanatos_' post anders niet; hij doelt expliciet op 't escapen van values i.v.m. parameterized queries in een context van SQL. Ik kan daar echt niets anders in lezen en hence mijn verhaal ;)
Ik bedoelde het allebei eigenlijk :)

日本!🎌


  • NMe
  • Registratie: Februari 2004
  • Laatst online: 20-11 11:59

NMe

Quia Ego Sic Dico.

Toshin schreef op maandag 10 maart 2014 @ 22:39:
[...]

Bedankt voor de reacties, Ik heb inmiddels uitgebreid getest en prepared statements lost inderdaad het probleem structureel op in combinatie met htmlspecialchars() en nl2br() om het te parsen.
Die laatste twee pas ná het uit de DB halen hoop ik? :?

'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.


  • Demonitzu
  • Registratie: Augustus 2012
  • Niet online

Demonitzu

Incidentele gebruiker

Topicstarter
NMe schreef op dinsdag 11 maart 2014 @ 11:17:
[...]

Die laatste twee pas ná het uit de DB halen hoop ik? :?
Jazeker, op het allerlaatste moment :)

TekkenZone - Dutch Tekken Community

Pagina: 1