Ben ik beschermd tegen SQL injection?
Staat de foutafhandeling voor de database in login.php?
Wat is issset.php?
Gewijzigd op 17/12/2014 17:02:48 door Ward van der Put
in mijn login php file staat gewoon:
$db_host = "localhost";
$db_username = " blablabla";
$db_password = " blablabla";
$db_database = "blablabla";
issset.php is mijn php code die ik gelinkt heb
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?php
require_once 'login.php';
$db_con= new mysqli($db_host, $db_username, $db_password, $db_database);
$db_con->set_charset("utf8");
if($db_con->connect_error) die ("(" . $db_con->connect_error . " Error during connection");
if(isset($_POST['zoeken'])){
$zoeknaam = $_POST['Zoek']; // declare the input here
$stmte = $db_con->prepare("SELECT * FROM customers WHERE Voornaam = ?");
$stmte->bind_param("s", $zoeknaam); // then use inside here
$stmte->execute();
$rows = $stmte->num_rows;
if($stmte->num_rows > 0) {
$results = $stmte->get_result();
while($row = $results->fetch_assoc()) {
echo $row['Achternaam'] . '<br/>';
// and other columns
}
}
}
?>
require_once 'login.php';
$db_con= new mysqli($db_host, $db_username, $db_password, $db_database);
$db_con->set_charset("utf8");
if($db_con->connect_error) die ("(" . $db_con->connect_error . " Error during connection");
if(isset($_POST['zoeken'])){
$zoeknaam = $_POST['Zoek']; // declare the input here
$stmte = $db_con->prepare("SELECT * FROM customers WHERE Voornaam = ?");
$stmte->bind_param("s", $zoeknaam); // then use inside here
$stmte->execute();
$rows = $stmte->num_rows;
if($stmte->num_rows > 0) {
$results = $stmte->get_result();
while($row = $results->fetch_assoc()) {
echo $row['Achternaam'] . '<br/>';
// and other columns
}
}
}
?>
Gewijzigd op 17/12/2014 21:45:28 door Michael Desmadril
Buiten dat het moet gebeuren voor je login variabelen , om ze af te vangen met 'mysgl_real_escape_string', moet het ook voor alle andere velden in je systeem. Dus bij registratie van NAW, Bankrekeningnummer (IBAN), etc, ??
Ik neem ook dat dat geldt voor je NAW-gegevens en bankrekeningsnummers.
Dus ja, ook hierbij geldt dat je het moet escapen. Verder is gebruik van de mysql_*() extentie afgeraden, en wordt PDO of MySQLi aangeraden.
Gewijzigd op 05/05/2015 16:27:33 door - Ariën -
Maar je kan die velden toch ook wel afvangen met javascript ?
Dus als je valideert:
- Validatie reeks controle (mailadres, telefoonnummer, website, etc...)
- SQL injection filteren
- Input validatie met JavaScript/HTML5
Gewijzigd op 05/05/2015 16:35:16 door - Ariën -
Duidelijke taal Aar ! Dank je.
Zet die gewoon NIET in variabelen, maar hardcoded in de code.
Nu doe je dat ook, maar wel via een variabele. Geen enkel voordeel, alleen maar mogelijke nadelen.
Dus doe het zo:
Code (php)
1
2
3
4
5
6
7
2
3
4
5
6
7
<?php
// require_once 'login.php';
$db_con= new mysqli("localhost", "gebruikerX", "kdeN3nen_83", "database");
$db_con->set_charset("utf8");
?>
// require_once 'login.php';
$db_con= new mysqli("localhost", "gebruikerX", "kdeN3nen_83", "database");
$db_con->set_charset("utf8");
?>
Gewijzigd op 05/05/2015 17:28:25 door Eddy E
Verder was die reactie waarop je reageert van iemand anders, en inmiddels gedateerd. Dit even ter informatie.
Gewijzigd op 05/05/2015 17:28:35 door - Ariën -
Eddy E op 05/05/2015 17:22:08:
Waarom zou je het risico lopen dat ergens $db_username of $db_password wordt weergeven?
Zet die gewoon NIET in variabelen, maar hardcoded in de code.
Zet die gewoon NIET in variabelen, maar hardcoded in de code.
Als je je daar druk om moet maken, heb je problemen van een hele andere orde. Daarmee geef je in feite toe dat je niet in kunt staan voor de veiligheid van je eigen code.
Het is heel goed denkbaar dat je dit soort parameters wilt vangen in variabelen, bijvoorbeeld in een configuratie-bestand dat verschillende waarden heeft voor een vaste set parameters op grond van bijvoorbeeld een hostname.
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php
switch ($_SERVER['HTTP_HOST']) {
// development
case 'mysite.dev':
$config->database = array(
'user' => '...',
'pass' => '...',
'database' => '...',
// etc...
);
// more host specific config...
break;
// production
case 'mysite.com':
$config->database = array(
'user' => '...',
'pass' => '...',
'database' => '...',
// etc...
);
// more host specific config...
break;
default:
die('unknown hostname');
}
?>
switch ($_SERVER['HTTP_HOST']) {
// development
case 'mysite.dev':
$config->database = array(
'user' => '...',
'pass' => '...',
'database' => '...',
// etc...
);
// more host specific config...
break;
// production
case 'mysite.com':
$config->database = array(
'user' => '...',
'pass' => '...',
'database' => '...',
// etc...
);
// more host specific config...
break;
default:
die('unknown hostname');
}
?>
Zoals gezegd, als iemand het op een of andere manier voor elkaar krijgt om de inhoud van $config af te drukken, dan wil dat zeggen dat iemand op een of andere manier PHP-code kan uitvoeren. Dan ben je al nat.
Dit klinkt als een soort mantra wat je je ooit hebt aangeleerd, maar waarvan je niet meer precies weet waarom het ook alweer zo zou zijn.
Ontopic: ik vind het grappig dat er zoveel nadruk wordt gelegd op het escapen van van alles en nog wat op het gebied van MySQL, en vervolgens druk je data die uit je database komt gewoon af, zonder deze te escapen :D. Dan mis je toch een beetje het punt geloof ik.
Vertrouw nooit user input. Ook / vooral niet nadat je deze hebt opgeslagen in je database lol.
Meestal wordt aangeraden om mysqli_real_escape_string() te gebruiken. Maar dat werkt niet altijd, bijvoorbeeld als je een ID wilt escapen en iemand gebruikt '1 OR 1=1'. Dan moet je in ieder geval nog alle data checken op type, dat is al een hele klus.
Daarom is de enige aanbevolen manier om met prepared statements te werken. Omdat het aanbieden van de query en de data in gescheiden stappen gaat, is er voor de database geen misverstand wat precies de query is en wat de data is.
1) Quote's regeltjes consequent overal toegepast (wanneer enkele quotes en wanneer dubbele quotes)
2) Overgestapt van PHP 5.3.29 naar PHP 5.5.24
3) MySQL-statements omgezet naar MySQLi
4) SQL-injection d.m.v. mysqli_real_escape_string afgevangen
5) Password encryptie toegepast (password_hash, password_verify, password_needs_rehash)
6) Javascripts verbeterd (o.a. IBAN check toegevoegd)
Nu zit ik nog met 2 puntjes:
1) Ik wil 'prepared statements' gaan toepassen om het nog veiliger te maken.
Mijn vraag is: Is het zinvol om gewoon alle SQL-statements om te zetten naar een versie van prepared statements ? Kan ik dus al mijn mysqli_real_escape_string-statements er weer uitgooien ?
2) Ik zit nog met een vraag (waarschijnlijk een domme vraag).
Ik heb middels javascript alle velden gecontroleerd (of het een juist IBAN-nummer is, of het veld niet leeg is, of de datum-va/dataum-tm goed zijn ingevuld, etc...). Moet ik nu alle javascript-controles ook nog eens bij de PHP-validaties doen? Want ik begrijp dat je javascript uit kan zetten en dan worden er geen javascript-validaties gedaan. Maar is dit niet allemaal een beetje dubbel op ??
Toevoeging op 17/05/2015 16:05:18:
3de puntje:
AJAX maakt gebruik van javascript. Wanneer javascript wordt uit gezet in de browser werkt AJAX dan ook niet meer ?
Gewijzigd op 17/05/2015 14:13:47 door Paco de Wulp
Mijn vraag is: Is het zinvol om gewoon alle SQL-statements om te zetten naar een versie van prepared statements ?
Nee, het gaat alleen om de injectie van buitenaf. SQL-expressies die geen output van buitenaf bevatten, kunnen niet met SQL-injectie worden misbruikt.
>> Ik heb middels javascript alle velden gecontroleerd (of het een juist IBAN-nummer is, of het veld niet leeg is, of de datum-va/dataum-tm goed zijn ingevuld, etc...). Moet ik nu alle javascript-controles ook nog eens bij de PHP-validaties doen?
Ja. Niet alleen kan JavaScript worden uitgezet: een hacker kan elk HTTP-request veranderen. Alle input die van buiten komt is dus bij voorbaat verdacht, totdat je met controles hebt bewezen dat deze ermee door kan.
ad.1)Maar wat is erop tegen om alles met prepared-statements doen? Het kan toch geen kwaad. Je hanteert dan wel tenminste overal dezelfde methodiek. Of heeft het andere consequenties voor bijvoorbeeld de performance, of is het niet sjiek om iets-wat overbodige statements in je code te hebben ?
ad.2)Dus eigenlijk kan je alle javascript checks skippen, want alles moet toch in PHP worden gecheckt. Eigenlijk zijn javascripts dus alleen maar voor een iets mooiere schermafhandeling, qua foutmeldingen en ander soort meldingen. Toch ?
ad.3) Maar hoe zit het dan met AJAX die ook gebruik maakt van javascript ?
2) Alles moet met PHP gevalideerd worden. Het is echter vaak wel gebruiksvriendelijk om ook javascript validatie te gebruiken. Denk bijv. aan een vakje dat direct rood wordt nadat de focus van het veld af is.
De gebruiker kan nu direct het vakje alsnog juist invullen en hoeft later niet nog een keer terug.
Persoonlijk vind ik dat met de komst van HTML5 de javascript validatie grotendeels weggelaten kan worden. Nu heb je immers de mogelijkheid om een input type "email" en "numeric" e.d. te maken.
3)Ook bij AJAX moet je serverside valideren en kun je om het gebruiksvriendelijker te maken ook clientside valideren.
Gewijzigd op 17/05/2015 19:57:43 door Frank Nietbelangrijk
Paco de Wulp op 17/05/2015 14:04:46:
4) SQL-injection d.m.v. mysqli_real_escape_string afgevangen
Mijn god daar gaan we weer.
mysqli_real_escape_string is geen wondermiddel.
Stel dat jij een query hebt waar je voor een zekere parameter een getal verwacht, zet je daar dan quotes omheen?
Bijvoorbeeld: SELECT * FROM users WHERE user_id = $x.
$x komt bijvoorbeeld uit $_GET['id'].
Als je geen quotes gebruikt doet je real_escape_string niets. Als $_GET['id'] "OR 1 = 1" bevat (zonder dubbele quotes) dan wordt er niets geescaped omdat er niets te escapen valt.
Als je wel quotes gebruikt... ik weet niet, het is wel "veilig" in combinatie met mysqli_real_escape_string() maar het is nogal onzinnig.
Als je prepared statement gebruikt... doe je een hoop werk voor niets als je het mij vraagt. prepare(), bind_param(), etc. Aint nobody got time fo dat.
Bottom line: als je een getal verwacht controleer dan op een getal. Oftewel filter je input. Als je invoer niet voldoet aan een zeker formaat dan hoef je ook geen query uit te voeren die niets oplevert.
@Thomas, mij hoor je er niet meer over...ik snap het nu. Be Happy !!
Je "regels" zijn ook voornamelijk gericht op het buiten houden van rotzooi, maar over een verdere behandeling van "user data" hoor ik je niet. Tenzij jij bepaalde gebruikers in je systeem/systemen vertrouwt (middels een soort van chain-of-trust waarbij privileges worden doorgegeven) moet je alle user data blijven behandelen als zijnde onbetrouwbaar, zelfs (en wellicht vooral) als deze opgeslagen is in je database.
Ik neem alle hints, suggesties, tips mee. Wat een fantastische website is dit toch !
AJAX is ook maar een soort 2e 'headless' browser die op de achtergrond HTTP requests doet, net als de browser. Alleen dan gebeurt het met een XMLHTTPRequest (XHR) object, in plaats van dat de gebruiker een URL typt/klikt/afvuurt. Voor Javascript hoeft er verder niets speciaals gedaan te worden, zolang je de inputvariabelen maar controleert en schoont voordat je ze bij een SQL query in stopt. Hiervoor gelden dus dezelfde regels, en kan ik prepared statements aanbevelen.