Last active
November 5, 2021 06:08
-
-
Save kirkbushell/5d40fdd7f7b364716742 to your computer and use it in GitHub Desktop.
Laravel 5 XSS protection middleware
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} |
We're using htmlspecialchars
in our project because of what @jackyef mentioned.
// Encode <, > and & as their HTML5 entity equivalent, leaving quotes, accented
// and special characters untouched.
$input = htmlspecialchars($input, ENT_NOQUOTES | ENT_HTML5);
I'm also thinking of replacing every EOL with a single char \n
style to ensure character counts aren't failing because of this.
$input = preg_replace('~\r\n?~', "\n", $input);
Hi. I introduced an arrangement that removes all special characters.
<?php
namespace App\Http\Middleware;
use Illuminate\Support\Facades\Redirect;
use Closure;
class XSS
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
$url = str_replace($request->url(), "", $request->fullUrl());
$input = $request->all();
array_walk_recursive($input, function (&$input) {
$input = strip_tags($input);
});
if (preg_match('/[\'^£$%&*()}{@#~><>|_+¬-]/', $url))
return redirect($request->url() . "/" . preg_replace('/[\'^£$%&*()}{@#~><>|_+¬-]/',"",strip_tags($url)));
$request->merge($input);
return $next($request);
}
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@kirkbushell Thanks for the script.
Taking on board other comments I've extended it to match what we needed and thought it might help others. If you have an input field called enquiry_field and you are wanting to accept html in that field, then if the form also passed through a hidden enquiry_field_html with any value in, this will tell the middleware to not feed it through the strip_tags but to use DomDocument and remove script tags and iframe tags instead, leaving the other, safer formatting tags. Ive also added an extra check that says that if its an admin user (via Sentinel) then dont apply the middleware as it will be handling content management requests with script tags anyway