So im trying to work out the best way to sanitize xss for safe output to the user.
More or less, when storing values from a form, im using strip_tags(); then bind_params();
And when Im about to output the data to the user Im also using htmlentities();
The data will only be shown inside <p> and <a> tags.
eg:
<p> Some data from user </p>
<a href=""> Some data from user </p>
Should this work?
Index.php
<form action="sante.php" method="post">
Name: <input type="text" name="fname">
Age: <input type="text" name="age">
<input type="submit">
</form>
And then sante.php
<?php
$name = $_POST["fname"];
$age = $_POST["age"];
$namn = strip_tags($name); // then storing into mysql with bind_param
$older = strip_tags($age); // then storing into mysql with bind_param
// before output, htmlentities
function safe( $value ) {
htmlentities( $value, ENT_QUOTES, 'utf-8' );
return $value;
}
// Now showing values
echo safe($namn). "<br>";
echo "<p>" .safe($older) . "</p>";
?>
Yes, you can use this code safely. I see you're already using bind_param (and I assume either the mysqli or PDO library), which prevents SQL injection (damage to you), and htmlentities, which prevents cross-site scripting (damage to the user).
You don't even need to call strip_tags before writing to the database, although it's a fine idea if you don't want user input to contain any JS/PHP/HTML tags at all (and also if you forget to call your safe function on output).
When you insert data to database you must use mysql_real_escape_string or use PDO,
if you display data you must use htmlspecialchars
Related
I've got a search function written in PHP/MySQL which works fine. What I want to happen is that when a user produces a search they can click a button which will submit the $id from the output to a table in my database.
I've copied my code below, the error is within the php echo in the form, it just displays the plain text of the php code.
Everything else works fine, I've tested this by setting value to "" and entering the id myself and then it works. I want it though to be a hidden input in future where the id automatically comes through from the search result. Multiple searches can be returned on the same page and this form is underneath each individual search result.
<?php
$conn = mysqli_connect("localhost","root","","users");
$output = '';
if(isset($_POST['search'])) {
$search = $_POST['search'];
$search = preg_replace("#[^0-9a-z]i#","", $search);
$query = mysqli_query($conn, "SELECT * FROM users WHERE main LIKE '%".$search."%'") or die ("Could not search");
$count = mysqli_num_rows($query);
if($count == 0){
$output = "There was no search results!";
}else{
while ($row = mysqli_fetch_array($query)) {
$id = $row ['id'];
$main = $row ['main'];
$postcode = $row ['postcode'];
$available = $row ['available'];
$email = $row ['email'];
$output .='<div><br><b>Player ID: </b>'.$id.'<br><b>Main:
</b>'.$main.'<br><b>Postcode: </b>'.$postcode.'<br><b>Available:
</b>'.$available.'<br>
<br>
<form action="request_player.php" action="post">
<input type="text" name="id" value="<?php echo $id ?>">
<input type="submit" value="Request Player">
</form>
</div>';
}
}
}
echo $output;
?>
<br> Back to your account
The issue Jay Blanchard highlighted and which you took a bit lightly - perhaps b/c you fear the distraction from your current problem - is actually pretty related to the issue you highlight in your question.
This btw. is nothing uncommon. In this little script you deal with at three languages: HTML, SQL and PHP. And all these are intermixed. It can happen that things jumble.
There are methods to prevent these little mistakes. What Jay highlighted was about how to encode a SQL query correctly.
The other problem is to encode a HTML string correctly. Let me highlight the part:
$output = '... <input type="text" name="id" value="<?php echo $id ?>"> ...';
In this PHP string you write "<?php echo $id ?>" verbatim, that means, this will echo'ed out then.
What you most likely meant was to write it this way:
$output = '... <input type="text" name="id" value="' . $id . '"> ...';
So this seems easy to fix. However, it's important that whether it is SQL or HTML, you need to properly encode the values if you want to use them as SQL or HTML. In the HTML case, you must ensure that the ID is properly encoded as a HTML attribute value. In PHP there is a handy function for that:
$output = '... <input type="text" name="id" value="' . htmlspecialchars($id) . '"> ...';
Or as the ID is numeric:
$output = '... <input type="text" name="id" value="' . intval($id) . '"> ...';
works similarly well.
You need to treat all user-data, that is all input - which includes what you get back from the database (!) - needs to be treated when you pass it into a different language, be it HTML, SQL or Javascript.
For the SQL Jay has linked you a good resource, for the HTML I don't have a good one at hand but it requires your own thoughtfulness and the will to learn about what you do (write) there. So sharpen your senses and imagine for each operation what happens there and how this all belongs together.
One way to keep things more apart and therefore help to concentrate on the job is to first collect all the data you want to output and then process these variables in a template for the output. That would prevent you to create large strings only to echo them later. PHP echoes automatically and a benefit of PHP is that you can use it easily for templating.
Another way is to first process the form input - again into your own variable structure - which is the programs input part and run first. Then follows the processing of the input data, in your case running and processing the database query. And after that you care about the presentation. That way you have common steps you can become more fluent in.
I hope this is understandable. It's full of further obstacles, but it pays to divide and conquer these programming problems. It will also help you to write more while you need to write less for that.
And btw., you don't need to switch to PDO, you can stick with Mysqli.
The reason it is happening is because you have put <?php echo $id ?> inside a string. You want to do the same thing you did elsewhere in your example: value="' . $id . '" It can quickly get confusing when you have single and double quotes happening together. You might be best off learning how to use PHPs multiline strings.
Also, <?= $id ?> is a useful shorthand for <?php echo $id ?> (although you don't want to use either here)
I have a simple code to add banners from admin panel to the index of the site. But the add function doesnt work correctly here is the form to add banner
<h2>Add Banner</h2>
<?php include ("../engine/config/config.php"); ?>
<form method="post" action="">
Clicks
<input type="text" name="click" value="0" style="width: 200px;" /> <div class="hr"></div>
Impressions
<input type="text" name="imp" value="0" style="width: 200px;" /> <div class="hr"></div>
LINK
<input type="text" name="url" value="http://" style="width: 200px;" /> <div class="hr"></div>
Size
<select name="razmer">
<option value='468x60'>468x60</option>
<option value='88x31'>88x31</option>
</select>
<div class="hr"></div>
Banner<br />
<input type="text" name="picurl" value="http://" style="width: 200px;" /><div class="hr"></div>
<input type="submit" name="submit" value="Submit"> <br />
</form>
<?
if($_POST['submit']) {
$click = $_POST['click'];
$imp = $_POST['imp'];
$url = $_POST['url'];
$razmer = $_POST['razmer'];
$picurl = $_POST['picurl'];
$sql = "INSERT INTO `banneradd` (click, imp, url, razmer, picurl, username) VALUES ('$click', '$imp', '$url', '$razmer', '$picurl', '')";
$result = mysql_query($sql);
echo "<div class='hr'>The Banner has been added, please go back to the index: <a href='view_reklama.php'> Index </a></div>";
}
?>
So it say it was added but when I go back ITS NOT. There is no error or anything, can someone help? Thanks in advance :)
Okay, there are way too many things wrong with your code, so if you're learning from a particular site or person... find a different source.
Don't open PHP with <?. This is the shorthand style. It is disabled on many if not most web servers, and for good reason -- because XML introduces its encoding using the same opening <? and it causes conflict. Always open your PHP with <?php. http://www.php.net/manual/en/ini.core.php#ini.short-open-tag
Don't use if($_POST['submit']), use if (isset($_POST['submit'])). Your current script should generate an error, but it's probably being masked because PHP defaults to not showing very many errors. It does trigger a warning, though, because you're checking if the variable (or rather array value) $_POST['submit'] is equal to true. In fact, that variable is undefined. Use isset() to check if a variable exists. http://php.net/manual/en/function.isset.php
Sanitize your user's input. If somebody typed a ' into any of your fields, your query would break. Why? Because in your query, you're placing your stringed values in single quotes, and any instance of another single quotation mark would break out of that. There is such a thing as magic quotes in PHP (which automatically escapes POST values), but it's absolutely awful, so please disable it. http://php.net/manual/en/security.magicquotes.php The best way to escape user input is with real escape functions (more on that later).
mysql_ functions are deprecated. Use PDO or MySQLi. If you're getting used to the mysql_ functions, it is easier to transition to MySQLi. For simplicity, I'll use the procedural style, but it's much better to go with the OOP style....
If you want to debug MySQL commands with PHP, you should format your queries carefully, print the error, and also print the computed query, because sometimes you need to look at the actual resulted query in order to see what is wrong with it.
That said, here's what I suggest:
<?php
error_reporting(E_ALL);
// Turn on all error reporting. Honestly, do this every time you write a script,
// or, better yet, change the PHP configuration.
$connection = mysqli_connect('host', 'username', 'password', 'database');
// Somewhere in your config file, I assume you're calling mysql_connect.
// This is a pretty similar syntax, although you won't need mysql_select_db.
if (isset($_POST['submit'])) {
$click = mysqli_real_escape_string($connection, $_POST['click']);
// This will escape the contents of $_POST['click'], e.g.
// if the user inputted: Hello, 'world'! then this will produce:
// Hello, \'world\'!
$imp = mysqli_real_escape_string($connection, $_POST['imp']);
$url = mysqli_real_escape_string($connection, $_POST['url']);
$razmer = mysqli_real_escape_string($connection, $_POST['razmer']);
$picurl = mysqli_real_escape_string($connection, $_POST['picurl']);
$query = "
INSERT INTO `banneradd` (
`click`,
`imp`,
`url`,
`razmer`,
`picurl`,
`username`
)
VALUES
(
'$click',
'$imp',
'$url',
'$razmer',
'$picurl',
''
);
";
// Format your query nicely on multiple lines. MySQL will tell you what line
// the error occurred on, but it's not helpful if everything's on the same line.
$result = mysqli_query($connection, $query);
$error = mysqli_error($connection);
if ($error) {
echo "A MySQL error occurred: $error<br>";
echo "<pre>$query</pre>";
// If an error occurred, print the error and the original query
// so you can have a good look at it.
die;
// Stop executing the PHP.
}
echo '<div class="hr">The Banner has been added, please go back to the index: Index </div>';
}
?>
See if that helps. Chances are, the MySQL error will be helpful with diagnosing the problem. You might have just misspelled a column name or table name.
Morning,
I have created a small form to store some information to a database.
I have magic_quotes_gpc turned off on my server.
If i enter a " or a £ sign in the box is stores into the database without a worry.
When i echo it back with php it displays, but if i use the value in an input form field the " close the value field.
<input type="text" name="variable" value="<?php echo $row[variable]; ?>" />
I have now used htmlspecialchars around the input value and it works.
<input type="text" name="variable" value="<?php echo htmlspecialchars($row[variable]); ?>" />
But i have looked at open cart source as a reference and they do not use htmlspecialchars but store the data in a different way.
I tried using the urlencodes method they have used :
urlencode(html_entity_decode($_POST[variable],ENT_QUOTES, 'UTF-8'));
but this seems to store as a lot of numbers and + signs which did not display back correctly.
I would rather encode the update database instead of using the method i am with htmlspecialschars.
But not quite sure which way would be best?
Thank You
you may use
htmlentities() function in php
Perhaps try mysqli_real_escape_string($dblink, $string) instead of htmlspecialchars
For storing the HTML Character change the charters and then store them:
<?php
$new = htmlspecialchars("<a href='test'>Test</a>", ENT_QUOTES);
echo $new; // <a href='test'>Test</a>
?>
To get back the correct HTML Character do the decoding as:
<?php
$str = "<p>this -> "</p>\n";
echo htmlspecialchars_decode($str);
// note that here the quotes aren't converted
echo htmlspecialchars_decode($str, ENT_NOQUOTES);
?>
For more information refer to http://www.php.net/manual/en/function.htmlspecialchars.php
I'm trying to make a "remember fields" thingy, so if there is one error you won't have to fill in the whole form again. But how can I make the output safe?
Example:
<input type="text" name="email" value="<?php echo (isset($_POST['email'])) ? htmlspecialchars($_POST['email']) : ''; ?>" />
If someone types in " ' " (without the quotes) for example you get:
Warning: mysql_result() expects parameter 1 to be resource, boolean given in C:\wamp\www\pages\register.php on line 55
So then I tried:
<input type="text" name="email" value="<?php echo (isset($_POST['email'])) ? mysql_real_escape_string($_POST['email']) : ''; ?>" />
Then it just adds a lot of //////.
What should I do?
I'm a noob yes. But I thought htmlspecialchars made user input safe?
It depends on context.
htmlspecialchars() is your friend in HTML.
mysql_real_escape_string() is your friend in MySQL.
Update
You could run all your $_POST through htmlspecialchars() first with this...
$encodedHtmlPost = array_map('htmlspecialchars', $_POST);
You have to use mysql_real_escape_string() before you put data in database, not for the output! It will prevent SQL injections. Use htmlspecialchars when outputting data to user, it prevents XSS attacks.
When inserting in database:
$data = mysql_real_escape_string($data);
mysql_query("INSERT INTO table1(data) VALUES('$data')"); //Safe insertion
When outputting to user:
echo htmlspecialchars($data);
As for html escaping, you should use a wrapper function because htmlspecialchars needs some parameters to produce reliably safe output:
htmlspecialchars($text, ENT_QUOTES, "UTF-8");
I cannot get my addslashes function and html option value to play nice together. My initial problem was the single quote in the option but by solving that I seem to have created another issue whereby $titleunit_name only comes through with the first word.
This is what I want to come out:
baroffice=O'Fallon & Highway K&N
titleunit_name=O'Fallon & Highway K&N
cleantitleunit_name=O\'Fallon & Highway K&N
This is what I get:
baroffice=O'Fallon
titleunit_name=O'Fallon & Highway K&N
cleantitleunit_name=O\'Fallon & Highway K&N
I don't know if it matters but the values are normally coming from and being sent back to ms sql.
<form method="post" action="formtest.php?" id="searchform" target="" autocomplete="off">
<div id="office">
<font style="font-size:12px; font-weight:bold;" color="#002EB8" face="Verdana">
Closing Office:</font>
<select name="baroffice" style="width:90px">
<?php
$titleunit_name= "O'Fallon & Highway K&N";
$cleantitleunit_name=addslashes("$titleunit_name");
echo "<option value=$cleantitleunit_name name= '$titleunit_name'>";
echo "$titleunit_name</option>";
?>
</select></div><br>
<br><Br>
<input type="submit" name="submit" value="submit" style="position:relative;z-index:3">
<br><Br>
</form>
<?php
$baroffice = str_replace("\'","'",($_POST['baroffice']));
if (isset($_POST['submit']))
{
echo "baroffice=$baroffice<br>";
echo "titleunit_name=$titleunit_name<br>";
echo "cleantitleunit_name=$cleantitleunit_name<br>";
}
else
{echo "";
};
?>
Thanks for any help in advance.
First of all, you don't need double quotes around variables. Just $titleunit_name is correct, not "$titleunit_name".
Second, never use addslashes. If you're escaping content to go into MySQL use the more robust mysql_real_escape_string function. addslashes misses cases and leaves your script every bit as open to attack as if you hadn't used it at all.
And finally, slashes do not belong in HTML output. You're looking for the htmlspecialchars function, which prepares a string to be written into an HTML document.
echo '<option value="' . htmlspecialchars($titleunit_name) . '" name="' . htmlspecialchars($titleunit_name) . '">' . htmlspecialchars($titleunit_name) . '</option>';
Note that all uses of $titleunit_name (or any other variable) must be escaped in this way before writing them out to the page.
Now, I'm guessing from context that you have "magic quotes" turned out, so PHP is automatically performing an addslashes on incoming POST data. If so, turn off magic quotes, and when it's time to insert a string into the database perform the appropriate escaping then. If this is not possible, then use stripslashes to strip the slashes from all POSTed data at the beginning of the script execution so that you're getting the data as submitted.