I'm having trouble putting together mySQL queries containing quotation marks when I have to put them through PHP statements that also use quotation marks, and this gets even messier when I add PHP variables. So far, the best I've come up with is something like this:
$sqlQuery = 'SELECT document FROM `mentioned_places` WHERE name="'.$mentionedPlace.'";';
Which is really just a quagmire of quotation marks. Is there a simpler way to do this?
Escape everything. If you are using mysql_ statements, stop using them as they are deprecated. Take a look at PDO or Mysqli.
Both of them escape symbols if you prepare the queries, so you also prevent sql injection.
To secure your application you should use prepared statements with MySQLi or PDO.
Then you can separate your variables from your query and bind them to the statement.
You can use double quotes:
$sqlQuery = "SELECT document FROM `mentioned_places` WHERE name='$mentionedPlace'";
But you're better off to use prepared statements either with mysqli or PDO.
Using mysqli:
$db = new mysqli(...);
$sql = "SELECT document FROM `mentioned_places` WHERE name = ?";
$query = $db->prepare($sql);
$query->bind_param("s", $mentionedPlace);
$query->execute();
$query->bind_result($document);
$documents = array();
while ($query->fetch()) {
$documents[] = $document;
}
$db->close();
Using PDO:
try {
$db = new PDO('mysql:host=localhost;dbname=test;charset=UTF8', 'user', 'userpwd');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$sql = "SELECT document FROM `mentioned_places` WHERE name = ?";
$query = $db->prepare($sql);
$query->execute(array($mentionedPlace));
$documents = $query->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
echo "Exeption: " .$e->getMessage(); //TODO better error handling
}
$query = null;
$db = null;
You can follow this procedure for give quotation for MYSQL query
Refer this Link and
2.links
Its more useful.
Better you can use this link
Related
I've just created a simple API for a CAD/MDT I'm working on, I've managed to get it to show the correct information when I do /citations/userid/1. This will then display all the correct values from the SQL database however, if I do /citations/issued_by/kevingorman1000 it will just throw an error. I can't tell what the error is as I'm using Slim php and can't seem to get the errors to display.
Any ideas why it isn't working ? I've added my code below..
$app->get('/citation/issuedby/{issued_by}', function(Request $request, Response $response){
$issued_by = $request->getAttribute('issued_by');
$sql = "SELECT * FROM ncic_citations WHERE issuedby = $issuedby";
try{
// Get DB Object
$db = new db();
// Call Connection to DB
$db = $db->connect();
$stmt = $db->query($sql);
$issby = $stmt->fetchAll(PDO::FETCH_OBJ);
$db = null;
echo json_encode($issby);
} catch(PDOExecption $e) {
echo '{"error"} : {"text": '.$e->getMessage().'}';
}});
Any ideas why this is the case? Does it only allow getting via number or do I need too do something else? First time using this and kinda new to PHP as well.
Thanks for any help.
Your problem is called SQL injection. You can solve it by using prepared statements. Never escape the values with quotes or anything else, as others might have suggested.
$sql = "SELECT * FROM ncic_citations WHERE issuedby = ? ";
$stmt = $db->prepare($sql);
$stmt->execute([$issuedby]);
$issby = $stmt->fetchAll(PDO::FETCH_OBJ);
For a good tutorial on PDO and prepared statements I recommend: https://phpdelusions.net/pdo
It's because SQL error (missing quotes around string).
You try to send query
$sql = "SELECT * FROM ncic_citations WHERE issuedby = kevingorman1000";
Correct query has to be
$sql = "SELECT * FROM ncic_citations WHERE issuedby = 'kevingorman1000'";
This question already has answers here:
Are PDO prepared statements sufficient to prevent SQL injection?
(7 answers)
Closed 9 years ago.
I'm fairly new to PDO and wondering if my query below is safe from SQL injection. I'll be using this method throughout the site if so.
// make connection to DB
$db = new PDO('mysql:host='.$dateBaseHost.';dbname='.$dateBaseName, $dateBaseUsername, $dateBasePassword);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//simple query and binding with results
$query = $db->prepare(" SELECT * FROM `profile` WHERE `fullname` = :fullname ");
$search = (isset($_GET['search']) === true) ? $_GET['search'] : '' ; // ? : shorthand for if else
// bind parameters - avoids SQL injection
$query->bindValue(':fullname', $search);
//try... if not catch exception
try {
// run the query
$query->execute();
$rows = $query->fetchAll(PDO::FETCH_ASSOC);
echo '<pre>', print_r($rows, true),'</pre>';
}
catch (PDOException $e){
sendErrorMail($e->getMessage(), $e->getFile(), $e->getLine());
}
Yes - parameterized queries are safe from injection when used in this way.
As long as you use prepared statements properly, you're safe from injection. but as soon as you DIRECTLY insert any external data into a query, even if it's otherwise a prepared statement, e.g.
INSERT INTO $table VALUES (:param)
you're vulnerable - $table can be subverted in this case, even though you're using a prepared statement.
Anyone who tells you simply switching mysql->PDO or mysqli will make you safer is a flat out WRONG. You can be just as vulnerable to injection attacks with either library.
You should also
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
By default it uses emulated mode, which merely does what mysql_real_escape_string does. In some edge cases, you're still vulnerable to SQL injection.
yes, it's fairly safe but whole script could be improved:
if (isset($_GET['search']) {
// make connection to DB
$opt = array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
);
$dsn = "mysql:host=$dateBaseHost;dbname=$dateBaseName;charset=$dateBaseCharset";
$db = new PDO($dsn, $dateBaseUsername, $dateBasePassword, $opt);
//simple query and binding with results
$query = $db->prepare("SELECT * FROM profile WHERE fullname = ?");
$query->execute(array($_GET['search']));
$rows = $query->fetchAll();
echo '<pre>', print_r($rows, true),'</pre>';
}
you need to set errmode as a connection option
never use try..catch to handle error message. if you want to have a email on every error (which is just crazy), you have to set up my_exception handler() for this.
setting search to empty string doesn't make any sense
connect to PDO should be moved so separate file (not shown)
charset have to be set in DSN
I have a script which works without errors, but can't delete chosen value from mysql.
It looks like: What problem could be?
include('opendb.php');
$a = $_GET['new_pav'];
$select = mysql_query("SELECT * from naujiena WHERE new_pav = '$a'");
while($row = mysql_fetch_row($select)){
$result = mysql_query("DELETE FROM `naujiena` WHERE new_pav='".mysql_real_escape_string($a)."' ");
}
Firstly, read this (and below):
Please, don't use mysql_* functions in new code. They are no longer maintained and are officially deprecated. See the red box? Learn about prepared statements instead, and use PDO, or MySQLi - this article will help you decide which. If you choose PDO, here is a good tutorial.
The red warning box is telling you to stop using mysql_* in anything new.
As for your query, DELETE FROM x WHERE y=z is a valid query, so the error could be from your use of quotes (if new_pav is an int, then this could explain it); strings are quoted in MySQL.
Also, do not interpolate/concat strings in an SQL query, or you risk SQL Injection. Look up pdo, and start using classes for something that involves a state (the db connection), rather than a variable and countless functions. (I originally used mysqli here):
try {
$db = new PDO("mysql:dbname=$dbname;host=$dbhost", $dbuser, $dbpass);
$query = $db->prepare("SELECT COUNT(*) FROM naujiena WHERE new_pav = :pav");
if (!$query->bindParam(":pav", $_POST["new_pav"])) {
die("Input incorrect; couldn't bind");
}
$query->execute();
$rows = $query->fetchColumn(0); // fetch a single column. count(*) here.
if ($rows !== 0) { // It has a result~
$query = $db->prepare("DELETE FROM naujiena WHERE new_pav = :pav");
$query->execute(array(":pav" => $_POST["new_pav"]));
}
$db = null; // explicitly close connection
} catch (PDOException $e) { // catch any exception PDO throws at you.
// note that you should catch where appropriate.
die("Connection Failed: " . $e->getMessage());
}
Note that with SQL Injection, I could type ' OR 1=1 -- and delete your whole table.
As you can see, this is far from a one/two-liner, but you must never trust anything added to SQL that you didn't hardcode in yourself, period.
Apart from using mysql_ libraries your code:
$select = mysql_query("SELECT * from naujiena WHERE new_pav = '$a'");
while($row = mysql_fetch_row($select)){
$result = mysql_query("DELETE FROM `naujiena` WHERE new_pav='".mysql_real_escape_string($a)."' ");
}
In the SELECT you are not escaping the value of $a but in the delete you are escaping it.
Anyway if you are just doing a delete you do not need the SELECT or while loop. So you could use the following code:
$result = mysql_query("DELETE FROM `naujiena` WHERE new_pav='".mysql_real_escape_string($a)."' ");
I was just wondering if there was a way I could use some form of prepared statements in MySQL so I wouldn't have to escape all my inputs and I wouldn't have to switch all of my files from MySQL to MySQLi. I really don't trust the escaping functions, so if there is any alternatives that work in regular MySQL, it would be great.
Use PDO (PHP Data Objects) to connect to your MySQL database. This method will make sure that all database input will always be treated as text strings and you will never have to do any manual escaping.
This combined with proper use of html_entities() to display data from your database is a solid and good way to protect your page from injection. I always use PDO to handle all my database connections in my projects.
Create database object (and in this case enforce a certain character encoding):
try {
$db = new PDO("mysql:host=[hostname];dbname=[database]",'[username]','[password]');
$db->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND, "SET NAMES utf8");
$db->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
$db->exec('SET NAMES utf8');
} catch (PDOException $e) {
echo $e->getMessage();
}
Then use it like so:
$id = 1;
$q = $db->prepare('SELECT * FROM Table WHERE id = ?');
$q->execute(array($id));
$row = $q->fetch();
echo $row['Column_1'];
or
$q = $db->prepare('UPDATE Table SET Column_1 = ?, Column_2 = ? WHERE id = ?');
$q->execute(array('Value for Column_1','Value for Column_2',$id));
and with wildcards:
$search = 'John';
$q = $db->prepare('SELECT * FROM Table WHERE Column_1 LIKE ?');
$q->execute(array('%'.$search.'%'));
$num = $q->rowCount();
if ($num > 0) {
while ($row = $q->fetch()) {
echo $row['Column_1'];
}
} else {
echo "No hits!";
}
Read more:
How can I prevent SQL injection in PHP?
When *not* to use prepared statements?
how safe are PDO prepared statements
http://php.net/manual/en/book.pdo.php
If you don't want to deal with escaping your input, you can always pattern match it as it comes in then dispatch your prewritten statements. This is really only going to be worth the effort if you have relatively few possible statements to execute.
Is this the best way to do it?
Should I do this to every value in every query? GET and POST?
Is addslashes(mysql_real_escape_string()) overkill?
If you're using mysql_query() then yes, mysql_real_escape_string() is the best way. And yes, you have to apply it to every parameter you mix into your sql statement. E.g.
$query = "
SELECT
x,y,z
FROM
foo
WHERE
a = '". mysql_real_escape_string($_POST['a'], $mysql) . "'
AND b = '". mysql_real_escape_string($_POST['b'], $mysql) . "'
";
But you can also use prepared statements, e.g. with the pdo module. The parameters are transferred apart from the sql statement and therefore do not require escaping. It's more secure (since you can't forget the escaping or doing it wrong/for the wrong charset), often faster and very often even simpler than mixing the parameters into the statement. e.g.
$pdo = new PDO('mysql:host=localhost;dbname=test', '..', '..');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $pdo->prepare("
INSERT INTO
foo (x,y,z)
VALUES
(:x,:y,:z)
");
$stmt->bindParam(':x', $x);
$stmt->bindParam(':y', $y);
$stmt->bindParam(':z', $z);
// insert all records (0,0,0) ... (0,1,0) ... (9,9,9)
for($x=0; $x<10; $x++) {
for($y=0; $y<10; $y++) {
for($z=0; $z<10; $z++) {
$stmt->execute();
}
}
}
edit: and addslashes(mysql_real_escape_string()) is not only overkill but also wrong.
You need to have a mysql connection already established in your script to use mysql_real_escape_string().
Have you tried PDO?
It prevents mysql injection attacks automatically.
$db = new PDO("mysql:host=$dbhost;dbname=$default_dbname", $dbusername, $dbuserpassword);
$st = $db->prepare ('SELECT * from my_table WHERE owner= ? and dog = ?');
$st->execute (array('Bob', 'Rex'));
$data = $st->fetchAll();
Might want to use htmlentities() on output though.