MySQL, PHP Acceptable way to sanitize Posted variable [duplicate] - php

This question already has answers here:
How can prepared statements protect from SQL injection attacks?
(10 answers)
Closed 5 years ago.
After my prior post PHP Looping through elements and adding to Database
I went back to the drawing board, as I'm terrified of injection and would like some advice. Is the below "safe":
$stmt = $conn->prepare("INSERT INTO responses (skey, rtext) VALUES (?, ?)");
$stmt->bind_param("is", $skey, $rtext);
$skey = 1;
$rtext = mysqli_real_escape_string($conn,$_POST['Q1Answer']);
if(!$stmt->execute()){trigger_error("there was an error....".$con->error, E_USER_WARNING);}
$skey = 2;
$rtext = "Hello";
if(!$stmt->execute()){trigger_error("there was an error....".$con->error, E_USER_WARNING);}
$stmt->close();
$conn->close();
I could also call the below function:
function SanitizeForSQL($str)
{
if( function_exists( "mysql_real_escape_string" ) )
{
$ret_str = mysql_real_escape_string( $str );
}
else
{
$ret_str = addslashes( $str );
}
return $ret_str;
}
Would any of the above help prevent injection?

When you bind variables to placeholder values your job is done. mysqli or PDO or whatever database driver you're using is responsible for safely encoding it from that point forward.
There is absolutely no need to add more sanitization functions on top of that, and many of these do more harm than good. The most important thing should be ensuring you never put unescaped data in your query, and the safest way to do that is to be extremely disciplined about using placeholder values.
If you pre-escape things then you'll have to un-escape them later. Data you assume is going to be used in HTML may very well turn up in a JSON document when you add an API to something, so now it has to be de-HTML-escaped before properly JSON escaping. This is really obnoxious.
Keep the data in your database as neutral as possible. That is, as raw as you can manage. If you're using Markdown, for example, keep the raw markdown in the database. If you're allowing certain HTML tags, put in whatever the user put in and scrub with a white-lister later. You may want to change your rules in the future to be more relaxed, and if you've already purged that content it's gone forever.

You should use access token. For each database access you should define access token for client and without token query won't be executed.
You can define your function like this:
function SanitizeForSQL($str,$token)
{
if($token=="Predefined token")
{
if( function_exists( "mysql_real_escape_string" ))
{
$ret_str = mysql_real_escape_string( $str );
}
else
{
$ret_str = addslashes( $str );
}
return $ret_str;
}
else return "Token is invalid".
}

Related

Uncaught ArgumentCountError: Too few arguments to function

