Escaping loads of characters going into MySQL - php

I've got an HTML form into which a user can enter an SQL query.
The query needs to be entered into a field of my MYSql database. But for complex queries that include % _ , ; ' " $ < > etc... it fails.
How would i go about entering this info into the DB without error?
I know the below is not a very secure way to do it, for now, I just need it to work :)
// Get values from form
$username = $_SESSION['user'];
$appname = $_POST['appname'];
$sql2 = $_POST['sql'];
// Insert data into mysql
$sqlquery="INSERT INTO puresql (username,appnm, query)VALUES('$username','$appname', '$sql2')";
$result=mysqli_query($dbconn,$sqlquery);

For anyone else with this issue. the below works, using mysqli_real_escape_string
$date = date("Y/m/d");
echo "$date";
$appname = mysqli_real_escape_string($dbconn, $_POST['appname']);
$sql2 = mysqli_real_escape_string($dbconn, $_POST['sql']);
$username = mysqli_real_escape_string($dbconn, $_SESSION['user']);
// Insert data into mysql
$sqlquery="INSERT INTO livepurespark (username,appnm, query, date)VALUES('$username','$appname', '$sql2', '$date')";
$result=mysqli_query($dbconn,$sqlquery);

Another way of saving complex texts in database fields with added benefit of protection from sql injection is by using parameterized query statements (Prepared Statements).
$username = $_SESSION['user'];
$appname = $_POST['appname'];
$sql2 = $_POST['sql'];
$stmt = mysqli_prepare($dbconn, "INSERT INTO puresql (username,appnm, query)VALUES('?','?','?')");
mysqli_stmt_bind_param($stmt, "sss", $username, $appname, $sql2);
mysqli_stmt_execute($stmt);

Related

Is this the right way to parameterize query? Is there any other way?

Well i learned how to parameterize queries in php but i just wanted to ask that is it now totally secure from sql injection or any other type of attacks and if it isnt what betternment can i do to secure it even more?
<?php
include 'db.php';
$name = "";
$pass = "";
if(isset($_POST['send'])) {
$name = $_POST['name'];
$sql_u = "SELECT * FROM users WHERE username='$name'";
$res_u = $connection->query($sql_u);
if (mysqli_num_rows($res_u) > 0) {
echo "Sorry Username already taken";
}
else {
$password = $_POST['pass'];
$hpass = password_hash($password, PASSWORD_DEFAULT);
$query=$connection->prepare("insert into users (username,password) values (?,?)");
$query->bind_param('ss',$name,$hpass);
if ($query->execute()) {
$query->close();
header('location:index.php');
} else {
header('location:not.php');
}
}
}
I want to know if their is a even more secure way than only parameterizing queries?
You're using parameters for the INSERT statement, but you skipped using parameters for the SELECT statement. Without parameterizing the SELECT, you still have an SQL injection vulnerability. You need to use parameters in all cases when you combine untrusted content with your SQL.
Parameters are a good way to prevent SQL injection when combining dynamic content as values in your SQL queries.
You asked if there were another way, so I will recommend that you use PDO if you're starting out with a new PHP project. It's a little bit easier than Mysqli. In my opinion, there's no reason to use Mysqli unless you're porting a legacy PHP application that had used the deprecated Mysql PHP extension.
Here's what it would look like using PDO:
$name = $_POST['name'];
$sql = "SELECT COUNT(*) FROM users WHERE username = ?";
$query = $connection->prepare($sql);
$query->execute([$name]);
$count = $query->fetchColumn();
if ($count > 0) {
echo "Sorry Username already taken";
}
else {
$password = $_POST['pass'];
$hpass = password_hash($password, PASSWORD_DEFAULT);
$sql = "insert into users (username, password) values (?, ?)";
$query = $connection->prepare($sql);
if ($query->execute([$name, $hpass])) {
header('location:index.php');
} else {
header('location:not.php');
}
}
I'm assuming that the PDO connection was made previously, and that it had been enabled with exceptions. If you don't enable exceptions, you should check return values from every prepare() and execute() call to make sure there are no errors.
The same is true for Mysqli, you can enable exceptions so you don't have to check for errors manually.
I also show in the example my preference to use SELECT COUNT(*) instead of SELECT *. It's probably a trivial optimization in this case, but if * refers to many columns or there are many rows matching username = $name then the fetch will need to transfer less data from the database.

updating data in a database - prepared statement (PHP)

I'm quite new to php and previously have just been using mysqli for my queries. However I always see people saying to use prepared statements instead, so i went through my project in an effort to change all my queries into prepared statements. This particular query is not updating
$email = $userDetails['email'];
$token = bin2hex(random_bytes(16));
$username = $userDetails['username'];
$timestamp = date('Y/m/d H:i:s');
$sql = "UPDATE users SET token = ? AND timestamp = ? WHERE email = ?";
$stmt = mysqli_prepare($connect, $sql);
mysqli_stmt_bind_param($stmt,"sss",$token,$timestamp,$email);
mysqli_stmt_execute($stmt);
You are using AND instead of , in your UPDATE query :
$sql = "UPDATE users SET token = ?, timestamp = ? WHERE email = ?";

