Does $this-db->query() have mysql injection protection? I was wondering because I use this in instances and have not done anything to protect against sql injection.
The ActiveRecord style of querying with CodeIgniter escapes parameters, but not query().
You can use active record in this manner:
$someAge = 25;
$this->db->select('names, age');
$query = $this->db->get_where('people', array('age' => '>' . $someAge));
Read more about it here: https://www.codeigniter.com/userguide2/database/active_record.html
No, db->query() is not SQL Injection protected by default, you got few options.
Use Query Bindings
$sql = "SELECT * FROM some_table WHERE id = ? AND status = ? AND author = ?";
$this->db->query($sql, array(3, 'live', 'Rick'));
For more complex quires where you have to build the query as you go on, use compile_bind() to get chunk of SQL.
$sql = "SELECT * FROM some_table WHERE id = ? AND status = ? AND author = ?";
$safe_sql = $this->db->compile_bind($sql, array(3, 'live', 'Rick'));
etc.
Or use escape $this->db->escape() on parameters
$sql = "INSERT INTO table (title) VALUES(".$this->db->escape($title).")";
It's always best practise to use form validation first and include things like xss_clear, max_length etc either way in combination with one of the above.
you can use query bindings.
Example from CI 3 user guide:
$sql = "SELECT * FROM some_table WHERE id = ? AND status = ? AND author = ?";
$this->db->query($sql, array(3, 'live', 'Rick'));
Related
I am using codeigniter, and I have multiple queries that I have written inside seperate public functions. I would like to then use each of these queries and call them as strings inside another query to process them.
Here is what I mean
public function first_of_many_queries(){
$query = "
SELECT *
FROM users
WHERE id = $id
AND age = $age
AND gender = $gender
ORDER BY id DESC LIMIT 0, 1
";
return $this->db->escape_str($this->handeling_all_queries($query, 1));
}
public function handeling_all_queries($qry, $type){
$query = $this->db->query($qry);
if ($query->num_rows() > 0){
//doo stuff
}
}
My question is
Is this safe practice? is the use of $this->db->escape_str($this->handeling_all_queries($query, 1)) enough to prevent sql injection and other problems?
THANKS
No, it's not safe. Use PDO prepared statements for safe queries:
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
$stmt = $conn->prepare("SELECT * FROM users WHERE id = ? AND age = ? AND gender = ? ORDER BY id DESC LIMIT 0, 1");
$stmt->execute([$id, $age, $gender]);
Yes it is not at all safe. You can use Query Binding in Codeigniter.
Binding queries is another useful security process; if you use binding
with your queries, values are automatically escaped by CodeIgniter,
and there is no need for you to manually do so.
$query = "SELECT * FROM users WHERE id = ? AND age = ? AND gender = ? ORDER BY id DESC LIMIT 0, 1";
$this->db->query($query, $id, $age , $gender);
I am using below code to execute MySQL query in PHP.
$cus_id = '1';
$query = new QUERY();
$clause = "SELECT * FROM customers WHERE cus_id=:cus_id AND status='ACTIVE'";
$params = array('cus_id'=>$cus_id);
$result = $query->run($clause, $params)->fetchAll();
Now the question is: is it secure enough. Or do I need to bind the static String as well? Something like:
$clause = "SELECT * FROM customers WHERE cus_id=:cus_id AND status=:status";
$params = array('cus_id'=>$cus_id, 'status'=>'ACTIVE');
It's secure because ACTIVE isn't user input. So you don't need to bind it.
It's fine the way you have it. The value for status isn't being dynamically assembled and doesn't create any vulnerabilities.
I'm sorry if this is a duplicate question but I don't know how to solve my problem. Every time I try to correct my error I fail. My code is:
if (isset($_GET["comment"])) {$id = $_GET["comment"];}
$query = "SELECT * FROM posts WHERE id = {$id['$id']};";
$get_comment = mysqli_query($con, $query);
Can anybody correct the code to not show an error anymore and tell me what did I wrong?
Try this:
$id = isset($_GET['comment']) ? $_GET['comment'] : 0;
$query = "SELECT * FROM `posts` WHERE `id` = " . intval($id);
The use of intval will protect you from SQL injection in this particular case. Ideally, you should learn PDO as it is extremely powerful and makes prepared statements much easier to handle to prevent all injections.
An example using PDO might look like:
$id = isset($_GET['comment']) ? $_GET['comment'] : 0;
$query = $pdo->prepare("SELECT * FROM `posts` WHERE `id` = :id");
$query->execute(array("id"=>$id));
$result = $query->fetch(PDO::FETCH_ASSOC); // for a single row
// $results = $query->fetchAll(PDO::FETCH_ASSOC); // for multiple rows
var_dump($result);
First of all you should prevent injestion.
if (isset($_GET["comment"])){
$id = (int)$_GET["comment"];
}
Notice, $id contanis int.
$query = "SELECT * FROM posts WHERE id = {$id}";
Assuming your $id is an integer and you only want to make the query if it is set, here's how you could do it using prepared statements, which protect you from MYSQL injection attacks:
if (isset($_GET["comment"])) {
$id = $_GET["comment"];
$stmt = mysqli_prepare($con, "SELECT * FROM posts WHERE id = ?");
mysqli_stmt_bind_param($stmt, 'i', $id);
mysqli_stmt_execute($stmt);
mysqli_stmt_bind_result($stmt, $get_comment);
while (mysqli_stmt_fetch($stmt)) {
// use $get_comment
}
mysqli_stmt_close($stmt);
}
Most of these functions return a boolean indicating whether they were successful or not, so you might want to check their return values.
This approach looks a lot more heavy duty and is arguably overkill for a simple case of a statement containing a single integer but it's a good practice to get into.
You might want to look at the object-oriented style of mysqli which you might find a little cleaner-looking, or alternatively consider using PDO.
Not sure how I can do this. Basically I have variables that are populated with a combobox and then passed on to form the filters for a MQSQL query via the where clause. What I need to do is allow the combo box to be left empty by the user and then have that variable ignored in the where clause. Is this possible?
i.e., from this code. Assume that the combobox that populates $value1 is left empty, is there any way to have this ignored and only the 2nd filter applied.
$query = "SELECT * FROM moth_sightings WHERE user_id = '$username' AND location = '$value1' AND english_name = $value2 ";
$result = mysql_query($query) or die(mysql_error());
$r = mysql_numrows($result);
Thanks for any help.
C
Use
$where = "WHERE user_id = '$username'";
if(!empty($value1)){
$where .= "and location = '$value1'";
}
if(!empty($value2 )){
$where .= "and english_name= '$value2 '";
}
$query = "SELECT * FROM moth_sightings $where";
$result = mysql_query($query) or die(mysql_error());
$r = mysql_numrows($result);
Several other answers mention the risk of SQL injection, and a couple explicitly mention using prepared statements, but none of them explicitly show how you might do that, which might be a big ask for a beginner.
My current preferred method of solving this problem uses a MySQL "IF" statement to check whether the parameter in question is null/empty/0 (depending on type). If it is empty, then it compares the field value against itself ( WHERE field1=field1 always returns true). If the parameter is not empty/null/zero, the field value is compared against the parameter.
So here's an example using MySQLi prepared statements (assuming $mysqli is an already-instantiated mysqli object):
$sql = "SELECT *
FROM moth_sightings
WHERE user_id = ?
AND location = IF(? = '', location, ?)
AND english_name = ?";
$stmt = $mysqli->prepare($sql);
$stmt->bind_param('ssss', $username, $value1, $value1, $value2);
$stmt->execute();
(I'm assuming that $value2 is a string based on the field name, despite the lack of quotes in OP's example SQL.)
There is no way in MySQLi to bind the same parameter to multiple placeholders within the statement, so we have to explicitly bind $value1 twice. The advantage that MySQLi has in this case is the explicit typing of the parameter - if we pass in $value1 as a string, we know that we need to compare it against the empty string ''. If $value1 were an integer value, we could explicitly declare that like so:
$stmt->bind_param('siis', $username, $value1, $value1, $value2);
and compare it against 0 instead.
Here is a PDO example using named parameters, because I think they result in much more readable code with less counting:
$sql = "SELECT *
FROM moth_sightings
WHERE user_id = :user_id
AND location = IF(:location_id = '', location, :location_id)
AND english_name = :name";
$stmt = $pdo->prepare($sql);
$params = [
':user_id' => $username,
':location_id' => $value1,
':name' => $value2
];
$stmt->execute($params);
Note that with PDO named parameters, we can refer to :location_id multiple times in the query while only having to bind it once.
if ( isset($value1) )
$query = "SELECT * FROM moth_sightings WHERE user_id = '$username' AND location = '$value1' AND english_name = $value2 ";
else
$query = "SELECT * FROM moth_sightings WHERE user_id = '$username' AND english_name = $value2 ";
But, you can also make a function to return the query based on the inputs you have.
And also don't forget to escape your $values before generating the query.
1.) don't use the simply mysql php extension, use either the advanced mysqli extension or the much safer PDO / MDB2 wrappers.
2.) don't specify the full statement like that (apart from that you dont even encode and escape the values given...). Instead use something like this:
sprintf("SELECT * FROM moth_sightings WHERE 1=1 AND %s", ...);
Then fill that raw query using an array holding all values you actually get from your form:
$clause=array(
'user_id="'.$username.'"',
'location="'.$value1.'"',
'english_name="'.$value2.'"'
);
You can manipulate this array in any way, for example testing for empty values or whatever. Now just implode the array to complete the raw question from above:
sprintf("SELECT * FROM moth_sightings WHERE 1=1 AND %s",
implode(' AND ', $clause) );
Big advantage: even if the clause array is completely empty the query syntax is valid.
First, please read about SQL Injections.
Second, $r = mysql_numrows($result) should be $r = mysql_num_rows($result);
You can use IF in MySQL, something like this:
SELECT * FROM moth_sightings WHERE user_id = '$username' AND IF('$value1'!='',location = '$value1',1) AND IF('$value2'!='',english_name = '$value2',1); -- BUT PLEASE READ ABOUT SQL Injections. Your code is not safe.
Sure,
$sql = "";
if(!empty($value1))
$sql = "AND location = '{$value1}' ";
if(!empty($value2))
$sql .= "AND english_name = '{$value2}'";
$query = "SELECT * FROM moth_sightings WHERE user_id = '$username' {$sql} ";
$result = mysql_query($query) or die(mysql_error());
$r = mysql_numrows($result);
Be aware of sql injection and deprecation of mysql_*, use mysqli or PDO instead
I thought of two other ways to solve this:
SELECT * FROM moth_sightings
WHERE
user_id = '$username'
AND location = '%$value1%'
AND english_name = $value2 ";
This will return results only for this user_id, where the location field contains $value1. If $value1 is empty, this will still return all rows for this user_id, blank or not.
OR
SELECT * FROM moth_sightings
WHERE
user_id = '$username'
AND (location = '$value1' OR location IS NULL OR location = '')
AND english_name = $value2 ";
This will give you all rows for this user_id that have $value1 for location or have blank values.
Is there a way to execute a SQL String as a query in Zend Framework?
I have a string like that:
$sql = "SELECT * FROM testTable WHERE myColumn = 5"
now I want to execute this string directly withput parsing it and creating a Zend_Db_Table_Select object from it "by hand". Or if thats possible create a Zend_Db_Table_Select object from this string, to execute that object.
How can I do that? I didn't find a solution for this in the Zend doc.
If you're creating a Zend_DB object at the start you can create a query using that. Have a look at this entry in the manual : https://framework.zend.com/manual/1.12/en/zend.db.statement.html
$stmt = $db->query(
'SELECT * FROM bugs WHERE reported_by = ? AND bug_status = ?',
array('goofy', 'FIXED')
);
Or
$sql = 'SELECT * FROM bugs WHERE reported_by = ? AND bug_status = ?';
$stmt = new Zend_Db_Statement_Mysqli($db, $sql);
If you are using tableGateway, you can run your raw SQL query using this statement,
$this->tableGateway->getAdapter()->driver->getConnection()->execute($sql);
where $sql pertains to your raw query. This can be useful for queries that do not have native ZF2 counterpart like TRUNCATE / INSERT SELECT statements.
You can use the same query in Zend format as
$select = db->select()->from(array('t' => 'testTable'))
->$where= $this->getAdapter()->quoteInto('myColumn = ?', $s);
$stmt = $select->query();
$result = $stmt->fetchAll();
Here is an example for ZF1:
$db =Zend_Db_Table_Abstract::getDefaultAdapter();
$sql = "select * from user"
$stmt = $db->query($sql);
$users = $stmt->fetchAll();