On 08-09-2010 11:24, Birger Sørensen wrote:
> Stig Johansen frembragte:
>> On 6 Sep., 12:10, Birger Sørensen <s...@bbsorensen.com> wrote:
>>> Stig Johansen kom med denne ide:
>>>> On 16 Aug., 17:17, Birger Sørensen <s...@bbsorensen.com> wrote:
>>>>> Jens R. Rasmussen skrev den 16-08-2010:
>>>>>> Leif Neland wrote in dk.edb.internet.webdesign.serverside.asp:
>>>>>>> UPDATE TABEL SET TAL=NULL WHERE ...
>>>>>> ja, selvfølgelig. Tak.
>>>
>>>>>>>> UPDATE TABEL SET FELT1="ABC", FELT2=14, TAL=????? WHERE ...
>>>>>>> Det er ikke den rette metode. (Har du læst den forældede metode
>>>>>>> på det
>>>>>>> forældede html.dk?)
>>>
>>>>>> Ja.
>>>
>>>>>> har du en link til "parametiserede queries"
>>>>>>> Brug parametiserede queries.
>>>
>>>>>>> Leif
>>>
>>>>>
http://php.net/manual/en/book.mysqli.php
>>>>> læs også
http://php.net/manual/es/security.database.sql-injection.php
>>>>> Jeg har (også) søgt en forståelig forklaring - men har hverken fået
>>>>> eller kan finde en, der forklarer "paramerterized queries" så det er
>>>>> indlysende, at det er arbejdet værd, at skulle omprogrammere til
>>>>> object
>>>>> orienteret, og at det er mere sikkert end at validere med f.eks.
>>>>> mysqli_real_escape_string.
>>>>> Humlen er, at valdere input, så man er 120% sikker på, at der ikke kan
>>>>> laves injektion.
>>>
>>>> Humlen er, Birger, at du *aldrig* kan sikre dig ved at 'validere
>>>> input'!
>>>
>>>> Jo - hvis du gør systemet ubrugeligt.
>>>> Jeg ved godt du bruger PHP/mySQL, hvor man indtil videre kan føle sig
>>>> nogenlunde sikker pga. mySQL/PHP's manglende understøttelse af f.eks.
>>>> stacked queries.
>>>
>>>> Hvis du sætter dig lidt ind i de forskellige databasers
>>>> 'capabilities', herunder diverse(hexadecimale m.m.) notationsformer,
>>>> vil du forstå hvorfor mysqli_real_escape_string ikke er sikker (nok) -
>>>> og heller aldrig bliver det.
>>>
>>>> mvh
>>>> Stig
>>>
>>> Det kommer vel an på, hvad man forstår ved at validere input.
>>> Hvis input skal være et tal, skal man sikere sig, at der faktisk
>>> leveres et tal. Hvis der er mulghed for at begrænse input data, kan man
>>> sikre sig at input er i en tilladt mængde.
>>> Tag en gæstebog som eksempel.
>>> Der skal bruges nogle felter - navn og tekst, f.eks. - hvor det ikke
>>> vil være muligt, på forhånd at opstille "lovlige værdier".
>>> Her fjerner mysqli_real_escape_string() karakterer der kunne bruges til
>>> at få databasen til at gøre andre ting, end at gemme input (injektion).
>>> Det kan godt være det ikke er godt nok - men os almindelige wannabees,
>>> mangler et brugbart alternativ.
>>>
>>> Det er efterhånden slået fast, af flere forskellige, at løsningen er
>>> "parameterized queries".
>>> Der er så efterhånden mange der har spurgt efter, hvad *det* er, eller
>>> en forklaring på, hvordan man gør det. Men der er ikke rigtigt nogen
>>> der har givet en sådan forklaring.
>>> Det er en smule omtalt i php manualen - se ovenstående link.
>>> Det handler OOP, og en indviklet procedure med kald til flere
>>> forskellige funktioner - for så vidt jeg kan se at ende med at gøre det
>>> samme.
>>> Og det bliver ikke mere sikkert af at det forgår i funktionerne i et
>>> objekt, end det er i sekventiel progammering.
>>>
>>> Derfor savner jeg - vi? - en forklaring på, præcist hvorfor
>>> "parameterized queries" gør tingene så megt mere sikre. Og hvordan man
>>> implementerer dem.
>>>
>>
>> Birger, husk nu du skriver i .ASP gruppen, og ikke i .PHP gruppen ;).
>>
>> 'Sikkerhed' eller mangel på samme er en symbiose mellem programmering
>> og database.
>> Hvis databsene ikke indeholder faciliteter, der kan udnyttes, ja så
>> kan man føle sig sikker - men kun så længe man holder sig til den
>> specifikke database.
>>
>> Lad mig citere:
>>> Tag en gæstebog som eksempel.
>>> Der skal bruges nogle felter - navn og tekst, f.eks. - hvor det ikke
>>> vil være muligt, på forhånd at opstille "lovlige værdier".
>>
>> Jeg var inde på at man kan decimere værdien at et givet system ved at
>> begrænse datamængden, og det er også det du er inde på med dine
>> "lovlige værdier" - som du kalder det.
>>
>> Snakker vi "parameterized queries" eller "prepared statements" eller
>> "parameter binding", er det flere udtryk for det samme, afhængig af
>> hvilken begrebsverden man befinder sig i, eks. MS/PHP/Oracle.
>>
>>
>> Uanset hvad man kalder det, så er teknikken den samme, nemlig at
>> adskille SQL og Data.
>> Det er essentielt, da SQL er uafhængigt af data, og derfor fuldstændig
>> og aldeles usårlig over for SQL injection.
>>
>> (Da SQL ikke bliver sendt som følge af input, kan de prøve fra nu af
>> og til verdens ende..)
>>
>> En forklaring..?
>> Det er ikke min opgave (eller interesse) at lave en fyldestgørende
>> tutorial over 'best practice' gennem de sidste 15+år inden for
>> database'programmering'.
>> mvh
>> Stig.
>
> Jeg opfatter det egentlig som en generel diskussion - men er lidt nødt
> til at holde mig til det PHP jeg kender. ^^
> Den burde måske være i databaser, så jeg futter lige...
>
> Jeg efterlyser ikke en "best practice" men en beskrivelse af
> "parameterized queries".
> Både fordi jeg gerne vil forstå det, og fordi det lidt er et udtryk der
> bare "smides på", hver gang nogen har problemer - enten faktiske eller
> forståelsesmæssige.
> F.eks. som i denne tråd:
>> Det er ikke den rette metode. ... Brug parametiserede queries.
> Der spørges så efter et link - og der kommer ikke noget svar. Hverken
> Jens eller andre læsere er blevet en dyt klogere.
>
> Jeg gør altid det, at jeg "decimerer værdien", hvis det overhovedet er
> muligt.
> Men med f.eks. en tekst til en gæstebog, har jeg ingen anden mulighed,
> end at fjerne eller escape karakterer, der *kunne* være et forsøg på
> injektion.
> Jeg skal bruge SQL til at indsætte data i min tabel; og jeg forstår
> ikke, hvordan jeg kan skille dataene fra SQL'en - i sidste ende er jeg
> nødt til at blande dem, ellers kan jeg ikke få dataene ind i tabellen.
>
> Jeg følger altid den her (og jeg er altså nødt til at bruge PHP til
> eksempler):
> 1. Læs den besøgendes data ind i en variabel som i f.eks.
> $data = $_POST( 'data');
> 2a. Decimer $data ud fra "lovlige værdier" eller
> numeriske typer (typecasting), eller
> 2b. Kontroller $data for ulovlige karakterer. (mysqli_escape_string())
> 3. Kald en funktion der indsætter data i tabellen f.eks.
> InsData( $data) - der bl.a. indeholder
> 4. $query = "INSERT INTO min_tabel SET tabel_data='$data' LIMIT 1";
>
> Hvordan kan jeg gøre det mere sikkert?
Det var en lang post.
Men p.g.a. det lidt komplekse emner bliver det også et
halvlangt svar.
"parametiserede queries" må være Danglish for noget som
er kendt under navnene:
parameters - ADO (VBS, VB6 etc.), ADO.NET (C#, VB.NET etc.)
prepared statements - JDBC (Java), mysqli (PHP), PDO (PHP)
I den mere seriøse del af software udvikling er der stort set
ingen der bruger at sætte værdier direkte ind i SQL strengen.
Folk bruger enten parameters/prepared statement direkte eller
bruger en O/R-mapper (som formentligt også bruger
parameters/prepared statement).
Den eneste grund der kan være til at bruge værdier direkte
i SQL strengen er brug af IN(liste) konstruktionen.
Parameters/prepared statement er populære fordi de slår
flere fluer med et smæk:
1) de håndterer streng værdier med single quote (eller
andre tegn med SQL syntaktisk betydning) hvilket dækker
både
a) ondsindet SQL injection
b) uforsætlige problemer som irske navne a la O'Toole
2) de håndterer dato formater
3) afhængig af implementationen (driver/provider og database)
vil de enten kun koste ganske minimalt i overhead eller
kunne give store performance fordele ved gentagne kald
af samme SQL med forskellige værdier
Bemærk her at:
- det er meget uheldig sammenblanding af lag at undlade
brug af parameters/prepared statement i backend fordi
man laver input validering i frontend
- det er aldeles uforsvarligt at undlade input validering
i frontend fordi man bruger parameters/prepared statement
i backend, fordi man også skal beskytte sig mod andre problemer
end SQL injection (for web apps f.eks. XSS)
Hvis vi hopper specifikt til PHP og MySQL, så er der forskellige
alternativer til prepared statement men ingen af dem er gode.
str_replace og addslashes er aldeles håbløse fordi de ikke
kender MySQL's syntax regler.
mysql_escape_string virker tilforladelig, men duer ikke
fordi den ikke er connection specifik. Meget snedige personer
har fundet ud af at man kan få problemer hvis default
og connection charset er forskellige (vestligt og kinesisk
tror jeg - du kan nemt Google det specifikke problem).
mysql_real_escape_string uden connection argument
har samme problem, men kommer connection argument
med er den OK.
Brug af mysqli med parameters kan dog klart
anbefales af flere årsager. Den væsentligste
er at det er langt nemmere at checke om der er
brugt parameters alle steder end om
mysql_real_escape_string er kaldt alle steder.
Bemærk at mysqli prepared statement kan bruges
både objekt orienteret og proceduralt. Du er ikke
tvunget til OOP fordi du vil bruge det.
(jeg har svært ved at se hvorfor man ikke skulle
bruge OOP til det, men det er en anden sag)
Bruger man PDO fremfor mysqli får man ovenikøbet
en simplere og mere læsbar syntax!
PDO findes dog (så vidt jeg ved) kun i en objekt
orienteret udgave.
Arne
PS: Personligt mener jeg at H2 har en supergod
feature: hvis man tilføjer ;ALLOW_LITERALS=NONE
til sin connection string, så får man en exception
ved enhver brug af værdier direkte i sin SQL!