FOK!forum / Digital Corner / [php/mysql] SQL Injection, Maqic Quotes genoeg?
jeroen2497woensdag 15 maart 2006 @ 20:19
Ik vroeg me zo af, is het voldoende om Magic Quotes in php.ini op true te zetten?
Of is het dan nog steeds mogelijk om SQL injection uit te voeren, zo ja, hoe???

Ben namelijk me nu bezig aan het houden van beveiligen van een website
(had ik al eerder moeten doen maar heb maqic quotes altijd al aangehouden)
SuperRembowoensdag 15 maart 2006 @ 22:35
Normaalgesproken zal dat wel voldoende zijn. Ik kan zo even geen manier bedenken waarop het zou lukken.
En toch vind ik het een slechte "feature". Als je iets meer wil dan de inhoud van een form in een database dumpen dan kom je al snel problemen tegen.
jeroen2497donderdag 16 maart 2006 @ 00:30
Tot nu toe heb ik geen problemen gehad met welke query dan ook, misschien dat ik ze gewoon 'simpel' hou

Iemand anders misschien een manier hoe een SQL Injection uit te voeren? Wil het zo safe als mogelijk hebben , dus als dit voldoende is dan ben ik tevreden
dokadonderdag 16 maart 2006 @ 01:33
Misschien is deze link: http://www.unixwiz.net/techtips/sql-injection.html wel interressant voor je
rickmansdonderdag 16 maart 2006 @ 06:45
persoonlijk zou ik iedere var die je in je query gebruikt afvangen door zoiets als:

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
32
33
34
35
36
37
38
39
40
<?php
function secureValue($value){
      if(
trim($value) == ""){
        
$new_value = "NULL";
        return
$new_value;
      }
      
      if(
is_array($value) || is_object($value)){
        if (!
get_magic_quotes_gpc()){
          
$new_value    = "'". addslashes(serialize($value)) ."'";
        }
        else{
          
$new_value    = "'". serialize($value) ."'";
        }
      }
       
      if(
is_string($value)){
        if (!
get_magic_quotes_gpc()){
          
$new_value    = "'". addslashes($value) ."'";
        }
        else{
          
$new_value    = "'". $value ."'";
        }
      }
      
      if(
is_float($value)){
        
$new_value    = "'". $value ."'";
      }
      
      if(
is_int($value)){
        
$new_value    = $value;
      }
      
      if(
strtoupper($value) ==  "NULL"){
        
$new_value    = $value;
      }
      
      return
$new_value;
    }
?>
jeroen2497donderdag 16 maart 2006 @ 11:22
Die functie ziet dr opzich wel veilig uit ja
SuperRembodonderdag 16 maart 2006 @ 13:35
Waarom maakt secureValue NULL van een lege string of een string met alleen spaties? En een float wordt wordt een string (met quotes) maar een integer blijft een integer?

Je code is niet echt optimaal, een switch op gettype($value) lijkt me hier makkelijker.
Ik zou zelf als magic quotes aan zou staan meteen in het begin alle slashes strippen.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function secureValue($value) {
   switch (gettype($value)) {
      case 'boolean':
         return $value ? '1' : '0';
      case 'integer':
      case 'double':
         return (string)$value;
      case 'string':
         return "'".addslashes($value)."'";
      case 'array':
      case 'object':
         return "'".addslashes(serialize($value))."'";
      default:
         //'resource', 'NULL', 'unknown type'
         return 'NULL';
   }
}


In plaats van addslashes() kan je ook mysql_real_escape_string() gebruiken. Dan moet je wel een verbinding met je db hebben op het moment dat je deze functie uitvoert.

[ Bericht 42% gewijzigd door SuperRembo op 16-03-2006 13:49:14 ]
Schorpioendonderdag 16 maart 2006 @ 13:53
quote:
Op woensdag 15 maart 2006 20:19 schreef jeroen2497 het volgende:
Ik vroeg me zo af, is het voldoende om Magic Quotes in php.ini op true te zetten?
Of is het dan nog steeds mogelijk om SQL injection uit te voeren, zo ja, hoe???
remove.php:
1
2
3
4
5
6
7
8
9
<?php
$id
= $_GET["id"];

$sql = "delete from blaat where id = " . $id;

$result = mysql_query($sql);

etc...
?>


Roep dan eens "remove.php?id=1%20OR%201" aan... happetee, heel je tabel weggepleurd...

Dus NEE magic quotes is niet voldoende om sql injection tegen te gaan. Je zal alle input moeten valideren en sanitizen.
jeroen2497donderdag 16 maart 2006 @ 16:45
met dus die functie hierboven ?
rickmansdonderdag 16 maart 2006 @ 16:53
quote:
Op donderdag 16 maart 2006 13:35 schreef SuperRembo het volgende:
Waarom maakt secureValue NULL van een lege string of een string met alleen spaties?
was specifiek voor mijn datamodel.
quote:
En een float wordt wordt een string (met quotes) maar een integer blijft een integer?

Je code is niet echt optimaal, een switch op gettype($value) lijkt me hier makkelijker.
Ik zou zelf als magic quotes aan zou staan meteen in het begin alle slashes strippen.
[ code verwijderd ]
gettype kon ik nog niet, maar dat is idd beter in mijn ogen
Chandlerdonderdag 16 maart 2006 @ 19:24
ik check mijn data altijd op input

