[Yii] Defending Against CSRF and XSS in Yii [Part 1]

CSRF stands for Cross-Site Request Forgery, and XSS stands for Cross-Site Scripting. To be honest, I only recently encountered these for the first time. After building a website with Yii and scanning it with testing software (e.g., IBM AppScan), two relatively common and serious issues were found: CSRF and XSS. So how do we fix them?

– CSRF

Reference: http://www.crarun.com/article-7.html

Yii supports CSRF configuration in its config file. Once configured, it embeds a hidden token with a hash key value in forms, and the server verifies whether each request is authorized through this token.

1
2
3
4
5
6
'components'=>array(
    'request'=>array(
        // Enable Yii Validate CSRF Token
        'enableCsrfValidation' => true,
    ),
),

In practice, because I was using an older version of Yii, the framework didn’t automatically create the input element in forms, so I had no choice but to create it manually by inserting the following code:

1
<input type="hidden" value="<?php echo Yii::app()->getRequest()->getCsrfToken(); ?>" name="YII_CSRF_TOKEN" />

Another issue arose: since CSRF wasn’t considered thoroughly early on, the entire system contained numerous AJAX POST requests, meaning lots of JS code had POST submissions. However, Yii’s view rendering doesn’t affect code inside .js files - even if you add the above code in a .js file, PHP won’t produce any output. So I came up with a workaround:

Add the following code to JS POST submissions:

1
$("input[name='YII_CSRF_TOKEN']").val()

Then add the hidden input in the PHP view. However, this also reveals a limitation - it doesn’t fully prevent CSRF. The optimal solution would be to embed authorization in each user’s session.

– XSS

When searching for solutions to this problem, a common question is: at which stage should string filtering be done - submission, storage, or display? I saw an answer on SegmentFault that said both are essential: one prevents malicious data from entering the database, and the other prevents it from being executed.

In my opinion, front-end user validation during submission is essential for good user experience. However, server-side validation is still a must, since programs can bypass the front end.

Should we also filter during display? I recommend yes - it adds an extra layer of safety to prevent attacks from taking effect.

How to do it? Yii provides CHtml and CHTMLPurifier for filtering. On GitHub, many people have open-sourced good front-end libraries for filtering - just search for them.