Output new line instead of \r\n - php

I am using this method to store data in database:
$content = $_POST['content'];
$content = mysqli_real_escape_string($mysqli,$content);
$stmt = $mysqli->prepare("INSERT INTO na_posts(postuid,content) VALUES (?, ?)");
$stmt->bind_param("ss",$post_id,$content);
$stmt->execute();
$stmt->close();
And I use this code to get data from the database:
$sql = "SELECT * FROM na_posts WHERE postuid = '" . $id . "'";
$stmt = $mysqli->query($sql);
$row = $stmt->fetch_Object();
echo nl2br($row->content);
but the output is like this:
hey this is line one \r\n this is line two
Why are the new lines show up like this \r\n?
It works if I remove the call to mysqli_real_escape_string() which is important for security as i have read.

mysqli_real_escape_string is not needed if you're using bind parameters, as you are here with bind_param. It's one or the other, you don't need both. Bind parameters are better for various reasons, mainly that it's easier to build the SQL and the database can also be more efficient (since it can be more efficient at executing the same query twice even if the bound values vary).
For outputting the value, in HTML you should use something like htmlspecialchars as mentioned by Alamri. Most decent templating engines will allow you to escape values by default so that you don't have to remember to escape every time. Symfony for example will escape values by default in its templates (other PHP web frameworks are available).

Related

MySQL syntax error?

