<?php
error_reporting(0);
$servername = "localhost";
$username = "test_usern";
$password = "test_passwd";
$dbname = "test_db";
date_default_timezone_set("Europe/Amsterdam");
$ip = 'unknown';
if(!empty($_SERVER['HTTP_X_FORWARDED_FOR']))
{
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
}
elseif(!empty($_SERVER['REMOTE_ADDR']))
{
$ip = $_SERVER['REMOTE_ADDR'];
}
else
{
user_error("Uh-oh! Neither IP variable was set.");
}
$fname = $_REQUEST['fname'];
$fname1 = $_REQUEST['fname1'];
$fname2 = $ip;
$fname3 = $_GET['id'];
$fname4 = date('Y/m/d H:i:s');
try {
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "INSERT INTO logs (test, test1, test2, test3, test4)
VALUES ('$fname', '$fname1', '$fname2', '$fname3', '$fname4')";
// use exec() because no results are returned
$conn->exec($sql);
header("Location: index.php");
}
catch(PDOException $e)
{
header("Location: index.php");
}
$conn = null;
?>
Via het programma: SQLMap kwam ik erachter dat mijn form hier vulnerable voor is.
Hiermee kon ik zo'n beetje mijn hele database uitlezen en dit is niet mijn bedoeling!
Ik ben zelf niet een held in SQL maar ziet iemand een oplossing? :)
Als ik de code zo zie, neem ik aan dat "$_GET['id']" gelijk is aan de "UNIQUE ID / Auto increment" in jouw database. Het maakt niet uit of je PDO gebruikt, of een integer escaped een database id mag gewoon niet gebruikt worden in een post, get, header of cookie request aangezien een getal gewoon niet te verifiëren valt.
Je kan een SQL injection tegen gaan door deze inderdaad te laten escapen, maar dat houd niet weg dat ik het getal ID in elk ander getal kan veranderen zodat ik misschien de password van gebruiker "id" kan veranderen vanuit mijn sessie.
Heb zelf wat geprobeert te maken maar krijg een foutmelding:
Error: SQLSTATE[HY093]: Invalid parameter number: parameter was not defined
Ik wil dit zo snel mogelijk oplossen want dat is een groot lek in mijn site!
En als de code hierboven zou werken, zou dit dan wel veilig zijn?
Je kunt trouwens die typehints achterwege laten, daar doet PDO (ingeval van MySQL, weet niet hoe het bij de andere drivers zit) volgens mij helemaal niets mee. Daarnaast als je in PDO een variabele echt als integer wilt behandelen dan moet deze variabele van het type int zijn, anders fietst PDO hier alsnog quotes omheen (de enige manier om hier achter te komen is ook door het loggen van queries, een andere mogelijkheid is er niet), of je nu aangeeft dat het PARAM_INT moet zijn, of niet. Tegelijkertijd zal een variabele $whatever = '12' altijd als string behandeld worden, of deze waarde nu een "numeriek voorkomen" heeft of niet.