2

I have found from different blogs that it is strongly recommended to use htmlspecialchars() to output any data on screen to be safe from XSS Attack.

I am using filter_input() to filter any data that comes from user before inserting into database. filter_input() convert special characters like ' to ' and saved it that way,like

 I'm going to shopping with Molly's sister;Dolly

.My question is

How can I print(output) apostrope or quotes and specific special characters to users screen using htmlspecialchars so that the output would be user friendly

I have tried to use htmlspecialchars($post,ENT_NOQUOTES);,but it gives me same copy of data that is stored in database.If I don't use htmlspecialchars(),just $post gives me expected result,which I think is vulnerable to XSS Attack

Thanks for your time,and look forward to get help from peers.

EDIT

I got suggestions to use htmlspecialchars_decode() or html_entity_decode() on answer,but (https://stackoverflow.com/users/1338292/ja͢ck) and some other suggested not to use these functions to output data on screen.

Please be informed that I am using prepared statement and parameterized query.But I don't want to keep any security holes,that's why filtering data before sending into database.

As I have used filter_input() to filter data before sending to database,is it safe to output data directly($post=$posted_data;) from database without using htmlspecialchars?

If I must need to use htmlspecialchars to output data,then how can I do it in this case?

Code Sample

 $stmt1=mysqli_stmt_init($connect_dude);

 /*Inserting into database*/

 if(isset($_POST['titlex']) && isset($_POST['pricex'])  && isset($_POST['detailx'])){
  $tit=filter_input(INPUT_POST,'titlex',FILTER_SANITIZE_STRING);
  $pri=preg_replace('#[^0-9]#','',$_POST['pricex']);
  $det=filter_input(INPUT_POST,'detailx',FILTER_SANITIZE_STRING); 

  $query2="INSERT INTO `hotel1`.`dine` (user_id,title,price,detail) VALUES (?,?,?,?)";

    mysqli_stmt_prepare($stmt1,$query2);
    mysqli_stmt_bind_param($stmt1, "isis", $logged_id, $tit, $pri, $det);
    mysqli_stmt_execute($stmt1);    
 }

 /*Get Data from DB*/

 $query1="SELECT id101,title,price,detail FROM `hotel1`.`dine` WHERE user_id=?";

    mysqli_stmt_prepare($stmt1,$query1);
    mysqli_stmt_bind_param($stmt1, "i", $user_idx);
    mysqli_stmt_execute($stmt1);
    mysqli_stmt_store_result($stmt1);
    mysqli_stmt_bind_result($stmt1, $id101, $title,$price, $detail);

    while(mysqli_stmt_fetch($stmt1)){
     $id101=$id101;
     $title=$title;        //htmlspecialchars needed
     $price=$price;       //htmlspecialchars needed
     $detail=$detail;    //htmlspecialchars needed

     ........................
     ........................
     }
Community
  • 1
  • 1
Coder
  • 237
  • 4
  • 21

4 Answers4

9

I am using filter_input() to filter any data that comes from user before inserting into database.

This is a bad practice. Do not mangle your data before you insert it into a database. It's 2015; don't sanitize, use prepared statements instead.

$db = new \PDO(
    'mysql:host=localhost;dbname=mydatabase;charset=UTF-8',
     $username,
     $password
);

// other stuff in between

$statement = $db->prepare(
    "INSERT INTO yourtable (email, username) VALUES (:email, :username);"
);
$success = $statement->execute([
    ':email'    => $_POST['email'],
    ':username' => $_POST['username']
]);

Prepared statements remove the need for filter_input(). You're not adding defense in depth by doing this, you're just ruining data integrity and giving yourself a headache.

When you render your output, if you want to allow HTML, use HTML Purifier.

Otherwise, use htmlspecialchars($output, ENT_QUOTES | ENT_HTML5, 'UTF-8') for best results.

Recommended Reading: Web Application Security by Taylor Hornby.

Scott Arciszewski
  • 33,610
  • 16
  • 89
  • 206
  • 2
    I am using `prepared statement` and `parameterized query` already.But I don't want to keep any security holes,that's why filter data before sending into database. – Coder Mar 04 '15 at 19:24
  • 1
    And,`HTMLPurifier` should be used for `textarea` where I want to allow limited `HTML Tags`.I am using `HTMLPurifier` for textarea,but not for text field.Because It's 2015.Thanks for your answer,dude.I really need an elaborate answer that would relieve all my confusion. – Coder Mar 04 '15 at 19:33
  • You should `htmlentities()` the contents of a textarea anyway. if you're using prepared statements, you don't need to sanitize your input. It separates data from instructions. – Scott Arciszewski Mar 05 '15 at 03:26
  • 2
    I just want to emphasize again that sanitizing for output is something you need to do __on output__, not when you insert it into the database. Sanitizing before insertion just leads to data corruption. – Sven Slootweg Mar 09 '15 at 19:14
  • @SvenSlootweg did you mean to insert user inputted data as it is into database?And just use `htmlspecialchars` to output to users' screen. doesn't malicious data can be inserted even after using `prepared statement`? – Coder Mar 10 '15 at 14:18
  • What do you mean by malicious data? – Scott Arciszewski Mar 10 '15 at 14:27
  • 1
    @Coder Yes, that is what I mean. It isn't "malicious data" as long as it is in the database - the database has no idea what HTML or Javascript is, doesn't care, and so doesn't need to be protected from it. It's all just bytes, it could be *anything* as far as the database is concerned. XSS only becomes a problem when you try to *output* data into a webpage, and that's why you sanitize it *on output*. Just keep the original data in your database, so that you have 'intact' data to work from if you ever need to change anything. – Sven Slootweg Mar 11 '15 at 06:31
  • I just want to keep it simple and don't want to allow any `html tags` for any field. – Coder Mar 13 '15 at 16:11
  • If you do that, it doesn't allow ANY tags. It turns `<` into `<`, etc. according to the HTML5 spec. You're safe. https://eval.in/300124 – Scott Arciszewski Mar 13 '15 at 20:09
0

I think there's a problem with your strategy.

You certainly need to filter input and output stuff but you're overlaying them - double escape.
The problem is your input filter is doing also the output filter's work.

As I have used filter_input() to filter data before sending to database,is it safe to output data directly($post=$posted_data;) from database without using htmlspecialchars?

No. Don't trust your database, or at least not always. It wouldn't be the first case an SQL injection caused a huge XSS.

If I must need to use htmlspecialchars to output data,then how can I do it in this case?

As I said above, stop using input filter for output filtering. Your input filter should just make sure the data is safe for internal use - to protect your application against not-indented operations. Thus you don't need to escape HTML before inserting to database, and as a bonus you'll save space.

On the other hand output filter cares about the end-user. You take the data from db and send it to the user. We're talking about htmlspecialchars which is fine with ENT_QUOTES but in my opinion is not sufficient. You should also escape characters like ( ) [ ] = + - \ since there are cases you don't need for a successful XSS attack to open/end any tag or use quotes. For example when you output data into onclick, etc.

I just saw that htmlspecialchars has double_encode parameter, which would eventually solve your problem:

htmlspecialchars($string, ENT_QUOTES, "UTF-8", false);

Doing this will always keep HTML special chars escaped and won't escape already escaped stuff.

Zaffy
  • 16,801
  • 8
  • 50
  • 77
-1

You want to go the other way around :) htmlspecialchars_decode()