PHP PDO Insert query with prepared statements

I am trying to run an sql query using PDO prepared statements
$sql = "INSERT INTO tickets (ticketnumber, status) VALUES (1234, Open) ";
$stmt = $connection->prepare($sql);
$stmt->execute();
But it is just not inserting. What have I done wrong?
Here is my connection:
$host = "localhost";
$db_name = "";
$username = "";
$password = "";
$connection = new PDO("mysql:host={$host};dbname={$db_name}", $username, $password);
Try this. It's much more secure.
Make sure you have included your connection file.
EDITED
$sql = "INSERT INTO `tickets` (ticketnumber, status) VALUES (:ticketnumber, :status)";
$stmt = $connection->prepare($sql);
$stmt->bindValue(':ticketnumber', 1234, PDO::PARAM_INT);
$stmt->bindValue(':status', 'Open', PDO::PARAM_STR);
$stmt->execute();
Also, the named parameters used above must NOT be enclosed in quotes. If you do so, it'll be treated as a literal string and not a named parameter.
You need to use quotes on strings before inserting them into a database.
Why use prepare if you're not preparing your data before sending it to the database?

sanitize using {$_GET['id']} doesn't display mysql info

I am trying to sanitize my $_GET input but for some reason, mysql doesn't retrieve the data from the DB. If I do this:
$user = mysqli_real_escape_string($connection, $_GET['id']);
//execute query to call user info
$query = "SELECT user
FROM company
WHERE user={$_GET['id']} ";
this will work and the results are displayed; however if I do this:
$user = mysqli_real_escape_string($connection, $_GET['id']);
//execute query to call user info
$query = "SELECT user
FROM company
WHERE user= '$user' ";
I don't get a database error, but nothing shows up.
Am I not sanitizing right? What's going on here? HELP, please!
Best way to avoid such situations is using prepared queries:
How can I prevent SQL injection in PHP?
It's very simple and effective:
$q = $db->prepare('SELECT user FROM company WHERE user=?');
$q->bind_param('i', $user);
$q->execute();
$result = $q->get_result();
while ($row = $result->fetch_assoc()) {
// do something with $row
}
It's cool because it's OOP and it's safe. Some links:
Connection to DB
Prepare statement
Bind parameters

Is mysql_real_escape_string() unsafe against hexadecimal encoded data?

We know that all user input must be escape by mysql_real_escape_string() function before executing on mysql in php script. And know that this function insert a \ before any ' or " character in user input. suppose following code:
$_POST['username'] = 'aidan';
$_POST['password'] = "' OR ''='";
// Query database to check if there are any matching users
$query = "SELECT * FROM users WHERE user='".mysql_real_escape_string($_POST['username']."' AND password='".mysql_real_escape_string($_POST['password']."'";
mysql_query($query);
// This means the query sent to MySQL would be:
echo $query;
this code is safe.
But I find out if user enters her inputs with hexadecimal format then mysql_real_escape_string() can not do any thing and user can execute her sql injection easily. in bellow 27204f522027273d27 is same ' OR ''=' but in hex formated and sql execute without problem :
$_POST['username'] = 'aidan';
$_POST['password'] = "27204f522027273d27";
// Query database to check if there are any matching users
$query = "SELECT * FROM users WHERE user='".mysql_real_escape_string($_POST['username']."' AND password='".mysql_real_escape_string($_POST['password']."'";
mysql_query($query);
// This means the query sent to MySQL would be:
echo $query;
But whether this is true and if answer is yes how we can prevent sql injection in this way?
If you are using mysql_real_escape_string(), odds are you would be better served using a prepared statement.
For your specific case, try this code:
/*
Somewhere earlier in your application, you will have to set $dbh
by connecting to your database using code like:
$dbh = new PDO('mysql:host=localhost;dbname=test', $DBuser, $DBpass);
*/
$_POST['username'] = 'aidan';
$_POST['password'] = "' OR ''='";
$user = $_POST['username'];
$password = $_POST['password'];
// Query database to check if there are any matching users
$query = "SELECT * FROM users WHERE user=? AND password=?";
$stmt = $dbh->prepare($query);
$stmt->bindParam(1, $user);
$stmt->bindParam(2, $password);
$stmt->execute();
This does require you to use PDO for your database interaction, but that's a good thing overall. Here's a question discussing the differences between PDO and mysqli statements.
Also see this StackOverflow question which is remarkably similar to yours and the accepted answer, from which I poached some of this answer.

Categories