XSS stands for cross-site scripting and is a type of vulnerability that allows one to inject a client-side script (typically, JavaScript) in the page viewed by other users. Considering the power of the client-side scripting this can lead to very serious consequences such as bypassing security checks, getting other user credentials, or data leaks.
In this recipe, we will see how to prevent XSS by escaping the output with both CHtml
and CHtmlPurifier
.
Generate a fresh web application by using yiic webapp
. Create protected/controllers/XssController.php
as follows:
<?php class XssController extends CController { public function actionSimple() { echo 'Hello, '.$_GET['username'].'!'; } }
Normally, it will be used as /xss/simple?username=Alexander
. However, as the main security principle "filter input, escape output" was not taken into account, malicious users will be able to use it in the following way:
/xss/simple?username=<script>alert('XSS'),</script>
The preceding will result in a script execution, shown in the following screenshot:
Note that instead of just alerting XSS, it is possible, for example, to steal page contents or perform some website-specific things such as deleting all users' data.
Carry out the following steps:
class XssController extends CController { public function actionSimple() { echo 'Hello, '.CHtml::encode($_GET['username']).'!'; } }
echo CHtml::link(CHtml::encode($_GET['username']), array());
CHtml::encode
anymore because it will render HTML as just a code and we need the actual representation. Fortunately, there is a tool bundled with Yii that allows filtering out the malicious HTML. It is named HTML Purifier and can be used in the following way:public function actionHtml() { $this->beginWidget('CHtmlPurifier'), echo $_GET['html']; $this->endWidget(); }
Alternatively, you can use it in the following way:
public function actionHtml() { $purifier=new CHtmlPurifier(); echo $purifier->purify($_GET['html']); }
html
action using a URL such as /xss/html?html=Hello,<strong>username</strong>!<script>alert('XSS')</script>
, the HTML Purifier will remove the malicious part and we will get the following result:Internally, CHtml::encode
looks like the following:
public static function encode($text) { return htmlspecialchars($text,ENT_QUOTES,Yii::app()->charset); }
So basically, we use the PHP's internal htmlspecialchars
function, which is pretty secure if one does not forget to pass the correct charset in the third argument.
CHtmlPurifier
uses the HTML Purifier library, which is the most advanced solution out there to prevent XSS inside of HTML. We have used its default configuration, which is OK for most of the user-entered content.
There are more things to know about XSS and HTML Purifier; they are discussed in the following section.
There are two main types of XSS injections, which are as follows:
The first type is exactly the one that we have used in the recipe and is the most common XSS type that can be found in most insecure web applications. Data passed by the user or through a URL is not stored anywhere, so the injected script will be executed only once and only for the user who entered it. Still, it is not as secure as it looks. Malicious users can include XSS in a link to another website and their core will be executed when another user will follow the link.
The second type is much more serious, as the data entered by a malicious user is stored in the database and is shown to many, if not all, website users. Using this type of XSS, one can literally destroy your website by commanding all users to delete all data to which they have access.
The HTML Purifier can be configured as follows:
$p = new CHtmlPurifier(); $p->options = array('URI.AllowedSchemes'=>array( 'http' => true, 'https' => true, )); $text = $p->purify($text);
For a list of all possible keys, which you can use in the options array, refer to the following URL:
As the HTML Purifier performs a lot of processing and analysis, its performance is not so good. Therefore, it is a good idea not to process text every time you are outputting it. Instead, it can be saved in a separate database field as discussed in Chapter 6, Database, Active Record, and Model Tricks, in the Applying markdown and HTML recipe or cached.
In order to learn more about XSS and how to deal with it, refer to the following resources:
3.134.118.95