ajoo Posted May 27, 2014 Share Posted May 27, 2014 Hi friends, Another security issue but this time its regarding outputting data from a DB to a browser. Please have a look at the code below which displays some output fetched from a DB and sends it to a browser. 1. If I just wish to display this output on a screen and not provide the user with any buttons or hyperlinks to interact with the information, would I still need to sanitize the output before echoing it to the screen ? 2. If I was to make at least one of the fields a hyperlink, so that I could then display some related information on another webpage, what security concerns would I need to address in my code? 3. If I was to add a button against each of these records, on each row, and then select some related information on another webpage after processing the button handler, what would be the security concerns that I should address for the code below. Thanks very much. <table> <tr> <th> S.No. </th> <th> Name </th> <th> Age </th> <th> City </th> <th> Cell </th> <th> Email</th> </tr> <?php $cnt = 1; while ($row = mysqli_fetch_array($result, MYSQLI_ASSOC)) { echo "<tr>"; echo "<td>".$cnt++."</td>"; echo "<td>".$row['Name']. "</td>"; echo "<td>".$row['Age']. "</td>"; echo "<td>".$row['City']. "</td>"; echo "<td>".$row['Cell']. "</td>"; echo "<td>".$row['Email']. "</td>"; echo "</tr>"; } ?> </table> Quote Link to comment Share on other sites More sharing options...
Psycho Posted May 27, 2014 Share Posted May 27, 2014 (edited) #1: Since I have no clue what the source of this information is, the answer would be Yes. Always assume data could be malicious and take appropriate precautions. So, for this you can just use htmlentities() or htmlspecialchars() when outputting those field values. I prefer to 'prepare" the data before outputting - instead of doing it in-line. Plus, put your "Logic" at the top of the page (or even in a separate file) <?php ## PUT ALL THE PHP LOGIC AT THE TOP OF YOUR SCRIPT ## CREATE VARIABLES THAT ARE OUTPUT IN THE HTML OUTPUT $user_list_HTML = ''; $cnt = 0; while ($row = mysqli_fetch_array($result, MYSQLI_ASSOC)) { $cnt++; $name = htmlspecialchars($row['Name']); $age = htmlspecialchars($row['Name']); $city = htmlspecialchars($row['Name']); $cell = htmlspecialchars($row['Name']); $email = htmlspecialchars($row['Name']); $user_list_HTML .= "<tr>\n"; $user_list_HTML .= " <td>{$cnt}</td>\n"; $user_list_HTML .= " <td>{$name}</td>\n"; $user_list_HTML .= " <td>{$age}</td>\n"; $user_list_HTML .= " <td>{$city}</td>\n"; $user_list_HTML .= " <td>{$cell}</td>\n"; $user_list_HTML .= " <td>{$email}</td>\n"; $user_list_HTML .= "</tr>\n"; } ?> <html> <head></head> <body> <table> <tr> <th> S.No. </th> <th> Name </th> <th> Age </th> <th> City </th> <th> Cell </th> <th> Email</th> </tr> <?php echo $user_list_HTML; ?> </table> </body> </html> #2: There is nothing in that code that would make sense to be a link. You would likely want to include the primary ID frm that table and use THAT in the link. Something like echo "<td><a href='get_user_data.php?id={id}'>{$name}</a></td>\n"; And, in that case you could use intval() on the ID, but that probably isn't necessary since the ID would be database defined and would never be set by an external source. However, on the get_user_data,php page you *would* need to add validation to ensure the id passed is valid and/or escaped to prevent SQL injection #3: I would assume the button would do something similar as the link and just pass the id of the record to be processed. So, the same applies. Not necessary to validate on the page that creates the button since the value is programatically created in the database (but it doesn't hurt to add some logic). but, you would definitely need to validate/sanitize on the receiving page. Edited May 27, 2014 by Psycho Quote Link to comment Share on other sites More sharing options...
ajoo Posted May 27, 2014 Author Share Posted May 27, 2014 Hi ! Thanks for the reply. #1. The source of this information would be a Mysql database. But yes I will use htmlspecialchars(). #2. For the second case I mentioned the hyperlink because that is passed through the URL and I thought that that maybe be a cause of a security concerns which should be addressed. #3. Yes this would be just like the #2 as you have mentioned and for this I would need to validate the post data submitted. If there is anything that you would like to add to the first 2 cases. Thanks Quote Link to comment Share on other sites More sharing options...
Psycho Posted May 27, 2014 Share Posted May 27, 2014 #1. The source of this information would be a Mysql database. But yes I will use htmlspecialchars(). No, it is not. The database isn't going to magically create names, ages, etc. It does automatically create auto-increment IDs. The latter are the types of values that you don't, necessarily, need to validate because you know they will be the type that you expect. As for the names, ages, etc. The values are being entered 'somewhere', but I don't know who is entering or what logic is applied before the data is saved. Although you *could* perform validations/sanitizing before storing the data in the database, you would not want to rely upon that during the output process. Don't create a process that *assumes* something is being done by a separate process. Quote Link to comment Share on other sites More sharing options...
Solution Jacques1 Posted May 27, 2014 Solution Share Posted May 27, 2014 (edited) You must specifiy the character encoding when you escape data. Without this, you're flying blind. If you're lucky, the browser will pick the same encoding which htmlspecialchars() happens to use by default, but this definitely isn't something you should rely on. For example, Internet Explorer is infamous for “guessing” the encoding if there's no explicit declaration. An attacker can use this to bypass escaping entirely: They give you a string which is harmless when interpreted with your default encoding, so htmlspecialchars() takes no action. But when Internet Explorer does its guessing and chooses a different encoding, the harmless string suddenly turns into malicious HTML. Try this in any version of Internet Explorer: <?php // Mimic the guessing behaviour of IE 7 and earlier. header('Content-Type: text/html;charset=utf-7'); $input = "+ADw-script+AD4-alert('XSS!')+ADw-/script+AD4-"; /* * Since you forgot to tell htmlspecialchars() which character encoding it should use, it will * assume ISO 8859-1 or UTF-8 depending on the PHP version. When $input is interpreted with those * encodings, it's meaningless and will not be touched by htmlspecialchars(). Unfortunately, the * client uses UTF-7! And in that case, the input means this: <script>alert('XSS!')</script> */ $maybe_safe = htmlspecialchars($input); // There's our XSS vulnerability, regardless of the fact that we've used htmlspecialchars(). echo $maybe_safe; So escaping without an encoding declaration is futile. You first need to define the character encoding of your HTML document if you haven't done that already: // If you're not using UTF-8, change this accordingly. header('Content-Type: text/html;charset=utf-8'); And then you need to use this exact encoding for htmlspecialchars(). It's probably best to write a custom wrapper function: function html_escape($input, $encoding) { /* * Note the flags: * * ENT_QUOTES tells the function to escape both single and double quotes. * Otherwise, single quotes will be ignored and can be used for attacks. * * ENT_SUBSTITUTE tells the function to replace invalid Unicode sequences * with an error symbol. Otherwise, the entire input will be replaced with * an empty string, which is probably not what you want. */ return htmlspecialchars($input, $encoding, ENT_QUOTES | ENT_SUBSTITUTE); } Edited May 27, 2014 by Jacques1 Quote Link to comment Share on other sites More sharing options...
ajoo Posted May 27, 2014 Author Share Posted May 27, 2014 Thanks loads. I'll take the precautions. Thanks Jacques for that insight into character encoding. I'll read more on that. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.