Patrick Webster
  • 290
  • 1
  • 7
  • But I was told `htmlspecialchars_decode` is a bad idea for outputting data.`XSS` risk – Coder Feb 28 '15 at 01:03
  • Ah, I understand now, my apologies. This is the "less bad" http://php.net/manual/en/function.html-entity-decode.php – Patrick Webster Feb 28 '15 at 01:07
  • If you wan to handle it yourself to be extra "secure" you could scan over the text in mysql checking it against http://php.net/manual/en/function.get-html-translation-table.php -- I don't know that its any more or less safe using the normal html_entity_decode() without looking at the underlying C code though. – Patrick Webster Feb 28 '15 at 01:11
-1

You dont need to, when you encode them and save them to DB, they will be shown on the web page (when you use echo $result['message'];) as they should. Browsers automaticaly decode them.

I am using this function to strip input:

function stripinput($text) {
    if (!is_array($text)) {
        $text = trim($text);
        $text = preg_replace("/(&amp;)+(?=\#([0-9]{2,3});)/i", "&", $text);
        $search = array("&", "\"", "'", "\\", '\"', "\'", "<", ">", "&nbsp;");
        $replace = array("&amp;", "&quot;", "&#39;", "&#92;", "&quot;", "&#39;", "&lt;", "&gt;", " ");
        $text = str_replace($search, $replace, $text);
    }else{
        foreach ($text as $key => $value) {
            $text[$key] = stripinput($value);
        }
    }
    return $text;
}
MiChAeLoKGB
  • 796
  • 14
  • 38