1

I've made the following script that shows blogposts. $_MULT[0] shows 'blog', $_MULT[1] shows the ID of the blogpost.

I'm wondering: 1) Is this script safe for SQL injection? 2) What if I removed ctype_digit() ? Would it still be safe then?

<?php
error_reporting(E_ALL);

$db = new PDO('mysql:host=localhost;dbname=blablabla','blablabla','passwd'); 
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

echo '<h2>Blog</h2>';

$iTijd = time();

$_MULT = explode("/", $_GET['p']);
if($_MULT[0] == 'blog' AND isset($_MULT[1]))
{
    if(ctype_digit($_MULT[1]))
    {
        // query
        $sql = "SELECT Titel, Post, Datum FROM Blog WHERE Id = :Id AND Status = :Status AND Datum < :Tijd LIMIT 1"; 

        // prepare query     
        $stmt = $db->prepare($sql); 

        // bind values
        $stmt->bindParam(':Id', $a=$_MULT[1], PDO::PARAM_INT); 
        $stmt->bindParam(':Status', $a='1', PDO::PARAM_INT); 
        $stmt->bindParam(':Tijd', $a=$iTijd, PDO::PARAM_INT); 

        // execute query
        $stmt->execute(); 

        // select data from db     
        $aRow = $stmt->fetch(PDO::FETCH_ASSOC);

        // show blogpost
        echo '<h4>'. $aRow['Titel'] .'</h4><br />';
        $datum = $aRow['Datum'];
        $datum = date("d-m-Y", $datum);

        echo '<i>'. $datum.'</i> - '. $aRow['Post'];
    }
    else
    {
        echo "<h2>404 - Pagina niet gevonden</h2>";
    }
}
else
{
    // query
    $sql = "SELECT Id, Titel FROM Blog WHERE Status = :Status AND Datum < :Tijd ORDER BY Id DESC LIMIT 10"; 

    // prepare query     
    $stmt = $db->prepare($sql); 

    // bind values
    $stmt->bindParam(':Status', $a='1', PDO::PARAM_INT); 
    $stmt->bindParam(':Tijd', $a=$iTijd, PDO::PARAM_INT); 

    // execute query
    $stmt->execute(); 

    echo '<br /><ul>';

    // select data from db     
    while($aRow = $stmt->fetch(PDO::FETCH_ASSOC)) 
    { 
        echo '<h4><li><a href="http://myurl.ext/blog/'. $aRow['Id'] .'" title="'. $aRow['Titel'].' ">'. $aRow['Titel'] .'</a></li>
        </h4>'; 
    } 

    echo '</ul>';
    if($stmt->rowCount() == 0)
    {
        echo '<p>Er zijn nog geen blogposts toegevoegd.</p>';
    }
}
?>

Is that safe? And what should I do with this? Just leave it?

$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
J.WWWWW
  • 11
  • 3
  • Have you considered using `bindValue(':Id', $_MULT[1], PDO::PARAM_INT)` instead of that weird hack of `bindValue(':Id', $a=$_MULT[1], PDO::PARAM_ING)`? – Niet the Dark Absol Oct 19 '14 at 09:38
  • Yep that didn't work weird enough :/ so I had to use $a=$_MULT[1] – J.WWWWW Oct 19 '14 at 09:41
  • `bindValue` didn't work?? – Niet the Dark Absol Oct 19 '14 at 09:47
  • It didn't work but it worked when I did $a=$_MULT[1] But that is not why I opened this topic, I want to know if the way I did it, is safe, and what happens when i remove ctype_digit. Is it (still) safe then? – J.WWWWW Oct 19 '14 at 09:52
  • Looks safe to me. You may want to look into the [`filter` extension](http://php.net/filter). About the `PDO::ATTR_EMULATE_PREPARES` attribute, it emulates the "prepared" part of prepared statements (i.e. it does not send the prepared statement to the database server before the variables are inserted). Someone else [has asked about it](https://stackoverflow.com/questions/10113562/pdo-mysql-use-pdoattr-emulate-prepares-or-not). – Sverri M. Olsen Oct 19 '14 at 09:54
  • [You can only bind variables and not value literals](http://stackoverflow.com/a/23843534/53114) as the second parameter of `bindParam` is [passed by reference](http://php.net/language.references.pass). – Gumbo Oct 19 '14 at 10:00

1 Answers1

-1

Strange code, but if You want use it change if statement to:

if($_MULT[0] == 'blog' && ! empty($_MULT[1])) { ... }

if(ctype_digit( (string) $_MULT[1])) { ... }
trzyeM-
  • 923
  • 8
  • 10