SQL-injection

Veldig vanlig å sende parametre som skal brukes i SQL-setninger, via URLen, f.eks http://www.foo.invalid/index.php?articleID=43

      <?php
      $query = "SELECT * FROM artikkler WHERE artikkelID = ".$_GET['articleID'];
      // Blir SELECT * FROM artikkler WHERE artikkelID = 43
      ?>
      

Dersom vi istedet endrer URLen til:
http://www.foo.invalid/index.php?articleID=0%20OR1=1
Så ender vi opp med å utføre en spørring som dette:

SELECT * FROM artikkler WHERE artikkelID = 0 OR 1=1

Andre muligheter

http://www.foo.invalid/index.php?articleID=0%20OR1=1;DROP%20TABLE%20artikkler;
// SELECT * FROM artikkler WHERE artikkelID = 0 OR1=1;DROP TABLE artikkler

http://www.foo.invalid/index.php?articleID=0%20OR1=1%20UNION%20SELECT%20*%20FROM%20users;
// SELECT * FROM artikkler WHERE artikkelID = 0 OR1=1 UNION SELECT * FROM users;

eksempel 1 2

Igjen er google 1 din venn


Hvordan unngå dette?

Low-tech

mysql__real_escape_string() / pg_escape_string()
is_numeric();

Veldig enkelt, men sårbart for uteglemmelser.

Automatisk

Man kan bruke biblioteker som f.eks pears DB-klasse.
Denne har metoder som prepare()/execute()/autoexecute(), som lar en sende inn et parameteriserte SQL-spørringer, hvor data man ønsker å sette inn i spørringen blir sendt inn separat.

        <?php
          $sth = $db->prepare('SELECT * FROM artikkler WHERE artikkelID = ?');
          $db->execute($sth, $_GET['articleID']);
        ?>
      

Eller
PDO-extension.

        <?php
          $stmt = $dbh->prepare("SELECT * FROM artikkler WHERE artikkelID = ?");
          $stmt->execute(array($_GET['articleID']));
        ?>