I have the following code:
function dbPublish($status)
{
global $dbcon, $dbtable;
if(isset($_GET['itemId']))
{
$sqlQuery = 'UPDATE ' . $dbtable . ' SET active = ? WHERE id = ?';
$stmt = $dbcon->prepare($sqlQuery);
$stmt->bind_param('ii', $status, $_GET['itemId']);
$stmt->execute();
$stmt->close();
}
}
Do I need to mysql_real_escape_string in this case or am i okay?
No, you don't have to escape value yourself (i.e. no you don't need to call mysqli_real_escape_string), when you are using prepared statements : the DB engine will do that itself.
(Actually, if you were calling mysql_real_escape_string and using bound parameters, your strings would get escaped twice -- which would not be great : you'd end up with escaping characters everywhere...)
As a sidenote : your values are passed as integers (as indicated by the 'ii'), so you wouldn't have to call mysql_real_escape_string, even if you were not using prepared statements : as its name indicates, this function is used to escape... strings.
For integers, I generally just use intval to make sure the data I inject into my SQL queries really are integers.
(But, as you are using prepared queries, once again, you don't have to do that kind of escaping yourself)
No, you must not. Combining the two would result
in visible escape characters showing up in your data.
function dbPublish($status)
{
global $dbcon, $dbtable;
if(isset($_GET['itemId']))
{
$sqlQuery = 'UPDATE ' . $dbtable . ' SET active = ? WHERE id = ?';
$stmt = $dbcon->prepare($sqlQuery);
$stmt->bind_param('ii', $status, $_GET['itemId']);
$stmt->execute();
$stmt->close();
}
}
Related
I propose the following question ... I have to make sure that the following query also accept values with the quotes inside ..
I tried using mysqli_real_escape_string but it did not work .. I am attaching my attempts ..
1° Put the function during the post
$idCantiere = $_POST["idCantiere"];
$nomeCantiere = mysqli_real_escape_string($_POST["nomeCantiere"]);
$sql = "INSERT INTO Cantiere(
idCantiere,
nomeCantiere)
VALUES(
'$idCantiere',
'$nomeCantiere')";
if (mysqli_query($mysqli, $sql))
{
echo "<script type='text/javascript'>alert('Cantiere Inserto');
</script>";
} else
{
echo "Error: " . $sql . "" . mysqli_error($mysqli);
}
2° Put the function during the query
$idCantiere = $_POST["idCantiere"];
$nomeCantiere = $_POST["nomeCantiere"];
$sql = "INSERT INTO Cantiere(
idCantiere,
nomeCantiere)
VALUES(
'$idCantiere',
mysqli_real_escape_string('$nomeCantiere'))";
if (mysqli_query($mysqli, $sql))
{
echo "<script type='text/javascript'>alert('Cantiere Inserto');
</script>";
} else
{
echo "Error: " . $sql . "" . mysqli_error($mysqli);
}
How can I solve the problem?
Drop the mysqli_real_escape_string() and just use prepared statements which is simple and prevents sql injections.
<?php
$idCantiere = isset($_POST['idCantiere']) ? $_POST['idCantiere'] : null;
$nomeCantiere = isset($_POST['nomeCantiere']) ? $_POST['nomeCantiere'] : null;
$sql = $mysqli->prepare("INSERT INTO Cantiere (idCantiere,nomeCantiere) VALUES(?.?)");
$sql->bind_param("is",$idCantiere,$nomeCantiere);
if($sql->execute()){
//success message
}else{
//return error
}
?>
A prepared statement is a feature used to execute the same (or similar) SQL statements repeatedly with high efficiency.
Prepared statements basically work like this:
Prepare: An SQL statement template is created and sent to the database. Certain values are left unspecified, called parameters (labeled "?"). Example: INSERT INTO MyGuests VALUES(?, ?, ?)
The database parses, compiles, and performs query optimization on the SQL statement template, and stores the result without executing it
Execute: At a later time, the application binds the values to the parameters, and the database executes the statement. The application may execute the statement as many times as it wants with different values
Compared to executing SQL statements directly, prepared statements have three main advantages:
Prepared statements reduce parsing time as the preparation on the query is done only once (although the statement is executed multiple times)
Bound parameters minimize bandwidth to the server as you need send only the parameters each time, and not the whole query
Prepared statements are very useful against SQL injections, because parameter values, which are transmitted later using a different protocol, need not be correctly escaped. If the original statement template is not derived from external input, SQL injection cannot occur.
You are wrong to pass parameters to the mysqli_real_escape_string () function
before inserting the post you must put the connection string with which you access the DB
$connection=mysqli_connect("localhost","USER","PASSWORD","DB");
$nomeCantiere= mysqli_real_escape_string($connection, $_POST['nomeCantiere']);
your second attempt is wrong reuses my line of code in the first .. during the post
You have to pass the connection variable as first parameter
Eg:
$con=mysqli_connect("localhost","my_user","my_password","my_db");
$age = mysqli_real_escape_string($con, $_POST['age']);
Checkout documentation for more detail.
http://php.net/manual/en/mysqli.real-escape-string.php
You can try to replace quote with php
$nomeCantiere = $_POST["nomeCantiere"];
str_replace("'", "''", $nomeCantiere );
if you insert 2 quotes ( '' ) instead of one mysql will put that value in the table with only 1 quote
You are missing one parameter in function
mysqli_real_escape_string($con,$sql);
I'm currently writing a CMS and I want to prevent SQL injection.
I have the variable $url_variable which is a $_GET. Now I want to prepare the statement and search for the $url_variable in my table.
$stmt = $db_connect->prepare("SELECT * FROM $url_table WHERE url = ?");
$url_variable = $stmt->quote($url_variable);
$stmt->bind_param("s", $url_variable);
Now my questions: Is this code above right? Do I need the quote? And is it safe from any SQL injection?
You should create a whitelist for your $url_table variable and check if the table name is in your whitelist before you use it in your query. For example, you can do so with a simple if check:
if ($url_table == 'allowedTableName' || $url_table == 'anotherAllowedTableName')
{
$stmt = $db_connect->prepare("SELECT * FROM $url_table WHERE url = ?");
$stmt->bind_param("s", $url_variable);
//........
}
else {
die('Illegal table name provided');
}
You shouldn't quote your variable that is bound, you are good to go with the prepared statement!
Using bind_param protects those parameters from SQL injection. You don't need $stmt->quote, and it can actually cause the query to fail. It will add escape characters, and when you use bind_param it will search for these characters literally.
In this code:
if you use Url_Variable by method GET can be added strip_tags or htmlenteties to remove/prevent cross-site-scripting attacks by completely removing any HTML and PHP tags it finds, as in:
$url_variable=$_GET['url_variable'];
$url_variable=strip_tags($url_variable);
This is to avoid mal program/script.
More secure will be handled by prepared statements, as in:
$stmt = $db_connect->prepare("SELECT * FROM $url_table WHERE url = ?");
$stmt->bind_param("s", $url_variable);
Therefore, no need to use Quote in Mysqli since it has been used prepared statements and bind the parameters to ensure that you don't forget to escape a particular string which is led to a potential security problem.
You shouldn't quote bind variables in prepared statements - the statement takes care of that for you:
$stmt = $db_connect->prepare("SELECT * FROM $url_table WHERE url = ?");
$stmt->bind_param("s", $url_variable);
What would be the best way to protect this query from sql injection?
This example is just an example, I've read a few articles on internet but can't get my head around parametrised queries. Any links to useful articles will get a vote up but I think seeing this example would help me best.
$id = $_GET["id"];
$connection = odbc_connect("Driver={SQL Server};Server=SERVERNAME;Database=DATABASE-NAME;", "USERNAME", "PASSWORD");
$query = "SELECT id firstname secondname from user where id = $id";
$result = odbc_exec($connection, $query);
while ($data[] = odbc_fetch_array($result));
odbc_close($connection);
Thanks,
EDIT: I didn't make it obvious but I'm using SQL Server not mysql.
This is just an example, it won't always be a number I'm searching on.
It would be nice if the answer used parametrised queries as many people suggest this and it would be the same for all query's instead of different types of validation for different types of user input.
I think PDO objects are the best.
In a nutshell, here is how you use them.
$databaseConnection = new PDO('mysql:host='. $host .';dbname=' . $databaseName, $username, $password);
$sqlCommand = 'SELECT foo FROM bar WHERE baz=:baz_value;';
$parameters = array(
':baz_value' => 'some value'
);
$preparedStatement = $databaseConnection->prepare($sqlCommand);
$preparedStatement->execute($parameters);
while($row = $preparedStatement->fetch(PDO::FETCH_ASSOC))
{
echo $row['foo'] . '<br />';
}
The values you would enter for the SELECT criteria are replaced with parameters (like :field_value) that begin with a colon. The paramters are then assigned values in an array which are passed separately.
This is a much better way of handling SQL queries in my opinion.
The parameters are sent to the database separately from the query and protects from SQL injection.
Use prepared statements. First build a statement with the odbc_prepare() function, then pass the parameters to it and execute it using odbc_execute().
This is much more secure and easier than escaping the string yourself.
Lewis Bassett's advice about PDO is good, but it is possible to use prepared statements with ODBC without having to switch to PDO.
Example code, untested!
try {
$dbh = new PDO(CONNECTION_DETAILS_GO_HERE);
$query = 'SELECT id firstname secondname from user where id = :id';
$stmt = $dbh->prepare($query);
$stmt->bindParam(':id', $id, PDO::PARAM_STR);
$result = $stmt->execute();
$data = $stmt->fetchAll();
} catch (PDOException $e)
echo 'Problem: ', $e->getMessage;
}
Note: $e->getMessage(); may expose things you don't want exposed so you'll probably want to do something different on that line when your code goes live. It's useful for debugging though.
Edit: Not sure if you wanted a PDO or ODBC example but it's basically the same for both.
Edit: If you're downvoting me please leave a comment and tell me why.
To begin with, be careful with the variables you use in your queries, specially those that come from external sources such as $_GET, $_POST, $_COOKIE and $_FILES. In order to use variables inside your queries you should:
Cast numeric data to integer or float (whichever is appropriate)
Use appropriate escaping to escape other data
A simple example for mysql databases:
$id = $_GET["id"]; // contains: OR 1 = 1
$name = $_GET["name"]; // contains: ' OR '' ='
$query = "SELECT * FROM table WHERE id = " . intval($id) . " AND name = '" . mysql_real_escape_string($name) . "'";
// SELECT * FROM table WHERE id = 0 AND name = '\' OR \'\' =\''
For other database, the escaping practice varies. But generally you're supposed to escape the ' character with '', so:
$id = $_GET["id"]; // contains: OR 1 = 1
$name = $_GET["name"]; // contains: ' OR '' ='
$query = "SELECT * FROM table WHERE id = " . intval($id) . " AND name = '" . str_replace("'", "''", $name) . "'";
// SELECT * FROM table WHERE id = 0 AND name = ''' OR '''' ='''
Having said that, perhaps you might want to switch to PDO. It allows you to use prepared statements, the PDO driver does all the escaping.
The mysql variant came with a method called mysql_real_escape_string, which was appropriate for the version of SQL being targeted. The best thing you can do is write a method to escape the Id. It's important that your escape method is appropriate for the target database. You can also do basic type checking like is_numeric for numeric inputs will reject SQL string injections immediately.
See How to escape strings in SQL Server using PHP?
and follow some of the related links for explicit examples
I'm using PDO and was under the impression that prepare escaped apostrophes but I can see that isn't the case. what do I use to escape my strings for apostrophes?
$sql = 'SELECT test FROM test WHERE id = :id';
$sth = $dbh->prepare($sql);
$sth->execute(array(':id' => 1));
$red = $sth->fetchAll();
I suspect that whilst you might be using a prepared statement, you are not binding parameters. For example, instead of
$val = "Some string with an a'postrophe in it";
$stmt = $pdo->prepare("UPDATE table SET col = '$val'");
$stmt->execute();
You should use
$val = "Some string with an a'postrophe in it";
$stmt = $pdo->prepare('UPDATE table SET col = :val');
$stmt->bindParam('val', $val);
$stmt->execute();
or at least
$val = "Some string with an a'postrophe in it";
$stmt = $pdo->prepare('UPDATE table SET col = :val');
$stmt->execute(array('val' => $val));
This is using named parameters but you can also use positional ones using ? as a placeholder
I am not sure I understand your question, but this might help with PDO escaping:
PDO::quote($data)
I Suspect you are not using preparred statements correctly, or there is something wrong with your code.
The docs specifically states:
The parameters to prepared statements
don't need to be quoted; the driver
automatically handles this. If an
application exclusively uses prepared
statements, the developer can be sure
that no SQL injection will occur
(however, if other portions of the
query are being built up with
unescaped input, SQL injection is
still possible).
I have the following code:
function dbPublish($status)
{
global $dbcon, $dbtable;
if(isset($_GET['itemId']))
{
$sqlQuery = 'UPDATE ' . $dbtable . ' SET active = ? WHERE id = ?';
$stmt = $dbcon->prepare($sqlQuery);
$stmt->bind_param('ii', $status, $_GET['itemId']);
$stmt->execute();
$stmt->close();
}
}
Do I need to mysql_real_escape_string in this case or am i okay?
No, you don't have to escape value yourself (i.e. no you don't need to call mysqli_real_escape_string), when you are using prepared statements : the DB engine will do that itself.
(Actually, if you were calling mysql_real_escape_string and using bound parameters, your strings would get escaped twice -- which would not be great : you'd end up with escaping characters everywhere...)
As a sidenote : your values are passed as integers (as indicated by the 'ii'), so you wouldn't have to call mysql_real_escape_string, even if you were not using prepared statements : as its name indicates, this function is used to escape... strings.
For integers, I generally just use intval to make sure the data I inject into my SQL queries really are integers.
(But, as you are using prepared queries, once again, you don't have to do that kind of escaping yourself)
No, you must not. Combining the two would result
in visible escape characters showing up in your data.
function dbPublish($status)
{
global $dbcon, $dbtable;
if(isset($_GET['itemId']))
{
$sqlQuery = 'UPDATE ' . $dbtable . ' SET active = ? WHERE id = ?';
$stmt = $dbcon->prepare($sqlQuery);
$stmt->bind_param('ii', $status, $_GET['itemId']);
$stmt->execute();
$stmt->close();
}
}