I just started helping on a site where there is an admin section that allows the site owner to input text to display on the site. They have a problem when adding text with apostrophes because it breaks the PHP statement. I have looked at using mysql_real_escape_string command, but not sure the best way to use it. The original code is below. Any suggestions would be great!
<textarea name="descr" cols="76" rows="5" id="descr" tabindex="5" onBlur="this.value=removeMSWordChars(this.value);">
<?php echo $data['descr']; ?>
</textarea>
<script type="text/javascript">
CKEDITOR.replace( 'descr' );
</script>
</td>
Read about Prepared Statements, they allow you to:
Make you code safe against SQL injection attacks
Insert any character easily into the database, without caring about escaping.
You seem to be still using the MySQL-extension (the one with mysql_query): Note that this extension is deprecated and does not support Prepared Statements. You should switch to either PDO or MySQLi, the link at the top explains how to.
Related
I'm new to web security.After spending time reading some blogs and community sites like SO,I have found some techniques to be safe from XSS Attack and SQL Injection.But the problem is,most of that security related questions are very old.So,my question is
does my following code has any major security holes that can be bypassed by amateur or mid-level attacker(hacker).
Is there anything else I can do to be safe from attack?By the way,I'm using HTMLPurifier to be safe from XSS Attack
PHP
require_once '/path/to/HTMLPurifier.auto.php';
$connect_dude=mysqli_connect('localhost','root','','user');
$config = HTMLPurifier_Config::createDefault();
$purifier = new HTMLPurifier($config);
if(isset($_POST["sub"])){
$name=$_POST["namex"];
$email=$_POST["email"];
$ques=$_POST["ques"];
$clean_name = $purifier->purify($name);
$clean_email = $purifier->purify($email);
$clean_ques = $purifier->purify($ques);
$stmt = mysqli_stmt_init($connect_dude);
if(mysqli_stmt_prepare($stmt, 'INSERT INTO question (name,email,question) VALUES(?,?,?)')) {
mysqli_stmt_bind_param($stmt, "sss", $clean_name, $clean_email, $clean_ques);
mysqli_stmt_execute($stmt);
}
}
HTML FORM
<div id="form">
<form id="sub_form" action="ask.php" method="post" enctype="multipart/form-data">
<p id="nam" class="indi">Name</p><input type="text" id="namex" name="namex" placeholder="Your Name" required></br>
<p id="ema" class="indi">Email</p><input type="text" id="email" name="email" placeholder="Email" required></br>
<p id="que" class="indi">Question</p><textarea id="ques" name="ques" placeholder="Question" required></textarea></br>
<input type="submit" id="sub" name="sub" value="Send">
</form>
</div>
The SQL stuff is fine, parameterised queries are the best-practice approach to prevent SQL injection.
The approach to XSS is... a bit weird.
HTMLPurifier is of use where you want to allow the user to input limited HTML markup. That can be reasonable for formattable freetext fields (like I'm guessing ques is) if you can't be bothered to go as far as providing your own custom mini-markup language like Markdown.
But do you really want the user to be able to input markup for all fields, including their name and e-mail address? Should I be able to have the name “Edward Boing Jr”? Are users going to have to enter & every time they want to use an ampersand?
A better approach is usually to accept plain text as it is, and then HTML-escape it at the point you insert it into an HTML page (eg with <?php echo htmlspecialchars($value); ?>) so that the exact string entered by the user appears in the page. The fields where you deliberately allow markup (and so use HTMLPurifier instead of htmlspecialchars) are typically very much exceptional cases.
Note that if you are injecting into other contexts you need different escaping functions: for example if you are injecting into a JavaScript string in a <script> block then you need JS-string escaping and neither htmlspecialchars nor HTMLPurifier will help you with that.
Perhaps testing if each of the post variables are set and not just the sub one. Also, checking them in javascript as well before sending to php to rid the post of any unwanted characters. You can regex and test for empty strings in javascript for example.
The most checks - the better.
You can also use names that are not so common (abrv_page_name_email instead of simply "email").
Lots of stuff.
Regex and mysqli_real_escape_string are also common practice.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What are the best practices for avoiding xss attacks in a PHP site
I have a form that user can fill in their personal information. The user submits the form and A web service will process these information and store the information in mysql database.
But what if users enter html tag, php code, or javascript in the input field. I would like to prevent that. I know in javascript there's a method call escapehtml, in php it's strip_tags.
I just want to know the correct way of disabling the abilities to type html, php, script from input field. Do I use strip_tags for all input I received?If I use strip_tags, how to disable script? Or there is away to do it in mysql?
Thank you
This is the form:
<div>
<label class='info-title whitetext' for="name">Full Name: </label>
<input type="text" name="name" id="name" size='25' maxlength="100" required />
</div>
<div>
<label class='info-title whitetext' for="phone">Phone: </label>
<input type='text' pattern='\d+' name='phone' id='phone' size='25' maxlength='12' />
</div>
<div>
<label class='info-title' for="email">Email: </label>
<input type="email" name="email" id="email" size='35' maxlength="60" required />
</div>
<div>
<label class='info-title' for="address">Address: </label>
<input type="text" name="address" id="address" size='45' maxlength="50" required />
</div>
Try htmlspecialchars($string);
That will encode all the HTML tags to character codes (<div> would become <div>, which will be displayed without being parsed as html) This way, script tags cannot be created as well.
Be sure to clean the content before supplying it to a database though, for example by escaping with mysqli_escape_string() (others will probably advice you to use prepare statements).
It is most likely not best practice to put HTML character encoded strings into the database, as it simply increases the string size unnecessarily. (And it doesn't provide protection against SQL injection on its own)
Personally, I just like to do $out = str_replace("<","<",$in). It provides the least possible disruption for the user, and they are most likely to get out what they typed in.
If the user input may end up in an HTML attribute (for whatever reason), you should also replace " with ".
Never put user-supplied content into a <script> tag, and never save it to a file without first performing the replacements.
You cannot disable "the abilities to type html, php, script from input field", unless you check users' input in real time and specifically block them when you detect that a tag is entered. Yet I don't see a reason why anyone would want that, the proper way is to properly process users' input when submitted.
For html tags or php codes or things like that you can definitely use escapehtml or strip_tags, but if you are later putting the content into mysql, I have to remind you of sql injection attack.
If you are not familiar with the term, users can type in mysql queries that interfere with your sql queries. If we blindly insert user provided content into our "INSERT" statements, those statements might be altered by sql keywords in user's input.
For ways to prevent sql injection attack, you can take a look at wiki's page for a good start: http://en.wikipedia.org/wiki/SQL_injection#Mitigation
Before going live with my website, i made some thoughts about security:
This question is about understanding the Processing in PHP and not strives for a solution in securing the form.
Consider this barebone script which is completely insecure against xss and
sql injections if provided.
<?
if ($_POST['submit']=="1"){
$input = $_POST['input'];
echo "echo the input: ".$input."<br/>";
}
?>
<form action="<? $PHP_SELF;?>" method="POST">
<input type="text" name="input" value="<? echo $_POST['input'];?>"/>
<input type="hidden" name="submit" value="1"/>
<input type="submit" value="submit"/>
</form>
i am wondering why such an injection like this does not work (in the field input):
";unset('index.php');
i am naively thinking the "; would end the echo and than proceed with the code.
Actually i am very happy this does not work but i would like to know why.
In SQL kind of this would actuall work ' OR 1'.
i know to secure this with addslashes or htmlspecialchars but this is not the question. I want to gain an inside of how php works in processing this.
thanks
The content of $_POST array elements are strings. So, whenever you submit ";unset('index.php');" (btw, doesn't unset work on variables?) you actually send that as a string, not as PHP executable code.
Unless you're using eval(), you don't need to fear about php code being evaluated.
Another thing, don't use addslashes() to secure queries, but use your library's dedicated function, such as mysql_real_escape_string() for mysql. Or better use query bindings with prepared statements and parametrized queries.
It would work if you put it through eval(), but otherwise it's just a string like any other.
Here's what I am doing,
<?php
if(isset($_POST['submit'])){
$text_area= mysqli_real_escape_string($dbc, strip_tags(trim($_POST['text_area'])));
echo $text_area;
}
?>
<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>" >
<input type="textarea" name="text_area" style="width:280px;height:90px" id="myTextarea" />
<input type="submit" name="submit" Value="Submit"/>
</form>
But whenever I try to insert something like this: "Hello World" or 'Hello World', it outputs: \"Hello World\" or \'Hello world\'
where am I going wrong?
That's because you using the mysql-real-escape-string function. Use the stripslashes function on your data before displaying it to remove the slashes.
It seems you are outputting the value from the mysqli_real_escape_string method that escapes the string value for a SQL query to avoid SQL Injection. If you simply want to output anything that was inputted into the textarea then you can just purely show the value from the $_POST array but BEWARE if you don't do any checks you can easily fall victim to someone inputting some javascript etc. and have it appear on the page.
So for example to output just the pure text you sent to the server.
trim($_POST['text_area'])
and then you can call mysqli_real_escape_string again while building your query to make the string safe and avoid some common attacks.
You are using mysqli_real_escape_string incorrectly - it serves no purpose here.
Do not use it in this context, and the problem will go away. Use it only when entering data into a database.
I am beginner in web development, I am developing a site that allows user to post various discussions and others comment and reply on it. The problem I am facing is, the user can post almost anything, including code snippets and any other thing which might possible include single quotes, double quotes and even some html content.
When such posts are being posted, it is intervening with the MySQL insert query as the quotes are ending the string and as a result the query is failing. And even when I display the string using php, the string is being interpreted as html by the browser, where as I want it to be interpreted as text. Do I have to parse the input string manually and escape all the special characters? or is there another way?
You need to read up on a few things
SQL Injection - What is SQL Injection and how to prevent it
PHP PDO - Using PHP PDO reduces the risk of injections
htmlentities
The basic premise is this, sanitize all input that is coming in and encode everything that is going out. Don't trust any user input.
If possible, whitelist instead of blacklisting.
EDIT :
I you want to display HTML or other code content in there, users need to mark those areas with the <pre> tag. Or you could use something like a markdown variation for formatting.
Use PDO, prepared statements and bound parameters to insert / update data, eg
$db = new PDO('mysql:host=hostname;dbname=dbname', 'user', 'pass');
$stmt = $db->prepare('INSERT INTO table (col1, col2) VALUES (?, ?)');
$stmt->execute(array('val1', 'val2'));
Edit: Please note, this is a very simplified example
When displaying data, filter it through htmlspecialchars(), eg
<?php echo htmlspecialchars($row['something'], ENT_COMPAT, 'UTF-8') ?>
Update
As noted on your comment to another answer, if you want to maintain indentation and white-space when displaying information in HTML, wrap the content in <pre> tags, eg
<pre><?php echo htmlspecialchars($data, ENT_COMPAT, 'UTF-8') ?></pre>
Look at mysql_real_escape_string and htmlentities functions in PHP manual.
You can also read the Security chapter in PHP manual.
To avoid the breaking of queries in database (which means you're not escaping them, leaving big holes for sql injection) you use mysql_real_escape_string($string) on the value before passing it to the query string, enclosing it in quotes also.
Ex. $value = mysql_real_escape_string($value); // be sure to have an open connection before using this function.
$query = "select * from `table` where value = '".$value."'";
As for displaying in html, you should at least echo htmlentities($string) before outputting it to the browser.
Like echo htmlentities($mystring, ENT_QUOTES)`;
Edit:
To preserve withe spaces, you can use nl2br function (which converts linebrakes to the html equivalen <br />) or go for a little deeper $string = nl2br(str_replace(" ", " ", $string));, but html code would look a bit ugly, at least for me
Reference: htmlentities and mysql_real_escape_string. nl2br
use mysql_real_escape_string. It is a good practice to use this on all user inputs to prevent SQL Injection attacks.