SQL Server Escape String - php

I'm using this question as a reference. My issue is that it's encoding my string to hex, but not decoding it once it's written to the database.
HTML textarea
<textarea class="form-control" rows="5" name="nomInfo[]" id="appNom" placeholder="Additional Information"></textarea>
Getting POST value and inserting into the DB
function mssql_escape($data) {
if(is_numeric($data))
return $data;
$unpacked = unpack('H*hex', $data);
return '0x' . $unpacked['hex'];
}
$nomInfo = $_POST['nomInfo'][0];
$nomInfoDecode = mssql_escape($nomInfo);
$query = "INSERT INTO dbo.emp_recog (nomInfo) VALUES (";
$query .= "'" . $nomInfoDecode . "');";
So for example, if I types in ggfdgdfg/fdg.fdgdf.gdf "fdskfdskfds;fsd ' sdfds' fds/f% into the textarea and submit the form, this is written to the database 0x67676664676466672f6664672e66646764662e676466205c226664736b6664736b6664733b667364205c272073646664735c27206664732f6625

Scrap all the hex stuff, there is no need. Really the only thing to worry about escaping is a quote '. MySQL uses a slash \ as an escape character. MS SQL uses a quote ' to escape a quote ', so you just double-up the quotes:
return str_replace("'", "''", $data );
However, you really should be using PHP Data Objects that supports MS SQL, then there is PDO::quote.

