PHP prevent HTML in form text field? - php

I have a text form field that users my enter notes into. I then use a PHP/MySQL database to store these entries. How do I prevent somebody from entering HTML into the text field?

You're probably looking for strip_tags

Dont do anything to the text, just store it as they enter it.
Reason being is that maybe you was to add content that looks like html but actually isn't. for example
I was updating the site erlier and i had to add a few < br > tags to let the content move down a touch.
What you shuold be doing is storing the content as it is within the database making sure that you escape the data for SQL injection purposes, and then upon output to the browser you should escape using htmlentites the content like so:
<div id="notes">
<?php echo htmlentities($row['note']) ?>
</div>
this way the html tags does not take any effect on the actual DOM as there escaped, the desired output within the DOM should look like:
I was updating the site erlier and i had to add a few < br > tags to let the content move down a touch.
and the user would actually see the <br> as plain text
Hope this helps.

if you're planning to also store the data in your database, you need to clean the input using mysql_real_escape_string() to prevent SQL injection (http://en.wikipedia.org/wiki/SQL_injection)

1. Filter input
First filter your input
Input filtering is one of the
cornerstones of any application
security, independently of the
language or environment.
2. Use PDO
Next use PDO prepared statements to make your SQL queries safe.
A prepared statement is a precompiled
SQL statement that can be executed
multiple times by sending just the
data to the server. It has the added
advantage of automatically making the
data used in the placeholders safe
from SQL injection attacks.

Related

Should all output be purified in PHP?

I am creating a rather small web application in PHP, where a (trusted) administrator can, amongst other things, store hundreds of objects in a database. The user can enter a number of details about these objects in the form of text fields (an input element with the type attribute set to "text").
The objects with their details are echoed in the form of a table, escaped by the htmlspecialchars function. This function, however, does not prevent against the malicious use of html tags, for example, the <script> tag.
The question is whether all user entered data (every cell in the table) should be purified by something like HTMLPurifier, which is already used elsewhere in the application. And if so, what would be the best way to do it as using HTMLPurifier thousands of times, as there are many details, may cause some serious performance issues.
The objects with their details are echoed in the form of a table, escaped by the htmlspecialchars function. This function, however, does not prevent against the malicious use of html tags, for example, the <script> tag.
Yes it does. They get harmlessly and correctly output as <script>.
The question is whether all user entered data (every cell in the table) should be purified by something like HTMLPurifier
Nope. You should only use HTMLPurifier on fields where you are deliberately intending to allow the user to enter markup for direct rendering to the page, for example a comment system where the user can type <i> for italics.
For other input that you are treating as plain text, htmlspecialchars remains the right thing to do when outputting to HTML.
Everything should be checked and cleaned before you save it into database. Principle is that you DO NOT TRUST anything which is coming from user.
ALWAYS escape everything.
Or just use tools which will do that for you - like frameworks.

How do I sanitize data from users before sending it to mySQL?

I am making a forum at this moment.
I would like to sanitize my input data (that is, the posts from users) before sending it to the MySQL database.
I already have been searching some functions to do that, but I'm not sure if I have used enough of them and if they're all secure enough. Any suggestions are welcome.
Here is the code I have:
$message=$_POST['answer'];
$message=nl2br($message); //adds breaks to my text
$message=stripslashes($message); //removes backslahes (needed for links and images)
$message=strip_tags($message, '<p><a><b><i><strong><em><code><sub><sup><img>'); //people can only use tags inside 2nd param
$message = mysql_real_escape_string($message); //removes mysql statements i think (not sure)
edit: Please tell me if I should add some tags to the strip_tags function. Maybe I have forgotten some.
Try using PDO instead. It has great binding function, which really improves security. Here's some examples: http://php.net/manual/pl/pdostatement.bindvalue.php
PDO is by default in PHP5, so pretty much everywhere these days.
If you want to allow limited HTML to be used in forum (as seen by the way you are using strip_tags()), use HTMLPurifier; otherwise you are vulnerable to javascript in attributes of those tags.
By the way, right now you are stripping the <br> tags you've added
When you save to DB:
$message=strip_tags($message, '<p><a><b><i><strong><em><code><sub><sup><img>'); //people can only use tags inside 2nd param
$message = mysql_real_escape_string($message); //removes mysql statements i think (not sure)
When you output:
$message=nl2br($message); //adds breaks to my text
$message=stripslashes($message); //removes backslahes (needed for links and images)
Besides, use htmlspecialchars when you write into html input elements like text or textarea
OBS: Don't reinvent the wheel. Learn some PHP framework like codeigniter that provides very secure ways to manage data.
.

Can a user change the input variable of a select box?

I would like to secure user input, if it is text input we can simply use filter_input and mysql_real_escape_string.
My question is: Do I have to use those when variables are coming from a select box? Is it possible for some crafty user to change POST values from the browser?
My select box is populated dynamically from a database. Do I still have to compare recevied data (after submit) with the database, and use mysql_real_escape_string for safety?
Absolutely, you need to confirm all data you get from the client, always.
Yes someone can alter input on any form element. Something as easy as FireBug in firefox will allow me to alter any source code on my client copy of a webpage and submit a form with my altered data.
You cannot trust anything that comes from the user. Assume everything a user sends you is evil. You need to escape everything or even better use prepared statements / parametrized queries.
You need to validate each input if you want a secured site.
You need to check if the select box field matches with your database values for surety.

Protection against user textarea input