I'm using a developer to help me build a site - and I'm getting an error relating to a webform when I use the text: I'm
Further details:
“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 'm', team_member_pic = ''' at line 7”
that he can't solve. He's suggesting it's the version of MySQL (5.5.23) on my webhost (Hostgator) - because the code seems to work okay on his server with MYSQL 5.5.xx at (GoDaddy)
The code he's applying is as follows:
$insert = "INSERT INTO ".TABLE_PREFIX."host_manager_team_members SET
user_id = '".$_REQUEST['id']."',
team_member_firstname =
'".addslashes($_REQUEST['team_member_firstname'])."',
team_member_surname =
'".addslashes($_REQUEST['team_member_surname'])."',
team_member_email =
'".addslashes($_REQUEST['team_member_email'])."',
team_member_phone =
'".addslashes($_REQUEST['team_member_phone'])."',
team_member_desc =
'".mysql_real_escape_string($_REQUEST['team_member_desc'])."',
team_member_pic = '".$filepath."'";
mysql_query($insert) or die(mysql_error());
Can anyone give some guidance on what could be causing this error? Would really appreciate any thoughts/ideas you would have.
Use sprintf like this
$insert = sprintf("INSERT INTO ".TABLE_PREFIX."host_manager_team_members SET
user_id = '%s',
team_member_firstname =
'%s',
team_member_surname =
'%s',
team_member_email =
'%s',
team_member_phone =
'%s',
team_member_desc =
'%s',
team_member_pic = '%s'",$_REQUEST['id'],addslashes($_REQUEST['team_member_firstname']),addslashes($_REQUEST['team_member_surname']),addslashes($_REQUEST['team_member_email']),addslashes($_REQUEST['team_member_phone']),mysql_real_escape_string($_REQUEST['team_member_desc']),$filepath);
mysql_query($insert) or die(mysql_error());
Your code is just about as vulnerable as it can be:
Don’t use $_REQUEST, as you don’t know where the data is coming from. It is a combination of $_GET, $_POST and $_COOKIE, and it makes it very easy for a user to inject their own additional data by simply appending ?evilstuff=hahaha to the URL.
Don’t use mysql_ functions. They are deprecated and removed in PHP7. That’s good because MySQL4, for which the original functions were created, did not have the more secure features implemented later.
Don’t use addslashes. It a poor attempt to escape strings against the possibility of SQL injection. If you must do it the old way, use one of the real_escape_string functions. Better still:
Always use prepared statements when accommodating user data. Preparing the statement results in interpreting the SQL before data has been injected, so any additional data, even if it looks like SQL, will be treated as pure data only.
Finally,
It is much easier to use PDO, which has been available since PHP 5.
Here is an alternative using PDO & prepared statements:
$table=TABLE_PREFIX.'host_manager_team_members';
$insert = "INSERT INTO $table SET user_id = ?, team_member_firstname = ?,
team_member_surname = ?, team_member_email = ?, team_member_phone = ?,
team_member_desc = ?, team_member_pic = ?";
$prepared=$pdo->prepare($insert);
$prepared->execute(array(
$_REQUEST['id'],
$_REQUEST['team_member_firstname'],
$_REQUEST['team_member_surname'],
$_REQUEST['team_member_email'],
$_REQUEST['team_member_phone']
$_REQUEST['team_member_desc'],
$filepath
));
The SQL statement is much easier to debug when you can see it by itself.
Note that you do not put quotes around the string values in a prepared statement. This is because quotes are only required for strings when they are constructed in code. By the time the prepared statement gets the data, the string has already been constructed.
I have also used a double quoted string to allow the interpolation of a variable which is not user-generated.
I see that you’re using a quirky MySQL extension to the INSERT statement, which is by no means universally supported. Perhaps you should try the more standard syntax:
$insert = "INSERT INTO $table user_id (team_member_firstname,
team_member_surname, team_member_email, team_member_phone,
team_member_desc, team_member_pic)
VALUES(?,?,?,?,?,?)";
Finally, to answer your question, it is quite possible that the error is caused by the data itself. What you need to do is print the contents of your string generated string, and then run that though MySQL directly (possibly using the SQL tab in PHPMySQL).
So, even without doing any of the above, you should try:
print $insert;
exit;
Perhaps you could try this and post the results here.

writing data into mysql with mysqli_real_escape_string() but without &

iam using this code below, but the character "&" will not be inserted into the db, also when i copy/paste some text from other pages and put it into the db the text ends for example in the middle of the text, dont know why, i tried also addslashes() and htmlspecialchars() or htmlentities().
i read mysqli_real_escape_string() is againt SQL injection attacks and htmlspecialchars() against XSS attachs, should i also combine them ?
$beschreibung = mysqli_real_escape_string($db, $_POST['beschreibung']);
SQL Injection is merely just improperly formatted queries. What you're doing is not enough, stop now. Get into the practice of using prepared statements..
$Connection = new mysqli("server","user","password","db");
$Query = $Connection->prepare("SELECT Email FROM test_tbl WHERE username=?");
$Query->bind_param('s',$_POST['ObjectContainingUsernameFromPost']);
$Query->execute();
$Query->bind_result($Email);
$Query->fetch();
$Query->close();
Above is a very basic example of using prepared statements. It will quickly and easily format your query.
My best guess to what is happening, I'm assuming you're just using the standard:
$Query = mysqli_query("SELECT * FROM test_tbl WHERE Username=".$_POST['User']);
As this query is not properly formatted you may have the quotes in your chunk of text which close the query string. PHP will then interpret everything as a command to send to the SQL server
If you know what you are doing, you can escape indata yourself and add the escaped data to the query as long as you surround the data with single quotes in the sql. An example:
$db = mysqli_connect("localhost","my_user","my_password","my_db");
$beschreibung = mysqli_real_escape_string($db, $_POST['beschreibung']);
$results = mysqli_query(
$db,
sprintf("INSERT INTO foo (beschreibung) VALUES ('%s')", $beschreibung)
);
To get predictable results, I advise you to use the very same character encoding, e,g, UTF-8, consistently through your application.

Column count doesn't match value count at row 1 (columns and values are equal)

I'm getting the error: Column count doesn't match value count at row 1
I think, normally this error occurs if the count of the columns and the values aren't equal, but in my code they are...(3).
This is my php code:
$tempsongtitel = $_POST['songtitle'];
$tempinterpret = $_POST['interpret'];
$templink = $_POST['link'];
$query = mysql_query("insert into tMusic (Songtitel, Interpret, Link) values ('$tempsongtitel, $tempinterpret, $templink')") or die(mysql_error());
You missed some quotes. Should be:
$query = mysql_query("insert into tMusic (Songtitel, Interpret, Link) values ('$tempsongtitel', '$tempinterpret', '$templink')") or die(mysql_error());
Otherwise, you were trying to insert all three POST values into the first field.
Moreover, the mysql_ extension has been deprecated and is on the way out and is highly discouraged, especially if you are creating new software.
AND I'll presume you are first sanitizing your data? You're not really taking user input and placing it directly into the database, are you? Even if you don't do any data validation, you should escape your data in the query... easiest and most foolproof way to do that is by using parameterized queries.
The root cause is that your values are all in one set of quotes instead of quoted individually. I think this is a pretty common error, and in my experience it is an easy mistake to make, but not immediately obvious when scanning over your code. You can fix it like this (quick fix, still using deprecated mysql, but with post values escaped):
$tempsongtitel = mysql_escape_string($_POST['songtitle']);
$tempinterpret = mysql_escape_string($_POST['interpret']);
$templink = mysql_escape_string($_POST['link']);
$query = mysql_query("insert into tMusic (Songtitel, Interpret, Link)
values ('$tempsongtitel', '$tempinterpret', '$templink')") or die(mysql_error());
If you can, it would be much better to update your code to use PDO. You could use a prepared statement like this:
$stmt = $pdo->prepare("INSERT INTO tMusic (Songtitel, Interpret, Link) VALUES (?, ?, ?)");
$stmt->bindValue(1, $tempsongtitel);
$stmt->bindValue(2, $tempinterpret);
$stmt->bindValue(3, $templink);
$stmt->execute();
Among the many benefits of using this database extension rather than the old mysql functions it should not be possible to make an error like this in your code. In the prepared statement, there are no quotes around the parameter markers, so if you have VALUES ('?, ?, ?'), or even VALUES ('?', '?', '?') You would get bind errors when trying to bind the values, and the problem would become apparent pretty quickly.
I've found that, even though it's not 100% necessary and it's more time consuming, properly quoting and backticking EVERYTHING helps prevent this from happening.
$myQuery = "INSERT INTO `tMusic` (
`Songtitel`,
`Interpret`,
`Link`
) VALUES (
'$tempsongtitel',
'$tempinterpret',
'$templink'
);";
$runQuery = mysqi_query($DBi, $myQuery) or die(mysqli_error($DBi));
The formatting you use is up to you but this helps me make sure I have a one to one relationship and that I've quoted everything.
Of course that's using mysqli_* in place of the deprecated mysql_* functions AND that's assuming you've set $tempsongtitel, $tempinterpret and $templink properly.

Insert mysql error when parsing a webpage

Hi when ever I want to insert a comment into my database, I sanitize the data by using Mysql Escape String function this however inserts the following verbatim in field. I print the comment and it works fine and show me the text however when ever I sanitize it, it literally inserts the following into my db
mysql_real_escape_string(Comment)
This is my insert statement, The Id inserts correctly however the comment doesn't it just inserts the "mysql_real_escape_string(Comment)" into the field. what can be wrong?
foreach($html->find("div[class=comment]") as $content){
$comment = $content->plaintext;
$username = mysql_real_escape_string($comment);
$querytwo = "insert into Tchild(Tid,Tcomment)values('$id','$username')";
$resulttwo = $db -> Execute($querytwo);
}
If I'm reading the documentation correctly, you should make the call like this:
$db->Execute("insert into Tchild(Tid,Tcomment)values(?, ?)", array($id, $username));
That will account for proper escaping. Having unescaped values in your query string is dangerous and should be avoided whenever possible. As your database layer has support for SQL placeholders like ? you should make full use of those any time you're placing data in your query.
A call to mysql_real_escape_string will not work unless you're using mysql_query. It needs a connection to a MySQL database to function properly.
Since you're using ADODB, what you want is probably $db->qstr(). For example:
$username = $db->qstr($comment, get_magic_quotes_gpc());
See this page for more information: http://phplens.com/lens/adodb/docs-adodb.htm

Replacing mysql_* functions with PDO and prepared statements

I've always done the simple connection of mysql_connect, mysql_pconnect:
$db = mysql_pconnect('*host*', '*user*', '*pass*');
if (!$db) {
echo("<strong>Error:</strong> Could not connect to the database!");
exit;
}
mysql_select_db('*database*');
While using this I've always used the simple method to escape any data before making a query, whether that be INSERT, SELECT, UPDATE or DELETE by using mysql_real_escape_string
$name = $_POST['name'];
$name = mysql_real_escape_string($name);
$sql = mysql_query("SELECT * FROM `users` WHERE (`name` = '$name')") or die(mysql_error());
Now I understand this is safe, to an extent!
It escapes dangerous characters; however, it is still vulnerable to other attacks which can contain safe characters but may be harmful to either displaying data or in some cases, modifying or deleting data maliciously.
So, I searched a little bit and found out about PDO, MySQLi and prepared statements. Yes, I may be late to the game but I've read many, many tutorials (tizag, W3C, blogs, Google searches) out there and not a single one has mentioned these. It seems very strange as to why, as just escaping user input really isn't secure and not good practice to say the least. Yes, I'm aware you could use Regex to tackle it, but still, I'm pretty sure that's not enough?
It is to my understanding that using PDO/prepared statements is a much safer way to store and retrieve data from a database when the variables are given by user input. The only trouble is, the switch over (especially after being very stuck in my ways/habits of previous coding) is a little difficult.
Right now I understand that to connect to my database using PDO I would use
$hostname = '*host*';
$username = '*user*';
$password = '*pass*';
$database = '*database*'
$dbh = new PDO("mysql:host=$hostname;dbname=$database", $username, $password);
if ($dbh) {
echo 'Connected to database';
} else {
echo 'Could not connect to database';
}
Now, function names are different so no longer will my mysql_query, mysql_fetch_array, mysql_num_rows etc work. So I'm having to read/remember a load of new ones, but this is where I'm getting confused.
If I wanted to insert data from say a sign up/registration form, how would I go about doing this, but mainly how would I go about it securely? I assume this is where prepared statements come in, but by using them does this eliminate the need to use something like mysql_real_escape_string? I know that mysql_real_escape_string requires you to be connected to a database via mysql_connect/mysql_pconnect so now we aren't using either won't this function just produce an error?
I've seen different ways to approach the PDO method too, for example, I've seen :variable and ? as what I think are known as place holders (sorry if that is wrong).
But I think this is roughly the idea of what should be done to fetch a user from a database
$user_id = $_GET['id']; // For example from a URL query string
$stmt = $dbh->prepare("SELECT * FROM `users` WHERE `id` = :user_id");
$stmt->bindParam(':user_id', $user_id, PDO::PARAM_INT);
But then I'm stuck on a couple things, if the variable wasn't a number and was a string of text, you have to given a length after PDO:PARAM_STR if I'm not mistaken. But how can you give a set length if you're not sure on the value given from user in-putted data, it can vary each time? Either way, as far as I know to display the data you then do
$stmt->execute();
$result = $stmt->fetchAll();
// Either
foreach($result as $row) {
echo $row['user_id'].'<br />';
echo $row['user_name'].'<br />';
echo $row['user_email'];
}
// Or
foreach($result as $row) {
$user_id = $row['user_id'];
$user_name = $row['user_name'];
$user_email = $row['user_email'];
}
echo("".$user_id."<br />".$user_name."<br />".$user_email."");
Now, is this all safe?
If I am right, would inserting data be the same for example:
$username = $_POST['username'];
$email = $_POST['email'];
$stmt = $dbh->prepare("INSERT INTO `users` (username, email)
VALUES (:username, :email)");
$stmt->bindParam(':username, $username, PDO::PARAM_STR, ?_LENGTH_?);
$stmt->bindParam(':email, $email, PDO::PARAM_STR, ?_LENGTH_?);
$stmt->execute();
Would that work, and is that safe too? If it is right what value would I put in for the ?_LENGTH_?? Have I got this all completely wrong?
UPDATE
The replies I've had so far have been extremely helpful, can't thank you guys enough! Everyone has got a +1 for opening my eyes up to something a little different. It's difficult to choose the top answer, but I think Col. Shrapnel deserves it as everything is pretty much covered, even going into other arrays with custom libraries which I wasn't aware of!
But thanks to all of you:)
Thanks for the interesting question. Here you go:
It escapes dangerous characters,
Your concept is utterly wrong.
In fact "dangerous characters" is a myth, there are none.
And mysql_real_escape_string escaping but merely a string delimiters. From this definition you can conclude it's limitations - it works only for strings.
however, it is still vulnerable to other attacks which can contain safe characters but may be harmful to either displaying data or in some cases, modifying or deleting data maliciously.
You're mixing here everything.
Speaking of database,
for the strings it is NOT vulnerable. As long as your strings being quoted and escaped, they cannot "modify or delete data maliciously".*
for the other data typedata - yes, it's useless. But not because it is somewhat "unsafe" but just because of improper use.
As for the displaying data, I suppose it is offtopic in the PDO related question, as PDO has nothing to do with displaying data either.
escaping user input
^^^ Another delusion to be noted!
a user input has absolutely nothing to do with escaping. As you can learn from the former definition, you have to escape strings, not whatever "user input". So, again:
you have escape strings, no matter of their source
it is useless to escape other types of data, no matter of the source.
Got the point?
Now, I hope you understand the limitations of escaping as well as the "dangerous characters" misconception.
It is to my understanding that using PDO/prepared statements is a much safer
Not really.
In fact, there are four different query parts which we can add to it dynamically:
a string
a number
an identifier
a syntax keyword.
so, you can see that escaping covers only one issue. (but of course, if you treat numbers as strings (putting them in quotes), when applicable, you can make them safe as well)
while prepared statements cover - ugh - whole 2 isues! A big deal ;-)
For the other 2 issues see my earlier answer, In PHP when submitting strings to the database should I take care of illegal characters using htmlspecialchars() or use a regular expression?
Now, function names are different so no longer will my mysql_query, mysql_fetch_array, mysql_num_rows etc work.
That is another, grave delusion of PHP users, a natural disaster, a catastrophe:
Even when utilizing old mysql driver, one should never use bare API functions in their code! One have to put them in some library function for the everyday usage! (Not as a some magic rite but just to make the code shorter, less repetitive, error-proof, more consistent and readable).
The same goes for the PDO as well!
Now on with your question again.
but by using them does this eliminate the need to use something like mysql_real_escape_string?
YES.
But I think this is roughly the idea of what should be done to fetch a user from a database
Not to fetch, but to add a whatever data to the query!
you have to given a length after PDO:PARAM_STR if I'm not mistaken
You can, but you don't have to.
Now, is this all safe?
In terms of database safety there are just no weak spots in this code. Nothing to secure here.
for the displaying security - just search this site for the XSS keyword.
Hope I shed some light on the matter.
BTW, for the long inserts you can make some use of the function I wrote someday, Insert/update helper function using PDO
However, I am not using prepared statements at the moment, as I prefer my home-brewed placeholders over them, utilizing a library I mentioned above. So, to counter the code posted by the riha below, it would be as short as these 2 lines:
$sql = 'SELECT * FROM `users` WHERE `name`=?s AND `type`=?s AND `active`=?i';
$data = $db->getRow($sql,$_GET['name'],'admin',1);
But of course you can have the same code using prepared statements as well.
* (yes I am aware of the Schiflett's scaring tales)
I never bother with bindParam() or param types or lengths.
I just pass an array of parameter values to execute(), like this:
$stmt = $dbh->prepare("SELECT * FROM `users` WHERE `id` = :user_id");
$stmt->execute( array(':user_id' => $user_id) );
$stmt = $dbh->prepare("INSERT INTO `users` (username, email)
VALUES (:username, :email)");
$stmt->execute( array(':username'=>$username, ':email'=>$email) );
This is just as effective, and easier to code.
You may also be interested in my presentation SQL Injection Myths and Fallacies, or my book SQL Antipatterns Volume 1: Avoiding the Pitfalls of Database Programming.
Yes, :something is a named placeholder in PDO, ? is an anonymous placeholder. They allow you to either bind values one by one or all at once.
So, basically that makes four options to provide your query with values.
One by one with bindValue()
This binds a concrete value to your placeholder as soon as you call it. You may even bind hard coded strings like bindValue(':something', 'foo') if desired.
Providing a parameter type is optional (but suggested). However, since the default is PDO::PARAM_STR, you only need to specify it when it is not a string. Also, PDO will take care of the length here - there is no length parameter.
$sql = '
SELECT *
FROM `users`
WHERE
`name` LIKE :name
AND `type` = :type
AND `active` = :active
';
$stm = $db->prepare($sql);
$stm->bindValue(':name', $_GET['name']); // PDO::PARAM_STR is the default and can be omitted.
$stm->bindValue(':type', 'admin'); // This is not possible with bindParam().
$stm->bindValue(':active', 1, PDO::PARAM_INT);
$stm->execute();
...
I usually prefer this approach. I find it the cleanest and most flexible.
One by one with bindParam()
A variable is bound to your placeholder that will be read when the query is executed, NOT when bindParam() is called. That may or may not be what you want. It comes in handy when you want to repeatedly execute your query with different values.
$sql = 'SELECT * FROM `users` WHERE `id` = :id';
$stm = $db->prepare($sql);
$id = 0;
$stm->bindParam(':id', $id, PDO::PARAM_INT);
$userids = array(2, 7, 8, 9, 10);
foreach ($userids as $userid) {
$id = $userid;
$stm->execute();
...
}
You only prepare and bind once which safes CPU cycles. :)
All at once with named placeholders
You just drop in an array to execute(). Each key is a named placeholder in your query (see Bill Karwins answer). The order of the array is not important.
On a side note: With this approach you cannot provide PDO with data type hints (PDO::PARAM_INT etc.). AFAIK, PDO tries to guess.
All at once with anonymous placeholders
You also drop in an array to execute(), but it is numerically indexed (has no string keys). The values will replace your anonymous placeholders one by one in the order they appear in your query/array - first array value replaces first placeholder and so forth. See erm410's answer.
As with the array and named placeholders, you cannot provide data type hints.
What they have in common
All of those require you to bind/provide as much values as you have
placeholders. If you bind too many/few, PDO will eat your children.
You don't have to take care about escaping, PDO handles that. Prepared PDO statements are SQL injection safe by design. However, that's not true for exec() and query() - you should generally only use those two for hardcoded queries.
Also be aware that PDO throws exceptions. Those could reveal potentially sensitive information to the user. You should at least put your initial PDO setup in a try/catch block!
If you don't want it to throw Exceptions later on, you can set the error mode to warning.
try {
$db = new PDO(...);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING)
} catch (PDOException $e) {
echo 'Oops, something went wrong with the database connection.';
}
To answer the length question, specifying it is optional unless the param you are binding is an OUT parameter from a stored procedure, so in most cases you can safely omit it.
As far as safety goes, escaping is done behind the scenes when you bind the parameters. This is possible because you had to create a database connection when you created the object. You are also protected from SQL injection attacks since by preparing the statement, you are telling your database the format of the statement before user input can get anywhere near to it. An example:
$id = '1; MALICIOUS second STATEMENT';
mysql_query("SELECT * FROM `users` WHERE `id` = $id"); /* selects user with id 1
and the executes the
malicious second statement */
$stmt = $pdo->prepare("SELECT * FROM `users` WHERE `id` = ?") /* Tells DB to expect a
single statement with
a single parameter */
$stmt->execute(array($id)); /* selects user with id '1; MALICIOUS second
STATEMENT' i.e. returns empty set. */
Thus, in terms of safety, your examples above seem fine.
Finally, I agree that binding parameters individually is tedious and is just as effectively done with an array passed to PDOStatement->execute() (see http://www.php.net/manual/en/pdostatement.execute.php).

Categories