I'm pretty sure the example is not quoting the value to be inserted:
mssql_query('
INSERT INTO sometable (somecolumn)
VALUES (' . mssql_escape($somevalue) . ')
');
which translated to your query using double quotes would be:
$query = "INSERT INTO dbo.emp_recog (nomInfo) VALUES (";
$query .= $nomInfoDecode . ");";
Can you give that a shot?

Related

Apostrophe causing problems with insert

Hi I am using php to insert some data into a MS Access Database, which works fine in most cases, the only time it doesnt work, as far as I can see is where there is an ' in the field, in this case its an address i.e. St John's Road.
This is the query statement I am using:
$sql = "insert into tempaddress (`id`, `StreetAddress`, `Place`, `PostCode`) values ('".$item["Id"]."', '".$item["StreetAddress"]."', '".$item["Place"]."','$SearchTerm')"; CustomQuery($sql);
And this is the error I am getting http://prntscr.com/58jncv
I'm fairly sure it can only be the ' within the string text that is messing it up, how can i change?
Apostrophes breaks SQL strings. So you should add slashes before each apostrophe in your SQL strings manually or use PHP's built in function addslashes().
Example:
$sql = "INSERT INTO myTable (value) VALUES ('Text that shouldn't break')";
$sql = addslashes($sql); // outputs "INSERT INTO myTable (value) VALUES ('Text that shouldn\\'t break')"
Source : php.net/manual/en/function.addslashes.php
Thanks, in the end I went with str_replace("'", "", $string);
You are using ' ' quote with the php variable $SearchTerm and use a backslash before column name.
Change your query statement to this:
$sql = "insert into tempaddress (\`id\`, \`StreetAddress\`, \`Place\`, \`PostCode`) values ('".$item["Id"]."', '".$item["StreetAddress"]."', '".$item["Place"]."',$SearchTerm)"; CustomQuery($sql);

Backing up MySQL DB... Proper way to escape strings?

So I am backing up my DB with the following code:
$rows = $this->_getDb()->fetchAll("SELECT * FROM $table");
foreach ($rows AS $row)
{
foreach ($row AS &$value)
{
if (!is_numeric($value))
{
$value = "'".addcslashes($value, "'\\")."'";
$value = str_replace("\n", '\n', $value);
}
}
if (!$count)
{
$output .= "INSERT INTO `$table` (" .implode(', ', $columns). ") VALUES";
}
$count++;
$output .= "\n(" .implode(', ', $row). "),";
if ($count >= $limit)
{
$count = 0;
$output = preg_replace('#,$#', ";\n\n", $output);
}
}
$output = preg_replace('#,$#', ";\n\n", $output);
This seems to be working great... But I'm comparing my output to what I get from a PHPMyAdmin and I'm noticing some slight differences. With my code, because of how I am using addcslashes, if a string contains a ' it will escape it with \'. However, in the output from PHPMyAdmin, it will instead replace a single ' with two single quotes '' in a row.
Is there really a difference? Please look at the way I am escaping non-numeric fields and tell me if there is a better way.
The method of two single-quotes in a row '' is more standard SQL, so it is more portable.
Even MySQL supports a SQL_MODE called NO_BACKSLASH_ESCAPES that would make your backslash-treated strings invalid if you try to import the backup to a server with that mode enabled.
But I have to add comments to make it clear that your method of backing up your database is full of other problems.
You don't handle NULLs:
if (!is_numeric($value))
This does not handle column names that need to be delimited because they may conflict with SQL reserved words:
$output .= "INSERT INTO `$table` (" .implode(', ', $columns). ") VALUES";
If you have millions of rows in any of your tabes, trying to store the entire content of that table in the form of a series of INSERT statements in a single string will exceed PHP's max memory limit:
$output .= "\n(" .implode(', ', $row). "),";
You only show part of your script, but it may also not properly handle binary strings, character sets, triggers, stored routines, views, table options, etc.
You are really reinventing the wheel.
I've seen past questions where people attempt to do what you're doing, but it's difficult to get right:
PHP Database Dump Script - are there any issues?
Why is my database backup script not working in php?
It will be a much better use of your time to just use shell_exec() from PHP to call mysqldump or mydumper.

Escaping for insert to MySql

I have a php page that uses mysql_real_escape_string() to escape content that contains single quotes. I believe it is using utf-8 (but I am not sure). When I insert some content, I get the following mysql warning (and it adds a ? instead of ' in the content):
Incorrect string value: '\x92t ...
Here is an example of my php:
$link = ConnectToServer($theIntranet, $theUser, $thePW);
$theTagToFind = 'ac';
$theTagToUse = 'trc';
$database = '{databaseName}';
$theQuery = "SELECT * FROM {$database}.templates
WHERE content like '%{" . $theTagToFind . ":%'";
$updates = fopen('001_intranet_change' . strtoupper($theTagToFind) . 'to' . strtoupper($theTagToUse) . '.sql', 'w+');
$rollback = fopen('001_intranet_change' . strtoupper($theTagToUse) . 'backto' . strtoupper($theTagToFind) . '.sql', 'w+');
$theResultHandle = mysql_query($theQuery, $link);
$comment = "--Update All $theTagToFind tags to $theTagToUse tags in $database --";
fwrite($updates, $comment . "\r\n\r\n");
fwrite($rollback, "--Rollback - Convert all $theTagToUse tags back to $theTagToFind tags --\r\n\r\n");
mysql_set_charset('latin1');
while (($data = mysql_fetch_assoc($theResultHandle)) != false)
{
$rb_content = $data['content'];
$data['content'] = preg_replace("/{" . $theTagToFind . ":/", "{" . $theTagToUse . ":", $data['content']);
$theResult[] = $data;
$update_script = "\r\n
Update $database.templates
SET content = '" . mysql_real_escape_string($data['content']) . "'
WHERE _id = " .$data['_id'] . ";";
$rollback_script = "\r\n
UPDATE $database.templates
SET content = '" . mysql_real_escape_string($rb_content) . "'
WHERE _id = " . $data['_id'] . ";";;
fwrite($updates, $update_script);
fwrite($rollback, $rollback_script);
}
fclose ($updates);
fclose($rollback);
print_r($theResult);
and $data['content'] could equal something like:
"Hello,
Please remember to contact the doctor's office at......"
here you go
mysql_set_charset('utf8');
you have to be sure that charset in your table definition also set to utf8
Are you sure your server is configured correctly and magic quotes are turned off? These can have the effect of double escaping values.
You can test this by looking at the $_POST data to see if it's been modified from what you'd expect. If so, see if you can fix the setting in php.ini.
As a note, you should not be using mysql_query in new code. It's dangerous, deprecated, and will be removed in future versions of PHP. Using SQL placeholders is the safest and easiest way to do escaping.
In your short example here it looks like you've forgotten to escape $data['_id'] which means it's a possible SQL injection bug. Even one mistake can have severe consequences, so never, ever put unescaped data into a query string.

Manually escaping in PHP/MySQL

I try to understand manually escaping in PHP. I read this example:
if ($_POST)
{
$query = 'UPDATE
hersteller
SET
zulieferer = \''.mysql_real_escape_string($_POST['zulieferer']).'\',
telefon = \''.mysql_real_escape_string($_POST['telefon']).'\',
city = \''.mysql_real_escape_string($_POST['telefax']).'\'
WHERE
id = '.$_POST['id'];
$update = mysql_query ($query) or die (mysql_error());
}
The statement starts by an apostrophe. Unfortunately I couldn't find a discription.
1st part?
'UPDATE hersteller SET zulieferer = \'
2nd part?
'.mysql_real_escape_string($_POST['zulieferer']).'
3rd part?
', telefon = \'
4th part?
'.mysql_real_escape_string($_POST['telefon']).'
The first part is this:
'UPDATE
hersteller
SET
zulieferer = \''
note the extra '.
The escape character \ is used to escape the first ' so that it's inserted as a character into the string rather than interpreted as the end of the string.
It's similar to this:
$message = 'Let\'s get started';
$query = 'INSERT INTO table SET value = \'' . $value . '\'';
A \ character marks the following character as "plain-text", or text that has no meaning. This way, your output would look like zuliefer = 'thevalue'.
For this example, if you don't like having to escape all the characters, you can start the variable with a double quote.
$query = "UPDATE
hersteller
SET
zulieferer = '" . mysql_real_escape_string($_POST['zulieferer'])."',
telefon = '".mysql_real_escape_string($_POST['telefon'])."',
city = '".mysql_real_escape_string($_POST['telefax'])."'
WHERE
id = '".$_POST['id'] . "'";
$update = mysql_query ($query) or die (mysql_error());
-More reading on single quotes and double quotes in PHP strings
-More reading on escaping
-PHP manual on strings and meanings of symbols inside them
The statement starts by an apostrophe. Unfortunately I couldn't find a discription.
In PHP you can define strings with a pair of ' or a pair of ".
The main difference lays in the fact that "-strings are also evaluated to seek for $ variables.
For both string types you can obviously escape the ' or " character in order to make it appear in the string:
echo "He said \"Welcome\".";
// He said "Welcome".
In your case, for example, assuming the POST variable to be equal to x:
'zulieferer = \''.mysql_real_escape_string($_POST['zulieferer']).'\''
// zulieferer = 'x'
Since that string doesn't use " I'd suggest you to refactor it to be:
$a = mysql_real_escape_string($_POST['zulieferer']);
$b = mysql_real_escape_string($_POST['telefon']);
$c = mysql_real_escape_string($_POST['telefax']);
$d = (int) $_POST['id'];
$query = "UPDATE hersteller
SET zulieferer = '$a', telefon = '$b', city = '$c'
WHERE id = $d";
On a side note: you shouldn't use mysql_* functions. Use prepared statements instead.
The code is a little hard to read for two reasons:
it uses single quotes within the SQL statement and for the php string
it is one long string spanning multiple lines
This might be easier to read:
$query = 'UPDATE '.
' hersteller '.
'SET '.
' zulieferer = "'.mysql_real_escape_string($_POST['zulieferer']).'", '.
' telefon = "'.mysql_real_escape_string($_POST['telefon']).'", '.
' city = "'.mysql_real_escape_string($_POST['telefax']).'" '.
' WHERE '.
' id = '.$_POST['id'];
Edit: Regarding your comment:
$query = "DELETE FROM description WHERE id = '" . $this->getId() . "'";
This serves the same purpose as my rewrite above, only exchanging the use of single and double quotes. It uses double quotes as php string delimiters and single quotes in SQL. Both variants are fine, since both PHP and MySQL allow both kinds of quotes. Your $query variable will actually contain DELETE FROM description WHERE id = '1234'. Please note, however, both versions are not syntactically identical. PHP handles double quotes a bit differently from single quotes. In double quotes, PHP will replace variable names with the contents of that variable, in single quotes it won't.
$query = "DELETE FROM description WHERE id='$id'"; <-- PHP will insert the variable $id
$query = 'DELETE FROM description WHERE id="$id"'; <-- PHP will not touch the string

How to deal with an apostrophe while writing into a MySQL database [duplicate]

This question already has answers here:
How can I prevent SQL injection in PHP?
(27 answers)
Closed 9 years ago.
I am getting this error:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 's','portal','','offering','MSNBC','News','','sports','','MSN','Money','','games'' at line 3
The only problem is that this error shows up when inserting data that contains an apostrophe. I tried changing the data type from VARCHAR to TEXT, but the result is still the same.
I tried to put in addslashes()
How do I fix this?
$query=" INSERT INTO alltags
(id,tag1,tag2,tag3,tag4,tag5,tag6,tag7,tag8,tag9,tag10,tag11,tag12,tag13,tag14,tag15,tag16,tag17,tag18,tag19,tag20,tag21,tag22,tag23,tag24,tag25,tag26,tag27,tag28,tag29,tag30)
VALUES
('',mysql_real_escape_string($uniqkey[0]),mysql_real_escape_string($uniqkey[1]),mysql_real_escape_string($uniqkey[2]),mysql_real_escape_string($uniqkey[3]),mysql_real_escape_string($uniqkey[4]),mysql_real_escape_string($uniqkey[5]),mysql_real_escape_string($uniqkey[6]),mysql_real_escape_string($uniqkey[7]),mysql_real_escape_string($uniqkey[8]),mysql_real_escape_string($uniqkey[9]),mysql_real_escape_string($uniqkey[10]),mysql_real_escape_string($uniqkey[11]),mysql_real_escape_string($uniqkey[12]),mysql_real_escape_string($uniqkey[13]),mysql_real_escape_string($uniqkey[14]),mysql_real_escape_string($uniqkey[15]),mysql_real_escape_string($uniqkey[16]),mysql_real_escape_string($uniqkey[17]),mysql_real_escape_string($uniqkey[18]),mysql_real_escape_string($uniqkey[19]),mysql_real_escape_string($uniqkey[20]),mysql_real_escape_string($uniqkey[21]),mysql_real_escape_string($uniqkey[22]),mysql_real_escape_string($uniqkey[23]),mysql_real_escape_string($uniqkey[24]),mysql_real_escape_string($uniqkey[25]),mysql_real_escape_string($uniqkey[26]),mysql_real_escape_string($uniqkey[27]),mysql_real_escape_string($uniqkey[28]),mysql_real_escape_string($uniqkey[29])) ";
mysql_query($query) or die(mysql_error());
I changed it to mysql_real_escape_string. Is this syntax correct? I am getting errors.
The process of encoding data which contains characters MySQL might interpret is called "escaping". You must escape your strings with mysql_real_escape_string, which is a PHP function, not a MySQL function, meaning you have to run it in PHP before you pass your query to the database. You must escape any data that comes into your program from an external source. Any data that isn't escaped is a potential SQL injection.
You have to escape your data before you build your query. Also, you can build your query programmatically using PHP's looping constructs and range:
// Build tag fields
$tags = 'tag' . implode(', tag', range(1,30));
// Escape each value in the uniqkey array
$values = array_map('mysql_real_escape_string', $uniqkey);
// Implode values with quotes and commas
$values = "'" . implode("', '", $values) . "'";
$query = "INSERT INTO alltags (id, $tags) VALUES ('', $values)";
mysql_query($query) or die(mysql_error());
Using mysql_real_escape_string is a safer approach to handling characters for SQL insertion/updating:
INSERT INTO YOUR_TABLE
VALUES
(mysql_real_escape_string($var1),
mysql_real_escape_string($var2))
Also, I'd change your columns back from TEXT to VARCHAR - searching, besides indexing, works much better.
Update for your update
Being that id is an auto_increment column you can:
leave it out of the list of columns, so you don't have to provide a value in the VALUES clause:
INSERT INTO alltags
(tag1,tag2,tag3,tag4,tag5,tag6,tag7,tag8,tag9,tag10,tag11,tag12,tag13,tag14,tag15,tag16,tag17,tag18,tag19,tag20,tag21,tag22,tag23,tag24,tag25,tag26,tag27,tag28,tag29,tag30)
VALUES
(mysql_real_escape_string($uniqkey[0]),mysql_real_escape_string($uniqkey[1]),mysql_real_escape_string($uniqkey[2]),mysql_real_escape_string($uniqkey[3]),mysql_real_escape_string($uniqkey[4]),mysql_real_escape_string($uniqkey[5]),mysql_real_escape_string($uniqkey[6]),mysql_real_escape_string($uniqkey[7]),mysql_real_escape_string($uniqkey[8]),mysql_real_escape_string($uniqkey[9]),mysql_real_escape_string($uniqkey[10]),mysql_real_escape_string($uniqkey[11]),mysql_real_escape_string($uniqkey[12]),mysql_real_escape_string($uniqkey[13]),mysql_real_escape_string($uniqkey[14]),mysql_real_escape_string($uniqkey[15]),mysql_real_escape_string($uniqkey[16]),mysql_real_escape_string($uniqkey[17]),mysql_real_escape_string($uniqkey[18]),mysql_real_escape_string($uniqkey[19]),mysql_real_escape_string($uniqkey[20]),mysql_real_escape_string($uniqkey[21]),mysql_real_escape_string($uniqkey[22]),mysql_real_escape_string($uniqkey[23]),mysql_real_escape_string($uniqkey[24]),mysql_real_escape_string($uniqkey[25]),mysql_real_escape_string($uniqkey[26]),mysql_real_escape_string($uniqkey[27]),mysql_real_escape_string($uniqkey[28]),mysql_real_escape_string($uniqkey[29])) ";
include id in the list of columns, which requires you use either value in its place in the VALUES clause:
NULL
DEFAULT
Here's an example using NULL as the id placeholder:
INSERT INTO alltags
(id,tag1,tag2,tag3,tag4,tag5,tag6,tag7,tag8,tag9,tag10,tag11,tag12,tag13,tag14,tag15,tag16,tag17,tag18,tag19,tag20,tag21,tag22,tag23,tag24,tag25,tag26,tag27,tag28,tag29,tag30)
VALUES
(NULL,mysql_real_escape_string($uniqkey[0]),mysql_real_escape_string($uniqkey[1]),mysql_real_escape_string($uniqkey[2]),mysql_real_escape_string($uniqkey[3]),mysql_real_escape_string($uniqkey[4]),mysql_real_escape_string($uniqkey[5]),mysql_real_escape_string($uniqkey[6]),mysql_real_escape_string($uniqkey[7]),mysql_real_escape_string($uniqkey[8]),mysql_real_escape_string($uniqkey[9]),mysql_real_escape_string($uniqkey[10]),mysql_real_escape_string($uniqkey[11]),mysql_real_escape_string($uniqkey[12]),mysql_real_escape_string($uniqkey[13]),mysql_real_escape_string($uniqkey[14]),mysql_real_escape_string($uniqkey[15]),mysql_real_escape_string($uniqkey[16]),mysql_real_escape_string($uniqkey[17]),mysql_real_escape_string($uniqkey[18]),mysql_real_escape_string($uniqkey[19]),mysql_real_escape_string($uniqkey[20]),mysql_real_escape_string($uniqkey[21]),mysql_real_escape_string($uniqkey[22]),mysql_real_escape_string($uniqkey[23]),mysql_real_escape_string($uniqkey[24]),mysql_real_escape_string($uniqkey[25]),mysql_real_escape_string($uniqkey[26]),mysql_real_escape_string($uniqkey[27]),mysql_real_escape_string($uniqkey[28]),mysql_real_escape_string($uniqkey[29])) ";
I want to really stress that you should not setup your columns like that.
Slight improvement of meagar's answer:
EDIT: meagar updated his post, so his answer is now better.
$query = 'INSERT INTO alltags (id, ';
// append tag1, tag2, etc.
$query .= 'tag' . implode(', tag', range(1, 30)) . ") VALUES ('', ";
// escape each value in the uniqkey array
$escaped_tags = array_map('mysql_real_escape_string', $uniqkey);
// implode values with quotes and commas, and add closing bracket
$query .= "'" . implode("', '", $escaped_tags) . "')";
// actually query
mysql_query($query) or die(mysql_error());
Please look at meagars answer. This is the correct code.
If you want to use the misguided mysql_query() function, then you have to break up the SQL string as follows:
mysql_query(
"INSERT INTO whateever (col1,col2,col3,col4) VALUES ("
. mysql_real_escape_string($col1)
. ","
. mysql_real_escape_string($col2)
. ","
. mysql_real_escape_string($col3)
. ","
. mysql_real_escape_string($col4)
. ")"
);
Or since you have an array, use the clever method call to escape all at once:
$uniqkey = array_map("mysql_real_escape_string", $uniqkey);
mysql_query("USE THE ESCAPED ARRAY THEN DIRECTLY ('$uniqkey[0]', '$uniqkey[1]', '$uniqkey[2]', '$uniqkey[3]', ...");

Categories