Do I need to do anything special to protect myself against user input from a textarea when the input is simply stored in a session cookie?
Im selling products that can be engraved with custom text. The user is "supposed" to enter the text they would like engraved into a textarea, and this text is stored in a session cookie along with the item they chose & some other data.
Right now, I use nl2br before storing it in the session cookie, then stripslashes when I display it back out onto the page.
Do I need to do anything else to protect myself from malicious code (i.e. htmlentities, etc)?
Thanks for your input (no pun intended!)
Validate the input if you only want to allow certain characters such as a-z 0-9. If you don't want characters like < and > then validate.
As a general rule of thumb, store the input as it was entered, and do any processing before it is printed to a page or other medium. By processing, I mean run it through nl2br() and htmlentities().
Usually it's better to store the data in a neutral form i.e not processed for HTML etc because you may want to output the data to some other form in future, like XML, web services, in which case it will need to be processed differently.
Store it in a session variable, not a cookie. A session variable is stored on the server and is not accessible by browsers or anyone else. If you store it in a cookie, it can be tampered with and you will have to re-validate the input every time you want to access it because it might have changed.
If you eventually store the data in a database, you'll need to escape it for SQL Injection. The method of that will vary depending on which library is used to interface with the database, but parameterised queries or prepared statements is preferable.
The first most obvious chance for attack would be direct HTML input. Imagine someone input <script src="http://malicious.com/ddos.js" /> into your textarea. Would your PHP code output that in a way that would make it run the .js code?
Second, how does the data get to the engraver? Most common would be that it's stored in a database for later use, or maybe emailed to a queue of work for the engraver.
If you're putting into a database, you'll want to look into a wrapper like PDO that can handle cleaning input.
If you're emailing it to yourself or someone else then you'll need to take care to avoid putting dangerous information in there. I believe php's mail() function will automaticlly keep the $message from making changes to the headers. http://www.php.net/manual/en/function.mail.php
If you have some other method, let us know and there may be other concerns.
You should run htmlspecialchars() before you display the variable in the textarea box.
This will make sure that possibly evil HTML code is safely displayed inside the textarea instead of being executed.
All other places you show the variable, eg. in an e-mail or an admin interface, you should run htmlspecialchars() on it as well.
Simularily, also remember to escape the variable if saving to a database, so people are not able to mess with your database query.
(An alternative approach to doing htmlspecialchars() upon display, would be running a strip_tags() on the user's input before it is stored in the session variable. But sanitizing input on display as suggested above is a more robust way of thinking, IMHO.)

Best way to store articles in a database? (php and sql)

I want to store articles in a database, but I cannot seem to find much information on the best way to do this, from what I have read it seems split between most people on how to effectively do this. A lot of people will suggest a way and others will point out sql injection issues, and I cannot seem to find much about this topic that is fairly new.
Here is the html of an article:
<div id="main">
<article>
<header>
<h3> Title </h3>
<time pubdate="pubdate"> 2011-07-22 </time>
</header>
<p> Article Text </p>
</article>
</div>
Ideally I guess it would be best to store the chunk of html making up each article into a database but there seems to be a lot of problems with this, and like I said I can't find many posts over this particular topic, and as someone new to php and databases I want to get some input on the best way to go about this before I proceed.
When ever I store a large amount of user text, I just base64 it, then before you display it, make sure to run it through htmlspecialchars, this will keep html from working, so htmlspecialchars(base64_decode($content)) would work fine for displaying.
If you are using bbcode for formatting, then make sure to run htmlspecialchars before you start formatting your bbcode.
This isn't the only way, you can sanitize inputs without base64'ng it, but I see no reason not to, especially when nobody needs to see directly into the database.
Storing it in a SQL db is fine, but you can and you must protect against SQL injection in your code.
ie, cleaning all user input before sending it to the db.
PHP Manual on SQL injection
I think the best method is to just store pure text, but usually that is not the case when you want to use extra formatting. You can convert the html tags to bbcodes or similar tags which can prevent sql injection however if you escape the html content it would be as safe as any other content. so do mysql_real_escape_string on whatever data you put into the database and you would be fine.
However, the best practice would be to store the html code along with the article text as a html file which you can serve when the user requests the data but in the database you can just store purely text for indexing and search purposes. This is ideal as you would not need the html content for searching anyways and it will also prevent sql attacks if the content is purely text that is to be stored in the database. But as the user requests the file get the content of the html file for that article which contains the formatted text and serve that.
use lucene or sphinx, either from Zend_Lucene or through solr. they will make the indexing for the article faster, and you can also do a full text search on them too. using lucene or solar to index and search in these cases is pretty much a standard procedure, and will let you scale to millions of articles.
sphinx is a daemon that runs "in parallel" to the mysql daemon. for using sphinx, you can use the pecl sphinx extension.
if you want to go with lucene, you can try zend_lucene or solr, which is actually a tomcat distro with an webapp that exposes lucene as a web service, so you can access it in a standard way, independantly of the language.
choosing either of them is ok. you can index by full text (content), and categories, or whatever you need to index by.
the safest way to prevent sql injection here is to use prepared statement.
$stmt = $con->prepare("INSERT INTO Articles (Title, Date, Article) VALUES (?, ?, ?)");
$stmt->bind_param("sss", $title, $currentDate, $articleBody);
The question marks represent the values you will pass. "sss" is saying that each of the 3 variables will be a string and then you can call this prepared statement and pass it the correct values.
$title = $_POST[title];
$currentDate = date("Y-m-d H:i:s");
$articleBody = $_POST[article];
$stmt->execute();
this will make sure that no malicious sql can be injected into your database.
hope this helps!
Store your article as TEXT :) Just pass it through this php function first to prevent injection attacks:
// Prevent MySQL Injection Attacks
function cleanQuery($string){
if(get_magic_quotes_gpc()) // prevents duplicate backslashes
$string = stripslashes($string);
return mysql_escape_string($string);
}

Categories