This question already has answers here:
How to include a PHP variable inside a MySQL statement
(5 answers)
Closed last year.
I'm trying to make like few text boxes and upon submit another php will be connected let's say it's database.php then the database.php will insert what's in the textboxes into the mysql database table but I'm not sure how I should be into the mysqli_query code....what I have now is
mysqli_query($db,"INSERT INTO jliu VALUE(null,$_GET['title'],$_GET['fname'],$_GET['lname'],$_GET['description'])");
and of course the $_GET won't work properly. I can't really figure how to get it correctly.
You need to break out of the string in order to concatenate it with the $_GET variables.
mysqli_query($db,"INSERT INTO jliu VALUES(null,".$_GET['title'].",".$_GET['fname'].",".$_GET['lname'].",".$_GET['description'].")");
But really you should look into prepared statements to avoid the gaping SQL injection security hole above.
With prepared statements you would be binding the $_GET variables to the parameters in the query.
$stmt = mysqli_prepare($db,"INSERT INTO jliu VALUES(null, ?, ?, ?, ?");
mysqli_stmt_bind_param($stmt, "s", $_GET['title']);
...
// and the same for the others
There's some more detail in the linked manual page on how to execute the prepared statement and return the result.
Please don't use mysql_query() and consorts, they are way too unsafe. Do have a look at PDO and use that instead. Specifically PDO::prepare() and PDOStatement::execute() will be your solution.
Your actual issue, inserting index values of an array into a string can be solved in two ways (more if you count heredoc, sprintf and whatnot):
Use curly braces:
"INSERT INTO jliu VALUE(null, {$_GET['title']}, {$_GET['fname']}, {$_GET['lname']}, {$_GET['description']})"
Use concatenation:
"INSERT INTO jliu VALUE(null, " . $_GET['title'] . ", " . $_GET['fname'] . ", " . $_GET['lname'] . ", " . $_GET['description'] . ")"
However, the overriding issue is that you shouldn't be doing this. With your code, you're wide open to SQL Injection vulnerabilities.
Use prepared statements, and insert your values in there. This creates a more secure (and marginally more performant) query, as you're only binding the values, and not changing the actual query itself. Code example:
if ($stmt = $mysqli->prepare("INSERT INTO jliu VALUES (NULL, ?, ?, ?, ?)")) {
$stmt->bind_param("ssss", $_GET['title'], $_GET['fname'], $_GET['lname'], $_GET['description']);
$stmt->execute();
}
You have to use a prepared statement and replace the variables with a placeholder.
http://php.net/manual/de/mysqli.prepare.php
Answering your question:
You may do something like below. Actually, that is to put a variable of array item into a string, not only for $_GET. Any array may be accessed like that:
$str = "some text {$_GET['title']}"
Or similar approach when you are working with objects:
$str = "some text {$obj->test}"
But, that is bad idea when you are working with sql queries. You should use some functions to clear your input in order to prevent sql injections.
The most stratiforward way is to use mysqli_real_escape_string:
$str = "some text " . mysqli_real_escape_string($_GET['title'])." ...";
Or you can use prepared statements which are more flexible
try this..
$title = mysqli_real_escape_string($_GET['title']);
$fname = mysqli_real_escape_string($_GET['fname']);
$lname = mysqli_real_escape_string($_GET['lname']);
$description = mysqli_real_escape_string($_GET['description']);
$stmt = mysqli_prepare($db,"INSERT INTO jliu VALUES(null,'".$title."','".$fname."','".$lname."','".$description."'");
mysqli_stmt_execute($stmt);
It should be like this.
$query = sprintf("INSERT INTO jliu VALUE(null,%s,%s,%s,%s)",$_GET['title'],$_GET['fname'],$_GET['lname'],$_GET['description']);
mysqli_query($db,$query);
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);
In a project I am working on for PHP and Mysqli, I have to use prepare and bind_param to for my mysqli statements. I wrote these statements before doing so and they work fine. This is before binding and preparing.
$sql = "INSERT INTO comments (commentid, userid, comment, commentdate)
VALUES (NULL, '".$_SESSION["userid"]."', '" . htmlspecialchars($comment, ENT_QUOTES) . "', CURRENT_TIMESTAMP)";
$conn->query($sql);
In the textarea where I write a comment, if I use enter and move to next line, the output would be something like:
Old Line New Line
Now, when I start binding values and preparing the statement my output gets a bit strange. Here is the code for that:
$userid = $_SESSION['userid'];
$stmt = $conn->prepare("INSERT INTO comments (commentid, userid, comment, commentdate)
VALUES (NULL, ?,?, CURRENT_TIMESTAMP)");
$stmt->bind_param("is", $userid, htmlspecialchars($comment, ENT_QUOTES));
$stmt->execute();
For some reason after doing it this way if I created a new line within the text are the output would be as follows:
Old Line/r/nNew Line
Is there something I am doing wrong that I can fix so that /r/n is not outputted to the page? Thanks for any help!
The solution to my problem I found had nothing to do with the html special characters within the bind param. It was the fact that I was already using mysqli_real_escape_string to retrieve the comment. If you already have escaped your string then there is no need to bind it but also you can just bind it without escaping! Either works.
Those line breaks entered into the textarea input field are converted by the htmlspecialchars() function into \r\n.
First, to remove the \r\n, you can use str_replace()
$escape_comment = htmlspecialchars( $comment, ENT_QUOTES );
$remove_line_breaks = str_replace( "\\r\\n", '', $escape_comment );
Or, instead of using htmlspecialchars(), why not use strip_tags(), then you can decide which tags are allowed in comments. Note:Unless you know that the comment content will be formatted properly, you may not want to use strip_tags()
$escape_comment = strip_tags ( $comment, '<a><p><i><strong><li>' );
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);
My prepared query looks like this:
$sql = "SELECT $t1.id FROM $t1 WHERE $t1.name IN (?)";
When I try:
$stmt = Sql::$select->prepare($sql);
$string="'aaa','bbb','ccc'";
$stmt->bind_param('s', $string);
...it doesn't return the expected results. It treats the string as one name and not many separate names. How can it be solved?
The rest of the function:
$stmt->execute();
$stmt->store_result();
return $stmt;
Try altering query like this
$sql = "SELECT $t1.id FROM $t1 WHERE FIND_IN_SET($t1.name, ?)>0";
$stmt = Sql::$select->prepare($sql);
$string='aaa,bbb,ccc';
$stmt->bind_param('s', $string);
And this solution is not reliable.
Please see FIND_IN_SET(str,strlist)
Correct method is to use separate placeholders for each element in the IN statement.
Another suggestion, get rid of the IN statement and run through a loop in php to generate the query and bind the params.
The problem is that the bind_param function with 's' threats the parameter as a single string, so it is basically transforming your query to:
"SELECT $t1.id FROM $t1 WHERE $t1.name IN (''aaa','bbb','ccc'')";
A quick fix would be to change the string variable to:
$string="aaa','bbb','ccc";
Note: without the leading/trailing quotes (you can make this using trim($string, "'")
You may also try inverting the quotes: using " instead of ' if this does not work.
A more reliable and robust solution is to change the query to incude a ? for each string (using arrays with expolode() / implode() php functions.
I'm having a slight problem with the PHP PDO library and prepared statements. As far as I can see the prepared statement below should work but it doesn't, instead I get: "PDOStatement::execute(): SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens".
My PHP code for this section looks like:
$sql = 'INSERT INTO '.POLYGON_TABLE.' (user_id, polygon, polygon_type) VALUES (:userId, PolygonFromText(\'POLYGON((:polygonArea))\'), :polygonType)';
$sth = $this->pdo->prepare($sql);
$sth->bindValue(':userId', $polygon->getUserId(), \PDO::PARAM_INT);
$sth->bindValue(':polygonArea', $polygon->getPolygonAsText(), \PDO::PARAM_STR);
$sth->bindValue(':polygonType', $polygon->getPolygonType(), \PDO::PARAM_STR);
if($sth->execute()) {
return true;
} else {
return false;
}
I have done a var_dump of $polygon->getUserId(), $polygon->getPolygonAsText() and $polygon->getPolygonType() and get the following:
string(1) "1"
string(226) "53.897910476098765 -1.739655277929728, 53.865530797116 -2.080231449804728, 53.67235280490181 -2.006073734960978, 53.68862047002787 -1.621552250585978, 53.89305512284903 -1.539154789648478, 53.897910476098765 -1.739655277929728"
string(7) "commute"
The issue is with $polygon->getPolygonAsText() as commenting out this particular bindValue call and the PolygonFromText(\'POLYGON((:polygonArea))\') from the SQL statement causes the query to work.
I'm now completely at a loss. Anyone know what's wrong here? I can't see anything wrong with the text contained within $polygon->getPolygonAsText(). I have searched high and low for a solution to this and spent several hours this evening tinkering with the code but to no avail.
I have even tried the suggestions in these 2 stack overflow topics but they didn't work either:
Invalid parameter number on PDO Prepared Statement
PHP PDO prepared statements
Any help would be much appreciated...
Did you try passing in the entire expression as the bind value?
$sql = 'INSERT INTO '.POLYGON_TABLE.' (user_id, polygon, polygon_type) VALUES (:userId, PolygonFromText(:polygonArea), :polygonType)';
$sth = $this->pdo->prepare($sql);
$area = sprintf("POLYGON((%s))", $polygon->getPolygonAsText());
$sth->bindValue(':userId', $polygon->getUserId(), \PDO::PARAM_INT);
$sth->bindValue(':polygonArea', $area, \PDO::PARAM_STR);
$sth->bindValue(':polygonType', $polygon->getPolygonType(), \PDO::PARAM_STR);
It appears that you're trying to use a named parameter inside a string:
PolygonFromText(\'POLYGON((:polygonArea))\')
This would be akin to doing something like this:
UPDATE foo SET bar = 'blah blah :wontwork blah blah'
What you should try instead is binding the whole string in the query:
PolygonFromText(:polygonArea)
And then including the rest of the string in the bound value:
$sth->bindValue(':polygonArea', 'POLYGON((' . $polygon->getPolygonAsText() . '))', \PDO::PARAM_STR);
Last resort you could do this:
$sql = "INSERT INTO ".POLYGON_TABLE." (user_id, polygon, polygon_type) "
."VALUES (:userId, PolygonFromText('POLYGON(". $polygon->$getPolygonAsText
.")'),:polygonType)";
But I think you should try the ? params first and see how that goes.
$sql = "INSERT INTO ".POLYGON_TABLE." (user_id, polygon, polygon_type) "
."VALUES (?, PolygonFromText('POLYGON(?)'), ?);";
$data = array($polygon->getUserId(), $polygon->getPolygonAsText(), $polygon->getPolygonType());
$query->execute($data);
Btw, I also think those single quotes around the POLYGON(?) function are dodgy... usually you don't quote a method call do you?