Currently, I have a setup so that when a MySQL query is made in PHP, I call this function:
getfromtable("table_name",array("field1","field2",...),"something='value' and something2='".$_GET['INPUT']."' and something3=\"".$_GET['INPUT2']."\" and count=3");
That function then arranges the parameters and calls this function:
$result=mysqli_query("SELECT field1,field2 FROM table_name where something='value' and something2='".$_GET['INPUT']."' and something3=\"".$_GET['INPUT2']."\" and count=3;",MYSQLI_USE_RESULT);
This in turn means this SQL statement:
SELECT field1,field2 FROM table_name where something='value' and something2='<user input 1>' and something3="<user input 2>" and count=3;
where <user input 1> and <user input 2> are two values directly from the query string.
The problem is that this is open to SQL injection. Another problem is its amplified nearly everywhere in my code because there are at least 290 spots in my application where that function is used.
What one would likely suggest to me is to sanitize each input right away and use it so then my function call would be similar to:
getfromtable("table_name",array("field1","field2",...),"something='value' and something2='".mysql_real_escape_string($_GET['INPUT'])."' and something3=\"".mysql_real_escape_string($_GET['INPUT2'])."\" and count=3");
But the problem is I have to look for the function 290 times and look for the variables to fix which is time consuming.
What I want to do instead is in my function, I want to take the condition and check to see if the SQL statement is properly escaped and escape it if it is not.
This is the function I use from a php class, and its one I made months ago:
function getfromtable($tname,$tparams,$condition){
unset($retres);$params="";
foreach ($tparams as $n){$params=$params.$n.",";}
$params=substr($params,0,-1);// strip last comma to prevent SQL error
if ($condition){$condition=" where ".$condition;}
// $condition=???? //need to fix mysql injection attack
$q=mysqli_query($this->conn,"SELECT ".$params." FROM ".$tname.$condition.";",MYSQLI_USE_RESULT);
if (mysqli_error($this->conn)){echo "query error: ".mysqli_error($this->conn)."<br>";}else{$retres=$this->parsemultiple($q);}
return $retres;
}
the this->parsemultiple() only produces the results from the query and is not relevant to the question.
I thought of using str_replace, but I'm not sure how to approach this since I have strings in single quotes and strings in double quotes and just using mysqli_real_escape functionality wouldn't make sense on the entire string or the quotes meant to open and close the string will be treated as literals and mysql errors would result.
Is there some way I can do this programmatically inside my getfromtable function where I can add a line or two just before the mysqli_query call that formats the entire query condition so no mysql injection results from bad user input?
Related
I want to run this:
UPDATE users SET about="$about" ;
but when my $about contains =, the script makes a mistake and do something like this:
$about="<img src=somevalue.jpg />";
The script adds this in the database:
<img src
and nothing more.
try it by using double single quotes.
$about = '<img src=somevalue.jpg />';
$query = "UPDATE users SET about='$about'";
As a sidenote, the query is vulnerable with SQL Injection if the value(s) of the variables came from the outside. Please take a look at the article below to learn how to prevent from it. By using PreparedStatements you can get rid of using single quotes around values.
How to prevent SQL injection in PHP?
This is called 'sql injection'. You have to take care of that anyway, so google it.
You have to escape all input you want to use inside statements, anything can happen otherwise. Best is not to use statements constructed by simply including variable content, but use a better engine. Take a look at PDO and the way it works. You "prepare" a statement and hand over parameters as an array. PDO takes care to cleanly escape as required. Much safer that way.
The issue is with putting quotes around string. I'm not very familiar with how php replaces variables in strings but you can try following for MS SQL server:
Set about ="'$about'"
I have read this:
will help you NOT against injection.
Beause escaping is just a string formatting facility, not injection preventer by any means.
Go figure.
However, escaping have something in common with prepared statements:
Them both doesn't guarantee you from injection if
you are using it only against notorious "user input", not as a strict rule for the building ANY query, despite of data source.
in case you need to insert not data but identifier or a keyword.
On the following Post: Are dynamic mysql queries with sql escaping just as secure as prepared statements?
So my question is that using:
$Var = "UserInput Data Possible SQL Injection";
$mysqli->real_escape_string($Var);
does not provide protection against SQL Injection?
I want to use $mysqli->query(); so I can use fetch_array(MYSQLI_ASSOC); Because to be frank, I have no idea how to fetch the results as an array after using a prepared statement.
So If I have this in my Database Connection:
$STD = new mysqli('localhost', 'root', 'xx', 'xx');
$STD->set_charset('utf8');
if ($STD->connect_error) {
die("Standard Access Has Been Revoked. Please Contact Administration");
}elseif (!$STD){
die ("Other problem With Connecting To Database, Please Contact Administration");
}
as stated in the manual for real_escape_string
http://php.net/manual/en/mysqli.real-escape-string.php
The above lists:
Caution
Security: the default character set
The character set must be set either at the server level, or with the API function mysqli_set_charset() for it to affect mysqli_real_escape_string(). See the concepts section on character sets for more information.
Which links to: http://php.net/manual/en/mysqli.set-charset.php
My overall question can split into three options, the first would be asking for a fetch_array() equlivant for prepared statements, which will provide full SQL injection prevention due to prepared statements sending data as raw.
The first question in this format follows:
I'm using a Query as:
$GetCompletedQuery = $STD->query("SELECT Status FROM UserCompletion WHERE `UserID`=' ". $STD->real_escape_string($_SESSION['UID']) ."'");
$GetCompletedArray = $GetCompletedQuery->fetch_array(MYSQLI_ASSOC);
Which returns:
Array ( [Status] => 1 )
But using prepared statements:
$GetCompletedQuery = $STD->prepare("SELECT Status FROM UserCompletion WHERE `UserID`=?");
$GetCompletedQuery->bind_param('i', $_SESSION['UID']);
$GetCompletedQuery->execute();
$GetCompletedArray = $GetCompletedQuery->fetch_row;
print_r($GetCompletedArray);
Which returns:
Fatal error: Call to a member function fetch_row() on a non-object in /var/www/New/API/Constants.php on line 17
The same appears when I try fetch_array() which I know cannot be used with prepared statements.
So what would be the option for using prepared statements?
Second Question
If I use My Usual Query as:
$GetCompletedQuery = $STD->query("SELECT Status FROM UserCompletion WHERE `UserID`=' ". $STD->real_escape_string($_SESSION['UID']) ."'");
which enabled me to use fetch_array(); is data properly secured from SQL injection?
Third Question:
Should I be escaping/protecting from SQL injection for a $_SESSION['UID']; as this is assigned in the following manor:
$InnerJoinQuery = $STD->query("
SELECT Users.ID, Users.Username, Users.Password, UserInformation.LastName, UserInformation.Firstname, UserInformation.DOB
FROM Users
INNER JOIN UserInformation
ON Users.ID = UserInformation.UserID WHERE Users.Username = '".$_SESSION['real_name']."'");
$InnerJoinArray = $InnerJoinQuery->fetch_array(MYSQLI_ASSOC);
$_SESSION['UID'] = $InnerJoinArray['ID'];
$_SESSION['Password'] = $InnerJoinArray['Password'];
$_SESSION['Firstname'] = $InnerJoinArray['Firstname'];
$_SESSION['LastName'] = $InnerJoinArray['LastName'];
$_SESSION['DOB'] = $InnerJoinArray['DOB'];
This snippet explained:
User Logs in with username & password, the file gets information from the database based on $_SESSION['real_name'];
and adds to the $_SESSION array with the results, adding each into a different key.
The question for this chunk is should I even be escaping/protecting from SQL injection when the $_SESSION['UID']; is assigned through the database based on $_SESSION['real_name'];
Thankyou for your time for reading over this massive chunk.
http://php.net/manual/en/mysqli-stmt.get-result.php
Yes, but it is very bad practice:
it will help you in this case but only in this case and deceive with anything else
manual escaping is just silly, better let driver to do it for you
YES, because there is no such thing like SQL injection but improper formatting ONLY
is that using $mysqli->real_escape_string($Var); does not provide protection against SQL Injection?
I didn't change my mind: sure, it doesn't.
It will do only if you enclose the resulting value in quotes (and set proper encoding using mysqli_set_charset() to be strict).
Look, SQL injection not something essential, existing on it's own, but it's rather mere a consequence. A consequence of improperly formatted query.
When creating a query, you have to properly format every part of it. Not because of whatever "injection" but for the sake of it. When you're going to insert a string into query, you HAVE to put it into quotes, or you will get a syntax error. When you're going to insert a string into query, you HAVE to escape these quotes were used to delimit this string, or you will get a syntax error. And so on. It is proper formatting that should be your concern, not scaring tales about injection. And as long as you have every dynamic query part properly formatted according to it's type - no injection ever could be possible
So, the source of variable or it's value should never be your concern. But only it's place in the query:
strings have to be enclosed in quotes and have these quotes escaped.
numbers have to be cast to it's type.
identifiers have to be enclosed in backticks and have these backticks doubled
When it's going for the static part of the query, hardcoded in the script, we don't use such strict standards - say, we're not enclosing every identifier in backticks.
But when it's going for the dynamical part of the query, applying formatting rules should be strict rule, as we cannot know variable content for sure.
By the way, there is another way to format your strings and numbers - prepared statements. It is not as convenient as it should be, but because it is using placeholders to represent your data in the query, it it recommended to use over silly manual formatting.
I have some special characters stored in a MySQL database. Specifically ®. I want to SELECT all entries with these characters. I am currently using this statement:
mysql_query("SELECT * FROM table WHERE description LIKE '%®%' OR name
LIKE '%®%'");
It returns 0 entries. When i try something with %a% it returns a lot so I know everything is right, it is just some kind of a charset problem or something.
When I echo "®" it returns "å¨".
Also when I do the exact same query in phpmyadmin it works properly. Please help!
Read this its very help full to you
Just simply add those symbols to your text, and execute it as SQL query:
INSERT INTO tbl_name VALUES ("Here's my text: ©®");
When you want to display it one the website don't do anything with these symbols (but remember to escape at least <, >, & (using htmlspecialchars()) cause those has special meaning in XML/SGML (HTML) documents)
PS. Also remember to escape text passed to SQL query using mysql_real_escape_string() to avoid any SQL Injection problems. If your server has magic_quotes_gpc enabled disable it or at least filter your GET/POST/COOKIE data to its raw value. You should always consciously escape values.
EDIT:
According to your comment... I don't remember whether magic_quotes_gpc are enabled by default but you can easily undone magic quotes effect. Just on the very beginning of your PHP code add something like this:
if (get_magic_quotes_gpc()) {
array_walk_recursive($_GET, 'stripslashes');
array_walk_recursive($_POST, 'stripslashes');
array_walk_recursive($_COOKIE, 'stripslashes');
}
Now each GPC value should be always raw - without quotes - so you have to escape it manually before passing any variable into query.
I am trying to SQL a DB2 database (on an iSeries) using PHP and "DB2_exec"- not mysql.
I have these characters in my WHERE clause (variable $EncSSN) which cause the SQL statement to stop: ðIn*Éæng “"Ò×ÑRÈ•`
The SQL is constructed as:
select EENUM, EESSN
from EEMAST
where EESSN = '$EncSSN'
The field in the table EESSN contains encrypted values.
- I get no errors and no log entries. The html renders a blank page.
- I have tried replacing (str_replace) quotes, single quotes, period, etc with escape character '\'
- I can't use mysql_real_escape_string because I am loading the db2_connect resource.
If I change the SQL statement above's where to select a value from a different field, my html is rendered properly.
Can you think of anyway I can accomplish this?
Steven
Prepare the SQL and set the parameter for where clause using the array approach. Never ever attempt to build SQL queries by string functions.
try the addslashes() function http://php.net/manual/en/function.addslashes.php
or heredoc or nowdoc syntax
http://php.net/manual/en/language.types.string.php
you could also put the sql in a stored proc, but you may have the same issues for the parameter value and need to try one of the above.
My php script won't work if i try to insert into database something in Saxon genitive (for example value "mike's" won't be inserted).
PHP code is plain and simple:
"INSERT INTO cache (id,name,LinkID,number,TChecked) VALUES(".$idUser.",'".$LinkName."',".$LinkID.",".$number.",NOW());"
Everything works great until "$LinkaName" get some value with "special character". How to put values like "mike's", "won't" etc. into MySql database?
You need to escape these strings properly. In addition, the technique that you're using right now exposes you to an SQL injection attack.
The PHP docs for mysql_real_escape_string gives a good example of what you should do:
// Query
$query = sprintf("INSERT INTO cache (id,name,LinkID,number,TChecked) VALUES(%d,'%s',%d,%d,'%s');",
mysql_real_escape_string($idUser),
mysql_real_escape_string($LinkName),
mysql_real_escape_string($LinkID),
mysql_real_escape_string($number),
mysql_real_escape_string(NOW()));
You must escape them first, otherwise you generate an invalid query. The single quote matches the single quote at the start of the string.
$LinkName = mysql_real_escape_string($LinkName);
You can also use prepared statements to bind parameters to the query instead of concatenating and sending a string (use the PDO or mysqli libraries instead of the mysql lib).
You need to use mysql_real_escape_string() on those values.
Also make sure if you are not quoting those other variables, to cast them to integer (the only reason why you wouldn't quote them).
If you're using mysqli or PDO and not the standard extension, you can use a prepared statement instead of escaping.