I want to save the data with $_POST method to the database using PDO with PHP. I wrote the code, but it gave me an error. Is there anyone who can figure this out?
macex.php
function daireekle($daire_no,$dpass,$daire_statu,$daire_adi,$daire_soyadi){
$sql ="insert into users (KULLANICIADI,SIFRE,TIPI,ADI,SOYADI) values ('$daire_no','$dpass','$daire_statu','$daire_adi','$daire_soyadi')";
$insert =$this->connection->query($sql);
}
Blok.html
<?php
$sinif = new macex();
if ($_POST) {
$daire_no = $_POST['daireno'];
$daire_adi = $_POST['daireadi'];
$daire_soyadi = $_POST['dairesoyadi'];
$daire_statu = $_POST['statu'];
$dpass = $_POST['dpass'];
$sinif->daireekle('users', ['KULLANICIADI', 'SIFRE', 'TIPI', 'ADI', 'SOYADI'], [$daire_no, $dpass, $daire_statu, $daire_adi, $daire_soyadi]);
}
?>
Your code is a bit difficult to understand, in terms of structure, but you're definitely misusing PDO by injecting unsanitized POST data.
If I were to attempt to convert your sample into something workable, I would suggest the following amendments:
(Note: Assuming $this->connection-> is your PDO object)
Blok.html
(not sure why you've called this PHP file Blok.html)
<?php
$sinif = new macex();
if ($_POST) {
$sinif->daireekle( $_POST );
}
?>
macex.php
function daireekle( $postArray ){
// Parameterised PDO will mostly prevent SQL Injection, but it's still best practice
// to validate and sanitize your inputs, especially if they are coming from the user
$daire_no = $postArray ['daireno'];
$daire_adi = $postArray ['daireadi'];
$daire_soyadi = $postArray ['dairesoyadi'];
$daire_statu = $postArray ['statu'];
$dpass = $postArray ['dpass'];
// Define the query with positional params
$sql = 'INSERT INTO users (KULLANICIADI, SIFRE, TIPI, ADI, SOYADI) VALUES (?,?,?,?,?)';
// Create an array of your params in the order they apply to the query
$paramsArray = array('$daire_no','$dpass','$daire_statu','$daire_adi','$daire_soyadi');
// Prepare the parameterised query
$query = $this->connection->prepare($sql);
// Execute the INSERT query with the parameters
$query->execute($paramsArray);
}
You could of course use different variations on the above, included named parameters, but it's conciser to explain as per the above.

How to prevent SQL Injection in parameters with CakePHP

How to prevent SQL Injection while fetching data from the database when using parameters received from the user input:
if(isset($_GET['cityval']) && $_GET['cityval'] !=''){
$city = $this->request->query('cityval');
$searching .= " and college_city in ($city) ";
} else {
$searching .= "";
}
if(isset($_GET['scholarship']) && $_GET['scholarship'] !=''){
$searching .= " and college_scholarship = '".$_GET['scholarship']."' ";
} else {
$searching .= "";
}
And my main query is below
$search = $this->Search->query("select * from colleges where college_id!='' and status='active' $searching order by $order desc limit $start, 10 ");
Don't use raw queries. Simply use the query builder CakePHP provides, and it will prevent injection for you. See the online CakePHP book for more information.
It is SUPER rare to need to use raw queries in CakePHP.
What you try to do is obviously to search by get parameters. There is a wonderful plugin that makes it pretty easy https://github.com/FriendsOfCake/search
It could be actually that easy with the plugin:
$query = $this->Colleges->find('search', [
'search' => $this->request->query
]);
$this->set('results', $this->Paginator->paginate($query));
The search params itself will be handled in the model layer, check the plugins documentation on that. And the framework will take care of sanitizing the input.
It seems that Cake ORM uses PDO:
Underneath the covers, the query builder uses PDO prepared statements
which protect against SQL injection attacks.
Reference: https://book.cakephp.org/3.0/en/orm/query-builder.html
Unfortunately the way you're creating the query is vulnerable as you're not using Cake ORM neither PDO prepared statements.
If you want to use raw queries you could do something like this to protect your code:
// Add this in the beginning of the file/code:
use Cake\Datasource\ConnectionManager;
// Replace connection_name with the name of your connection (maybe it's "default")
$connection = ConnectionManager::get('connection_name');
$bindList = [];
$city = $this->request->query('cityval');
// PDO as a limitation for the parameter markers. See in the comments below
$cityList = array_filter(explode(',', $city), function($item) {
return preg_match('/^\d+$/', $item);
});
$csvCity = implode(',', $cityList);
$scholarship = $this->request->query('scholarship');
if (!empty($csvCity)) {
$searching .= " and college_city in ($csvCity)";
}
if (!empty($scholarship)) {
$searching .= " and college_scholarship = :scholarship";
$bindList['scholarship'] = $scholarship;
}
$stmt = $connection->prepare($searching);
$stmt->bind($bindList);
$stmt->execute();
// Read all rows.
$rows = $stmt->fetchAll('assoc');
// Read rows through iteration.
foreach ($rows as $row) {
// Do work
}
PDO has a limitation and because of that there's no proper way to use the SQL IN() clause in a prepared statement (to bind the values to it), so we need to parse manually the values to be inside that clause as I did in the code.
From the PDO Prepare manual page:
Note: Parameter markers can represent a complete data literal only.
Neither part of literal, nor keyword, nor identifier, nor whatever
arbitrary query part can be bound using parameters. For example, you
cannot bind multiple values to a single parameter in the IN() clause
of an SQL statement.
References
CakePHP 3.3 Cookbook - Database basics
PHP Manual - PHP Data Objects
PHP The Right Way

Question while reading Learning PHP, MySQL & JavaScript by Robin Nixon RE: Sanitizing Input PHP [duplicate]

This question already has answers here:
How can I prevent SQL injection in PHP?
(27 answers)
Closed 6 years ago.
I'm currently reading and learning PHP from a book that offers this as the proper way to sanitize input from forms:
function mysql_entities_fix_string($connection, $string)
{
return htmlentities(mysql_fix_string($connection, $string));
}
function mysql_fix_string($connection, $string)
{
if (get_magic_quotes_gpc()) $string = stripslashes($string);
return $connection->real_escape_string($string);
}
Which is great, except I know that get_magic_quotes_gpc() is deprecated in the current version of PHP. From looking at a few different resources I learned that instead of using get_magic_quotes_gpc() I should just use an sql prepared statement. That confuses me though because I would presume that we still need to do some functional cleaning of the string.
Unless I'm wrong(it happens, I'm relatively new at this) this is a big no-no, regardless of the prepared statement:
$username = $_POST['username'];
$stmt = $conn->prepare("SELECT password FROM users WHERE username=?");
$stmt->bind_param("s", $username");
$stmt->execute();
...
but if that's the case, is this an acceptable sanitation process:
function get_post($conn, $var) {
return $conn->real_escape_string($_POST[$var]);
}
...
$username = get_post($conn, 'username');
$stmt = $conn->prepare("SELECT password FROM users WHERE username=?");
$stmt->bind_param("s", $username);
$stmt->execute();
...
or do I need to add some other escaping function on top of it?
Uh no. That sanitization code is garbage.
Your proposed sanitization process with PDO statements is fine. That is all you need.

Is my PDO INSERT INTO enough secure?

I would like your opinion about my code. Is it secure enough against any injections.
Thanks for your replies.
class Product extends DB {
public function __construct() {
$db = $this->DB();
if(isset($_POST['productName'])) {
foreach ($_POST as $key => $value) {
if (ini_get('magic_quotes_gpc'))
$_POST[$key] = stripslashes($_POST[$key]);
$_POST[$key] = htmlspecialchars(strip_tags($_POST[$key]));
}
$this->AddProduct();
}
}
public function AddProduct() {
$sSQL = "INSERT INTO ".PREFIX."product (productName, productPrice)
VALUES (:productName,:productPrice)";
$query = $this->db->prepare($sSQL);
$query->execute(array(
":productName" => $_POST['productName'],
":productPrice" => $_POST['productPrice']
));
}
}
Using query parameters is enough to make it secure against SQL injection vulnerability.
The code that calls htmlspecialchars and strip_tags is not relevant to SQL injection. It might be called for to prevent Cross-Site Scripting vulnerabilities, but that's a separate issue. I don't recommend doing those steps as you insert data into the database. Just filter against XSS vulnerabilities when you output to HTML. Otherwise, you get literal & sequences stored in your database, and that's premature. You aren't necessarily going to use the data to display in HTML every time. Just encode it when you output, not when you input.
I never bother with compensating for the possible magic_quotes_gpc. Test for it when you deploy your app, and abort the deployment. It's not valid for any PHP instance to set magic_quotes_gpc in 2014.

php mysqli should I be using real_escape_string? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Do I need to escape data to protect against SQL injection when using bind_param() on MySQLi?
I have a class that simplifies doing a queries. Here is a code example how to insert data:
$dbi->prepare("INSERT INTO `temp` (`name`,`content`) VALUES (?,?);")->execute($name,$content);
There is a function in class like this:
public function execute(){
if(is_object($this->connection) && is_object($this->stmt)){
if(count($args = func_get_args()) > 0){
$types = array();
$params = array();
foreach($args as $arg){
$types[] = is_int($arg) ? 'i' : (is_float($arg) ? 'd' : 's');
$params[] = $arg;
/*
or maybe $params[] = $this->connection->real_escape_string($arg);
*/
}
array_unshift($params, implode($types));
call_user_func_array(
array($this->stmt, 'bind_param'),
$this->_pass_by_reference($params)
);
}
if($this->stmt->execute()){
$this->affected_rows = $this->stmt->affected_rows;
return $this;
}
else {
throw new Exception;
}
}
else {
throw new Exception;
}
}
When I declare $params[] I have like this $params[] = $arg; Should I put $params[] = $this->connection->real_escape_string($arg); or not?
Thanks.
No. When you use parameters, you don't need to escape the strings.
In fact, you must not escape the strings, because you'll end up storing strings in your database containing literal backslashes. This is not what you want.
According to PHP Manual on mysqli and prepared statements:
Escaping and SQL injection
Bound variables will be escaped automatically by the server. The
server inserts their escaped values at the appropriate places into the
statement template before execution. A hint must be provided to the
server for the type of bound variable, to create an appropriate
conversion. See the mysqli_stmt_bind_param() function for more
information.
The automatic escaping of values within the server is sometimes
considered a security feature to prevent SQL injection. The same
degree of security can be achieved with non-prepared statements, if
input values are escaped correctly.
So no, you don't have to take care about escaping, server will take care about escaping for you.
Escaping manually will result in double escaped values. And in my personal opinion the greatest advantage of placeholders ? in sql statements is that you don't have to take care about escaping.

Categories