The code below is very simple. PHP uses POST to collect a string from a form, which I am then looking to trim and run a preg_replace function which will strip any special characters except a single quote or a hyphen. Bare in mind that the entire code works fine without the involvement of the quotes or hyphen in the regex expression.
preg_replace("/[^\w\s'-]/", '', $raw_lemurName);
Those clean variables are then inserted into a database. Apache/2.4.37. MariaDB.
When I make lemurName a string like "Diademed Sifaka<>!", it works, and returns 'Diademed Sifaka'.
When I make it a string including a single quote, however, like "Coquerel's Sifaka" the operation doesn't complete and no information is inserted.
I have tested the regex expression on its own and it works fine, it seems that when you begin to involve SQL and databases that it ceases to work.
Worth noting:
Any ideas?
Much appreciated.
$raw_lemurName = isset($_POST['lemurName']) ? $_POST['lemurName'] : null;
$raw_lemurLat = isset($_POST['lemurLat']) ? $_POST['lemurLat'] : null;
$raw_family = isset($_POST['family']) ? $_POST['family'] : null;
//the regex expression below seems to be messing something up
$c_lemurName = trim(preg_replace("/[^\w\s'-]/", '', $raw_lemurName));
$c_lemurLat = strtolower(trim(preg_replace('/[^\w\s]/', '', $raw_lemurLat)));
$c_family = trim(preg_replace('/[^\w\s]/', '', $raw_family));
if (isset($_POST['submit'])) {
$query1 = "INSERT INTO `lemurs` (`id`, `lemur`, `latin`, `family`) VALUES (NULL, '$c_lemurName','$c_lemurLat','$c_family')";
$run_query = mysqli_query($connection, $query1);
if($run_query){
echo "Data has been inserted";
} else {
echo "Operation Unsuccessful";
}
header("location: index.php");
return;
}
This is a standard SQL injection problem. The issue stems from the way you are getting these variables into your query:
$query1 = "INSERT INTO `lemurs` (`id`, `lemur`, `latin`, `family`) VALUES (NULL, '$c_lemurName','$c_lemurLat','$c_family')";
Think about exactly what is happening here, all you are doing is concatonating strings together, so if $c_lemurName
is '
- then your SQL will become:
[...] VALUES (NULL, ''', '[...]
This actually really opens you up to what is called an "injection attack". Basically, a malicious user could set $c_family
to something like... ');drop table lemurs;--
- you are now executing an insert statement, and then a drop table statement, with the rest of your SQL being a comment.
There are several ways to combat this, the most frequently advised way is to look into paramaterised queries - which for the mysqli library have to be done through prepared statements. There's an example of this on the PHP docs page.