dus wil je iets nummerics hebben dan doe ik gewoon is_numeric en dan kan 1 OR 1=1 dus niet... want dat is niet meer nummeric...
smesjzdonderdag 16 maart 2006 @ 20:47
(s)printf is ook veilige manier om gare invoer tegen te gaan en het zorgt ook goed leesbare code omdat je ook de maximaal toegestane (string) lengte kan meegeven en het kan dus ook type conversie doen.

Zie ook: http://nl2.php.net/manual/en/function.sprintf.php
SuperRembodonderdag 16 maart 2006 @ 21:13
quote:
Op donderdag 16 maart 2006 20:47 schreef smesjz het volgende:
(s)printf is ook veilige manier om gare invoer tegen te gaan en het zorgt ook goed leesbare code omdat je ook de maximaal toegestane (string) lengte kan meegeven en het kan dus ook type conversie doen.

Zie ook: http://nl2.php.net/manual/en/function.sprintf.php
Je kunt er idd nette query's mee maken, maar...
Aan het opgeven van een maximaal toegestane lengte voor een string heb je niets. Je moet een string eerst inkorten, dan pas addslashes toepassen. Als je het andersom doet kan het gebeuren dat er tussen de \ en ' afgekapt wordt, dan gaat je query alsnog op z'n bek. Ook wordt de string te kort afgekapt, hij telt de \'s ook mee.
smesjzdonderdag 16 maart 2006 @ 22:37
quote:
Op donderdag 16 maart 2006 21:13 schreef SuperRembo het volgende:

[..]

Je kunt er idd nette query's mee maken, maar...
Aan het opgeven van een maximaal toegestane lengte voor een string heb je niets. Je moet een string eerst inkorten, dan pas addslashes toepassen. Als je het andersom doet kan het gebeuren dat er tussen de \ en ' afgekapt wordt, dan gaat je query alsnog op z'n bek. Ook wordt de string te kort afgekapt, hij telt de \'s ook mee.
Dat klopt, maar je kan het ook gebruiken om bijv. XSS tegen te gaan en dan maakt het niet zo veel uit.
Die afkapping is ook meer voor de zekerheid gedaan, als ik een voornaam verwacht in mijn script kan ik deze prima afkappen op zo'n 40 tekens. Die limiet gebruik ik niet vaak voornamelijk bij het weergeven van floats of ints.

Verder is het slim om SQL strict mode aan te zetten in MySQL 5.0, dan geeft je query een error i.p.v. een waarschuwing als je meer data kwijt wil dan er in je kolom past. Je voorkomt dan truncation.

Het is vaak een combinatie van technieken die je kan gebruiken om SQL injection en XSS tegen te gaan, er is imho niet 1 magisch commando dat je invoer beveiligd. Ook zijn de ctype_* functies de moeite van het bekijken waard:

"It should be noted that ctype functions are always preferred over regular expressions, and even to some equivalent str_* and is_* functions. This is because of the fact that ctype uses a native C library and thus processes significantly faster."
Roonaandonderdag 16 maart 2006 @ 22:42
quote:
Op donderdag 16 maart 2006 06:45 schreef rickmans het volgende:
persoonlijk zou ik iedere var die je in je query gebruikt afvangen door zoiets als:
[ code verwijderd ]
Waarom gebruik je niet gewoon mysql_real_escape_string()

(Of is jouw code neergezet als een cross-db solution?)
rickmansdonderdag 16 maart 2006 @ 22:50
quote:
Op donderdag 16 maart 2006 22:42 schreef Roönaän het volgende:

[..]

Waarom gebruik je niet gewoon mysql_real_escape_string()

(Of is jouw code neergezet als een cross-db solution?)
cross-db in principe, al ga ik hem aanpassen aangezien de gettype functie een stuk mooier is .
smesjzdonderdag 16 maart 2006 @ 22:59
quote:
Op donderdag 16 maart 2006 22:50 schreef rickmans het volgende:

[..]

cross-db in principe, al ga ik hem aanpassen aangezien de gettype functie een stuk mooier is .
Is het niet logischer dat je aan die functie ook het verwachtte type meegeeft? Wat heb je er aan als je script een integer verwacht en hij krijgt een geescapte string of een float terug? Dan gaat je query als nog stuk...
Keiichidonderdag 16 maart 2006 @ 23:00
mysql_real_escapestring

Linkje: http://nl2.php.net/mysql_real_escape_string

[ Bericht 22% gewijzigd door Keiichi op 16-03-2006 23:02:10 (linkje) ]
rickmansvrijdag 17 maart 2006 @ 06:38
quote:
Op donderdag 16 maart 2006 22:59 schreef smesjz het volgende:

[..]

Is het niet logischer dat je aan die functie ook het verwachtte type meegeeft? Wat heb je er aan als je script een integer verwacht en hij krijgt een geescapte string of een float terug? Dan gaat je query als nog stuk...
Wat mij betreft niet, die functie is in mijn geval een stukje van de db layer en persoonlijk vind ik dat die alleen maar de input moet afhandelen, de classes die gebruik maken van de db layer zouden voor de datatype validatie moeten zorgen.
SuperRembovrijdag 17 maart 2006 @ 08:36
quote:
Op donderdag 16 maart 2006 22:42 schreef Roönaän het volgende:

[..]

Waarom gebruik je niet gewoon mysql_real_escape_string()

(Of is jouw code neergezet als een cross-db solution?)
Het voordeel van die functie is dat een string inclusief quotes wordt teruggegeven, of null als de input null is. Misschien is het beter om aparte functies voor string en numerieke data te maken.