DEV Community

Cover image for Protect your project from SQL injections
Frank Wisniewski
Frank Wisniewski

Posted on

Protect your project from SQL injections

In the following example I use a SQLite memory database to manage my vehicles...

The user interface
The user interface

The code for this project...

<?PHP
function createMemoryDB () {
  // First we need some data, 
  // I have some vehicles that need to be managed
  $sqlCreate = <<<ENDSQL
  CREATE TABLE myvehicles (id INTEGER PRIMARY KEY, vehicle TEXT, parkingspace TEXT);
  INSERT INTO myvehicles (vehicle, parkingspace) VALUES 
  ('Mercedes GLA', 'Garage 1 Place 11'),
  ('Mercedes SLK', 'Garage 2 Place 14'),
  ('Missile Launcher', 'Hall 2 Place 3'),
  ('Mercedes Vito', 'Garage 1 Place 12'),
  ('Bobbycar', 'Summer House Nizza'),
  ('Nissan Micra', 'Garage 1 Place 16')
  ;
  ENDSQL;
  $memDB = new PDO('sqlite::memory:');
  $memDB->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  $memDB->exec($sqlCreate);
  return $memDB;
}
function tableFromArray($array){
  $table = "<table><thead><tr>";
  $header = array_keys($array[0]);
  foreach ($header as $key){
    $table .= '<th>'. $key;
  }
  $table.='</tr></thead><tbody>';
  foreach($array as $key=>$row) {
      $table.= "<tr>";
      foreach($row as $key2=>$row2){
          $table.= "<td>" . $row2 ;
      }
      $table.= "</tr>";
  }
  $table.= "</tbody></table>";
  return $table;
}
// create DemoDB
$memDB = createMemoryDB();
$action = $_POST['action'] ?? ""; 
if ($action=== 'addcar'){
  $vehicle = $_POST['vehicle'];
  $parkingspace = $_POST['parkingspace'];
  // insert into database
  $result = $memDB->exec("
  INSERT INTO myvehicles (vehicle, parkingspace) values ('$vehicle', '$parkingspace');");
}
$result = $memDB->query('SELECT vehicle, parkingspace FROM myvehicles');
if ($result){
  $allVehicles = $result->fetchAll(PDO::FETCH_ASSOC);
}
if (sizeof($allVehicles)>0){
  $myTable=tableFromArray($allVehicles);
} else {
  $myTable='';
}
?>
<!DOCTYPE html>
<html lang="de">
<head>
  <meta charset="UTF-8">
  <title>SQL-Attack</title>
  <link rel="stylesheet" href="https://unpkg.com/@picocss/pico@latest/css/pico.min.css">
  <style>th{font-weight:bold;}</style>
</head>
<body>
  <div class="container">
    <hgroup>
      <h1>my Vehicles</h1>
      <h2>where can i find them...</h2>
    </hgroup>
    <hr>
    <?=$myTable?>
    <h3>add a new vehicle:</h3>
    <form method="post">
    <div class=container>
      <h2>Fetch Data</h2>
      <div class=grid>
        <input type=hidden 
            name=action value='addcar'>
        <label>Vehicle:
          <input type=text name=vehicle 
            placeholder="vehicle" required>
        </label>
        <label>Parking Space:
          <input type=text name=parkingspace 
            placeholder="parking space" required>
        </label>
      </div>
      <button>Add new Vehicle</button>
    </div>
  </form>
  </div>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

When I fill out the form...

the filled form

I get the following result:

the result

Now I try the SQL injection, I fill out the form as follows:

Hackit'); DELETE FROM myvehicles;INSERT INTO myvehicles (vehicle, parkingspace) VALUES ('Hack' , 'Hackers Paradise'

the filled form

After submitting I get this result:

hacked result

In real life, the data would now be gone, so it is advisable to work with prepared statements...

change this part to

$action = $_POST['action'] ?? ""; 
if ($action=== 'addcar'){
  $vehicle = $_POST['vehicle'];
  $parkingspace = $_POST['parkingspace'];
  // insert into database
  // use prepared statments
  $query = "INSERT INTO myvehicles (vehicle, parkingspace) values (:vehicle, :parkingspace);";
  $myQuery = $memDB->prepare($query);
  $prep = [
    'vehicle'=>$vehicle,
    'parkingspace'=>$parkingspace
  ];
  $isOK = $myQuery->execute($prep);   
}
Enter fullscreen mode Exit fullscreen mode

now an XSS Attack:

sample XSS

your result after submit:

xss result

Howto prevent:

first I write a simple function:

function htmlOut ($val){
  return htmlspecialchars($val, ENT_COMPAT | ENT_HTML5, "UTF-8");
}
Enter fullscreen mode Exit fullscreen mode

and alter the tableFromArray function

function tableFromArray($array){
  $table = "<table><thead><tr>";
  $header = array_keys($array[0]);
  foreach ($header as $key){
    $table .= '<th>'. $key;
  }
  $table.='</tr></thead><tbody>';
  foreach($array as $key=>$row) {
      $table.= "<tr>";
      foreach($row as $key2=>$row2){
          $table.= "<td>" . htmlOut($row2) ;
      }
      $table.= "</tr>";
  }
  $table.= "</tbody></table>";
  return $table;
}
Enter fullscreen mode Exit fullscreen mode

your result after XSS Attack:

result
Good Luck

Top comments (1)

Collapse
 
julia_kot profile image
Julia K

Thank you for code examples. This way it is impossible for an attacker to inject malicious SQL.

Indeed, the correct way to avoid SQL injection attacks is to use prepared statements and parameterized queries for any supported database driver. These are SQL statements that are sent to and parsed by the database server separately from any parameters.