I wonder how (if anyhow) is XSS protection provided in Laravel. I couldn\'t find anything about it in the documentation.
Problem
I am using
class XSSProtection
{
/**
* The following method loops through all request input and strips out all tags from
* the request. This to ensure that users are unable to set ANY HTML within the form
* submissions, but also cleans up input.
*
* @param Request $request
* @param callable $next
* @return mixed
*/
public function handle(Request $request, \Closure $next)
{
if (!in_array(strtolower($request->method()), ['put', 'post'])) {
return $next($request);
}
$input = $request->all();
array_walk_recursive($input, function(&$input) {
$input = strip_tags($input);
});
$request->merge($input);
return $next($request);
}
}
You also filter input before validation like, First create /app/Common/Utility.php
<?php
namespace App\Common;
use Illuminate\Support\Facades\Input;
class Utility {
public static function stripXSS()
{
$sanitized = static::cleanArray(Input::get());
Input::merge($sanitized);
}
public static function cleanArray($array)
{
$result = array();
foreach ($array as $key => $value) {
$key = strip_tags($key);
if (is_array($value)) {
$result[$key] = static::cleanArray($value);
} else {
$result[$key] = trim(strip_tags($value)); // Remove trim() if you want to.
}
}
return $result;
}
}
And use in your controller like this
use App\Common\Utility;
public function store()
{
Utility::stripXSS();
// Remaining Codes
}
This code will clean your input before validation
The package laravelgems/blade-escape extends Blade by adding different escaping strategies/directives - @text
, @attr
, @css
, @js
, @param
Example:
<style>
.userPrefix:before { content: "@css($content)"; }
</style>
<div>
<label class="userPrefix">@text($label)</label>
<input type="text" name="custom" value="@attr($value)"/>
</div>
<a href="/profile?u=@param($username)">Profile</a>
<button onclick="callMyFunction('@js($username)');">Validate</button>
<script>
var username = "@js($username)";
</script>
Read their README. XSS is very tricky, there are a lot contexts and approaches.
Testing page - http://laragems.com/package/blade-escape/test
Makes much more sense to me not to let those sneaky bastards into the database in the first place.
Actually - that is not true.
The reason that XSS is only handled by blade is that XSS attacks are an output problem. There is no security risk if you store <script>alert('Hacking Sony in 3...2...')</script>
in your database - it is just text - it doesnt mean anything.
But in the context of HTML output - then the text has a meaning, and therefore that is where the filtering should occur.
Also - it is possible that XSS attack could be a reflected attack, where the displayed data is not coming from the database, but from another source. i.e. an uploaded file, url etc. If you fail to filter all the various input locations - you run a risk of missing something.
Laravel encourages you to escape all output, regardless where it came from. You should only explicitly display non-filtered data due to a specific reason - and only if you are sure the data is from a trusted source (i.e. from your own code, never from user input).
p.s. In Laravel 5 the default {{ }}
will escape all output - which highlights the importance of this.
Edit: here is a good discussion with further points on why you should filter output, not input: html/XSS escape on input vs output
As far as I know, the "official" Laravel position is that XSS prevention best practice is to escape output. Thus, {{{ }}}
.
You can supplement output escaping through input sanitation with Input::all()
, strip_tags()
, and array_map()
:
$input = array_map('strip_tags', \Input::all());
I examined the Laravel's protection {{{...}}}
against xss attack. It just uses the htmlentities()
function in the way like this: htmlentities('javascript:alert("xss")', ENT_QUOTES, 'UTF-8', false);
This protects you against xss only if you use it properly means dont use it in certain HTML tags because it will result in XSS attack possibility. For example:
$a = htmlentities('javascript:alert("xss")', ENT_QUOTES, 'UTF-8', false);
echo '<a href="'.$a.'">link</a>';
In this case, it is vulnerable to xss.