I know a standard query runs an SQL statement that requires all data to be escaped for safety, like preventing SQL injections.
And Prepared statements bind parameters where escaping data in not needed, and is ideal for queries that are being executed multiple times.
But I was wondering in terms of security and safety, what is the difference between these three query examples.
I know the first query ($query) with binding parameters is the safest and most ideal to use, but are the other two query examples ($query2 and $query3) also safe when using the CodeIgniter framework?
And if we just use php, is $query3 safe because the data variable its quoted?
Query 1
$query = "SELECT * FROM users WHERE id = ?";
$bind = array($id);
$query = $this->db->query($query, $bind);
Query 2
$query2 = "SELECT * FROM users WHERE id = '" . $this->db->escape_str($id) . "'";
Query 3
$query3 = "SELECT * FROM users WHERE id = '" . $id . "' ";
Related
I need to execute this query in my php code. My issue is that I have never run a query that uses a variable as part of it. This is my code, i do not get any results returned or an error. Where did I miss up?
$userID = getFields('users', JFactory::getUser(), true);
$db->setQuery("SELECT rep_id, inventory_id, value
FROM #data
WHERE inventory_id_id = 1
AND rep_id = " $userID ");
$results = $db->loadObjectList();
You use a period to concatenate strings in PHP.
$db->setQuery("SELECT rep_id, inventory_id, value
FROM #data
WHERE inventory_id_id = 1
AND rep_id = " . $userID);
Also, please note that your code is open to SQL Injection Attacks. I'd highly recommend switching to Prepared Statements.
I have an SQL query
qry1 =
"SELECT DISTINCT (forename + ' ' + surname) AS fullname
FROM users
ORDER BY fullname ASC";
This gets forename and surname from a table called users and concatenates them together, putting a space in the middle, and puts in ascending order.
I then put this into an array and loop through it to use in a select drop-down list.
This works, however, what I now want to do is compare the fullname with a column called username in another table called users.
I'm struggling with how to write the query though. So far I have...
$qry2
"SELECT username
FROM users
WHERE (forename + ' ' + surname) AS fullname
=" . $_POST['Visiting'];
Any advice on to what I am doing wrong?
Rather CONCAT the two columns together. Also remember to escape any variables before adding them to your query.
$qry2 =
"SELECT username AS fullname
FROM users
WHERE CONCAT(forename, ' ', surname)
='" . mysqli_real_escape_string($connection, $_POST['Visiting']) . "'";
Where $connection is your current db connection
I'm not sure that the use of the declared word 'AS' after 'WHERE' is correct in principle.
if you use MySQL, query should look like this:
SELECT [columns]
FROM [tables] [AS declareTableName]
WHERE [condition]
GROUP BY [declares|columns]
SORT BY [declares|columns]
But, i think your problem not in the query. Concatenating names in the query is incorrect. You must separate string with names in Back-end and than use it in query:
$names = explode(' ', $_POST['Visiting']);
This might work, assuming you use PDO:
$qry2 = "SELECT username FROM users
WHERE CONCAT(forename, ' ', surname) = '" . $conn->quote($_POST['Visiting']) . "'";
...but you should have a look at the possible vulnerabilities through SQL injections.
Without knowing which library you use for connecting to the MySQL database, it's impossible to give proper advise about which method you should use for escaping the user's input. quote is the PDO method for escaping, real-escape-string is the equivalent for MySQLi
You should really refer to using PDO.
When using PDO you can bind parameters to specified parts of your query. PDO also has built-in SQL-injection prevention, which is a great security measure that you won't have to deal with yourself. I hope this answers your question. See my example below.
Example:
// Create a new PDO object holding the connection details
$pdo = new PDO('mysql:host=localhost;dbname=test', $user, $pass);
// Create a SQL query
$query = "SELECT username FROM users WHERE (forename + ' ' + surname) AS fullname = :visiting;";
// Prepare a PDO Statement with the query
$sth = $pdo->prepare($query);
// Create parameters to pass to the statement
$params = [
':visiting' => $_POST['Visiting']
]
// Execute the statement and pass the parameters
$sth->execute($params);
// Return all results
$results = $sth->fetchAll(PDO::FETCH_ASSOC);
If you have any other questions about PDO, please refer to the following:
Official PDO documentation:
http://php.net/manual/en/book.pdo.php
Documentation on how to bind variables:
http://php.net/manual/en/pdostatement.bindparam.php
You can use this construction (without "AS fullname" and with apostrophes around variable):
$qry2 "SELECT username FROM users WHERE (forename + ' ' + surname) = '" . $_POST['Visiting'] . "'";
But for better security (SQL injection) You should use the escaping of variable. For example this construction, if You use MySQL database:
$qry2 "SELECT username FROM users WHERE (forename + ' ' + surname) = '" . mysql_real_escape_string($_POST['Visiting']) . "'";
Which one is correct?
Having trouble with single quotes vs double quotes in PHP and using Oracle 11g db...
<?php
$query1 = oci_parse($conn, 'SELECT * FROM SCHEMA.TABLE_A WHERE B_ID=' . $id);
$query1 = oci_parse($conn, "SELECT * FROM SCHEMA.TABLE_A WHERE B_ID='" . $id . "'");
?>
If id is numeric, you should not quote the value. If it's a character string, you should.
Regardless, using string manipulation to create an SQL statement is usually a bad practice that leaves your application vulnerable to SQL injection attacks.
Instead, you should use a prepared statement:
$query1 = oci_parse($conn, 'SELECT * FROM SCHEMA.TABLE_A WHERE B_ID=:id');
oci_bind_by_name($query1, ":id", $id);
oci_execute($query1);
I am writing some SQL and using AdoDb to connect to my database and run the queries and so on. I am using parametrized queries and have run into a snag.
Is their a way to pass an array of values to an in_clause in AdoDb/MySql for parametrization.
My problem is that if I pass a prepared string as the parameter i.e. 'test','test2','test3' it does not work as the library or database auto escapes it and adds external quotes at the start and end so all the internal quotes are then auto escaped thus the query returns nothing as it looks for '\'test\',\'test2\',\'test3\'' as opposed to what I fed it.
UPDATED WITH ANOTHER POSSIBLE METHOD TO ACCOMPLISH THIS
<?php
$in_clause = implode(",", $first_names);
$query = "
SELECT
mytable_id_pk
FROM
mytable
WHERE
FIND_IN_SET(mytable_fname," . $DB->Param('first_names') . ")"
$stmt = $DB->Prepare($query);
$result = $DB->Execute($stmt,array($in_clause));
?>
I would do it this way (as I was googling for a while and google came up with nothing useful):
$count = count($first_names);
$in_params = trim(str_repeat('?, ', $count), ', ');
$query = "
SELECT
mytable_id_pk
FROM
mytable
WHERE
mytable_fname IN ({$in_params});";
$stmt = $DB->Prepare($query);
$result = $DB->Execute($stmt, $first_names);
This should do it...
First a few tips:
Please read carefully the AdoDB documentation on prepared statements.
Never include ; in SQL query strings.
You can try something like this:
$question_marks = substr(str_repeat('?,', count($first_names)), 0, -1);
$query = "SELECT mytable_id_pk FROM mytable WHERE mytable_fname IN (" . $question_marks . ")";
$stmt = $DB->Prepare($query);
$result = $DB->Execute($stmt,$first_names);
WARNING: I haven't tested this (not having a mySQL installation here).
Is this the right way to use mysql_real_escape_string? I was using $GET but a friend told me to make it safer with real_escape_string:
$id = intval($_GET['id']);
$result = mysql_query("SELECT *
FROM products
WHERE id = $id") or die("err0r");
if(!$result) mysql_real_escape_string($id); {
No, you normally use mysql_real_escape_string to prepare variables for use in a query, but in your case:
you already use intval;
you use it in the wrong place.
You don't need it in your example.
No. That is entirely wrong, and I can't quite understand what you're intending the call to do.
The purpose of mysql_real_escape_string is to avoid SQL injection, which is one of the biggest security risks in a website. It stops your users giving input that manipulates the SQL in evil ways. For instance:
$sql = "SELECT FROM users WHERE username = '" . $_GET['username'] . "'";
If I put lonesomeday' or 'a' = 'a into $_GET['username'], your query becomes
SELECT FROM users WHERE username = 'lonesomeday' or 'a' = 'a'
and obviously arbitrary SQL could then be executed. mysql_real_escape_string escapes unsafe characters (such as ' in that example), so that they can't be used in this way.
$sql = "SELECT FROM users WHERE username = '" . mysql_real_escape_string($_GET['username']) . "'";
// SELECT FROM users WHERE username = 'lonesomeday\' or \'a\' = \'a'
The quotes are now escaped. so the query can't be manipulated into doing evil things.
With all that said, in this case, intval does all you need. It also ensures that nothing that is not an integer can be in $id, so your code is safe here from SQL injection.
NO, you need to escape before quering
$id = intval($_GET['id']);
$result = mysql_query("SELECT *
FROM products
WHERE id = '" . mysql_real_escape_string($id) . "'") or die("err0r");
if(!$result) {
}
Use:
$query = sprintf("SELECT *
FROM products
WHERE id = %d",
intval($_GET['id']));
$result = mysql_query($query) or die("err0r");
You use mysql_real_escape_string before the value is used in the query, otherwise you're not handling the SQL injection attack.
you want to escape it before you stick it in a query (Before it interacts with DB so you don't get injections).
// check if your $_GET is not empty otherwise you
// will run into "undefined variable"
if(!empty($_GET['id'])){
$id = intval($_GET['id']);
// to simplify you can escape here,
// or to be a bit more complex, you can escape in the query line.
$id = mysql_real_escape_string($id);
$result = mysql_query("SELECT *
FROM products
WHERE id = '$id'") or die("err0r");
}
else
print 'No ID';