I am in the middle of creating a comment box where people can ask their questions.
I get a lot of people asking how do they do something which involves inputting code into the form.
The form goes through htmlpurifier to make sure its safe to use.
But when ever someone inputs echo codes etc it does not allow it.
Or if someone inputs a div then it does not allow that either, even when wrapping in the < code >.
For instance this:
<code><div class="classname"></div></code>
will just add a div.
and
<code><?php echo $word; ?></code>
Will not show the code at all.
The way I have set this up the htmlpurifier is:
$content = $_POST['comment'];
$rawf = str_replace('<code>', '<pre><code>', $content);
$rawfp = str_replace('</code>', '</code></pre>', $rawf);
require_once '../Libs/htmlPurifier/library/HTMLPurifier.auto.php';
$purifierconfig = HTMLPurifier_Config::createDefault();
$purifierconfig->set('HTML.Allowed', 'b,a[href],i,em,br,code,pre');
$purifier = new HTMLPurifier($purifierconfig);
$clean_html = $purifier->purify($rawfp);
$ticketpost = str_replace('<a ', '<a rel="nofollow" ', $clean_html);
Then the $ticketpost is inserted into the database using PDO prepared statements.
Is there something I am not doing, or doing wrong?
If so please could you help.
Thanks
Your problem is, if the input is truly HTML, then any code fragments need to be escaped in order to show up in the result. We have special <![CDATA[ put code here ]]> syntax for just that, but sometimes, you don't want to bother users with extra syntax like that. In that case, you could do a preg_replace_callback on code tags, where the callback escapes the code between two code tags. But notice, now, there is no way to express a code fragment that contains code tags! So it is all tradeoffs.
Related
I have found out that if a user writes in an input php/HTML code the code will excecute in my admin panel. Can this damage my system ? And if yes how can I disable it?
I will appreciate any answers!
You can remove HTML and PHP tags with
<?php
$text = '<p>Test paragraph.</p><!-- Comment --> Other text';
echo strip_tags($text);
echo "\n";
// Allow <p> and <a>
echo strip_tags($text, '<p><a>');
?>
result:
Test paragraph. Other text
<p>Test paragraph.</p> Other text
source: https://www.php.net/manual/pt_BR/function.strip-tags.php
It is a good practice to always filter data that comes from outside the application. So I mean every input that is given to the application. Particular attention must be given by the programmer to the way in which to execute the queries to the database. Since database queries can also be made using parameters that come from the user or more generally from outside the application.
Remove all HTML tags from the input before they are used to run queries or saved to the DATABASE.
https://www.php.net/manual/en/function.strip-tags.php
strip_tags ( string $string , array|string|null $allowed_tags = null )
Pay particular attention to the formatting of queries and input parameters before running database queries to avoid SQLinjection
an interesting article about it : https://www.ptsecurity.com/ww-en/analytics/knowledge-base/how-to-prevent-sql-injection-attacks/
Cyber Security is a very broad topic and I don't think it can be expressed here in just one answer.
Dealing with this topic requires more and more IT requirements such as, for example, knowing Programming
This answer is intended to be a starting point to deepen the subject
Yes, definitely it effect the project, not only html and PHP also SQL queries and JavaScript code also.
For prevention you have to validate the input using JavaScript or jQuery.
Is there any possibility in PHP to save new lines in an textarea into a sql database?
I mean without typing in html commands like br ?
If not, how its done here? And how i can install it into my programm?
Thanks for help!
$descriptionraw = mysqli_real_escape_string($conn, $_POST['setdescription']);
$description = nl2br($descriptionraw);
The premise of this question is flawed, as the newlines are stored in the database already.
At least as long as you haven't done anything to remove them prior to saving the input, that is.
The question should be how to display the newlines in HTML pages, and for this you have a couple of methods.
Either use a <pre> tag around the output. This will cause the text to be showns preformatted, and thus include the newlines as actual content. The bad side about this is that the text won't break normally, and as such can (and will) break out of the natural flow of your page.
Or use nl2br() or a custom nl2p() function, when echoing the content to the browser. This translates the newlines into <br> (or <p>) tags, and will follow the normal flow of your site's layout. Which makes this the recommended method.
PS: This line is wrong:
$description = nl2br($descriptionraw);
This is function to format output to a HTML-compatible viewer, a database is not. Using nl2br() and similar functions before you save stuff to the database will only cause you headaches, especially if you ever want to view the data in something that is not equipped to handle HTML code. (Such as the native MySQL client.)
Quick and dirty examples, using PDO:
First for saving the data:
$input = filter_var ($_POST['input'], FILTER);
$stmt = $db->prepare ("INSERT INTO `table`(`input`) VALUES (:data)");
$stmt->exec (array (':data' => $input));
Then for displaying it:
$output = '';
$res = $db->exec ("SELECT `input` FROM `table`");
foreach ($res->fetchArray () as $row) {
$output .= nl2br ($row['input']);
}
echo $output;
User php function nl2br
echo nl2br("This\r\nis\n\ra\nstring\r");
I have a simple comments section with which I would like to be able to style each comment, saving the text and html tags in the database.
For the most part, I feel confident about the way I am inserting my comment data into my database. Of course, if you feel otherwise, I am not opposed to hearing your opinion.
if(isset($_POST["comment"])) {
$userid = $_SESSION['user_id'];
$comment = $conn->real_escape_string(trim($_POST['comment']));
$sql = "INSERT INTO comments (`user_id`, `comment`, `parent_id`, `type`)
VALUES ('.$userid.', '$comment', '$parent_id', '$type')";
if ($conn->query($sql) === TRUE) {
echo "Thanks for the comment!";
} else {
die("Error commenting" . $conn->error);
}
}
However, if I go directly through MySQL and update a row to a simple javascript alert, it renders and I receive the alert on page load. Accordingly, I have a hole in my reading of the data.
while($row = mysqli_fetch_array($result)) {
$parent_id = $row['parent_id'];
$type = $row['type'];
echo '<h1>'.$row['user_name'].'</h1>';
echo '<p>'.$row['comment'].'</p>';
}
I know that I can make this safer through something like strip_tags($row['comment']). However, if I do this, there cannot be any styling on the comments as <p> tags (and other tags for that matter) will be stripped. Accordingly, my question is this: how can I read the data in a way that prevents glaring XSS holes while allowing simple html styling (much like you see on these comments).
Thanks so much!
first of all you can use a harmless bbcode in your commenting system for that matter, but i think you didn't understand strip_tags() well. strip_tags() has two arguments. first one is your string but second one is allowed tags (tags that can pass through strip_tags()) so it goes like this for example:
<?php
$text = '<p>Test texts.</p><!-- Comment --> and other text';
echo strip_tags($text);
# Allow <p> and <a>
echo strip_tags($text, '<p><a>');
?>
and it outputs this:
<p>Test texts.</p> and other text
you can use strip_tags() documentation here
strip_tags() has a second argument, which is a string of allowable tags.
In this case, all tags would be removed:
$comment = "<script>alert('Hello world');</script>This is <i>a comment</i>.";
$strippedComment = strip_tags($comment);
echo $comment;
This would result in: alert('Hello world');This is a comment.
However, with the second argument you can allow basic formatting tags, like so:
$comment = "<script>alert('Hello world');</script>This is <i>a comment</i>.";
$strippedComment = strip_tags($comment, "<i><u><b>");
echo $comment;
This would now result in: alert('Hello world');This is <i>a comment</i>.
http://php.net/strip_tags
Unfortunately, the other answers are wrong: Using strip_tags is not secure.
The reason?
A user could simply enter code like this to bypass your sanitization:
<p onmouseover="alert('This could be evil XSS')">Test texts.</p> and other text
Passing this through strip_tags allowing <p> tags does not remove the code:
echo strip_tags("<p onmouseover=\"alert('This could be evil XSS')\">Test texts.</p> and other text", "<p>");
as p's attribute is still output:
<p onmouseover="alert('This could be evil XSS')">Test texts.</p> and other text
which will run:
You should implement a Content Security Policy on any pages where you output the user controlled text in addition to making the text safe for HTML output by using a sanitizer such as HTML Purifier. This should be effective in preventing injected script commands from running.
The CSP allows you to effectively stop inline script from being executed by the browser. It is currently supported by modern browsers such as Chrome and Firefox (although IE only currently has partial support).
This is done by a HTTP response header from your page.
e.g.
Content-Security-Policy: script-src 'self' https://apis.google.com
will stop inline JavaScript from being executed if a user managed to inject it into your page (it will be ignored with a warning), but will allow script tags referencing either your own server or https://apis.google.com. This can be customised to your needs as required. The HTML sanitizer is still needed for browsers that do not support CSP so you should still run all user supplied input through that first.
I have url ( with file_get_contents ) and this link have script tags, how can I remove them?
Try the following regex (taken from the jQuery sourcecode).
$data = preg_replace('/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi', '', $data);
And before somebody is going to tell me that Regexes+HTML are an evil combination: You are right, but in this specific case it's perfecly valid since script tags have some specific behaviour such as that the first </script> will close the script tag; no matter if it's inside quotes etc.
However, if you plan to do anything else with the HTML data, use a HTML parser!
Read this: Writing secure PHP
Also, please don't steal content, if that's what you are doing.
What are good options to restrict the type of html tags a user is allowed to enter into a form field? I'd like to be able to do that client side (presumably using JavaScript), server-side in PHP if it's too heavy for the user's browser, and possibly a combo of both if appropriate.
Effectively I'd like users to be able to submit data with the same tag-set as on Stackoverflow, plus maybe the standard MathML tags. The form must accept UTF-8 text, including Asian ideograms, etc.
In the application, the user must be able to submit text-entries with basic html tags, and those entries must be able to be displayed to (potentially different) users with the html rendered correctly in a way that is safe to the users. I'm planning to use htmlspecialchars() and htmlspecialchars_decode() to protect my db server-side.
Many thanks,
JDelage
PS: I searched but couldn't find this question...
If you're looking to filter input agains XSS attacks etc., consider using an existing library like HTML Purifier. I've not used it myself yet but it promises a lot and is in high regard.
HTML Purifier is a standards-compliant
HTML filter library written in
PHP. HTML Purifier will not only remove all malicious
code (better known as XSS) with a thoroughly audited,
secure yet permissive whitelist,
it will also make sure your documents are
standards compliant, something only achievable with a
comprehensive knowledge of W3C's specifications.
I think is way easy to use strip_tags and just specify the tags you are allowing.
You could do something like this, if you are familiar with regular expressions:
<?php
function parse($string)
{
//To stop unwanted HTML tags being used
$string = str_replace("<","<",$string); //Replace all < with the HTML equiv
$string = str_replace(">",">",$string); //Replace all > with the HTML equiv
$find = array(
"%\*\*\*(.+?)\*\*\*%s", //Search for ***any string here***
"%`(.+?)`%s", //Search for `any string here`
);
$replace = array(
"<b>\\1</b>", //Replace with <b>any string here</b>
"<span style=\"background-color: #DDDDDD\">\\1</span>" //Replace with <span style="background-color: #DDDDDD">any string here</span>
);
$string = preg_replace($find,$replace,$string); //Do the find and replace
return $string; //Return the output
}
echo parse("***Hello*** `There` <b>Friend</b>");
?>
Outputs:
Hello There <b>Friend</b>
I had similar problem for some time. There were some $%^&*) who liked to post some comments like <script>alert('Hello');</script> or something like that. I got tired and made a small function, which helped me, to allow, only <br> or <br /> tags for normal view of message.
I did it only in PHP, but I think it might help you.
function eliminateTags($msg) {
$setBrakes = nl2br($msg);
$decodeHTML = htmlspecialchars_decode($setBrakes);
# Check PHP version
if(version_compare(PHP_VERSION, '5.2') == 1) {
$withoutTags = strip_tags($decodeHTML, "<br />");
} else {
$withoutTags = strip_tags($decodeHTML, "<br>");
}
return $withoutTags;
}