XSS Attack Vectors in Laravel Blade

August 27, 2020

XSS attacks have been reported and exploited since the 1990s but still sometimes we see cases when developers underestimate how dangerous the attack can be because of the fact that it’s executed on the browser not on the server.

But it can be very dangerous, for example an XSS attack in the admin panel can allow an attacker to inject a code like this.

Some text 
<input
  onfocus='$.post("/admin/users", {name:"MaliciousUser", email: "MaliciousUser@example.com", password: "test123", });' 
  autofocus 
 />  test

Which will allow an attacker to create an admin user with his credentials and take over the admin panel. And even restricting the admin panel by IPs will not prevent the attack, since the code will be executed in the user’s browser who has an access to the network/application.

Now let's see what are the possible XSS attack vectors in Laravel. If you are using Laravel Blade, it protects you from most of XSS attacks, so for example an attack like this will not work

// $name = 'John Doe <script>alert("xss");</script>';
<div class="user-card">
   <div> ... </div>

   <div>{{$name}}</div>

   <div> ... </div>
</div>

because the Blade {{ }} statement automatically encodes the output. So the server will send the following properly encoded code to the browser

<div class="user-card">
   <div> ... </div>

   <div>John Doe &lt;script&gt;alert(&quot;xss&quot;);&lt;/script&gt;</div>

   <div> ... </div>
</div>

which will prevent the xss attack.

But not everything Laravel(or any other framework) can handle for you, here are some XSS attack vectors that we found most common during our security checks of dozens of Laravel applications.

1. XSS via {!! $userBio !!} Statement

Sometimes you need to output a text that contains HTML, and for it you will use {!! !!}

// $userBio = 'Hi, I am John Doe <script>alert("xss");</script>';
<div class="user-card">
   <div> ... </div>

   <div>{{$userBio}}</div>

   <div> ... </div>
</div>

In this case Laravel can’t do anything for you and if the $userBio contains JavaScript code, it will be executed as-is and we will get an XSS attack.

Prevention tips:
  • If you can, avoid outputting user supplied data without html encoding.
  • If in some cases you know that the data can contain HTML, use a package like http://htmlpurifier.org/ to clean the HTML from JS and unwanted tags before outputting the content.

2. XSS via a.href Attribute

If you are outputting user provided value as a link, here are some examples on how it can turn into an XSS attack.

Example 1: Using javascript:code

// $userWebsite = "javascript:alert('Hacked!');";

<a href="{{$userWebsite}}" >My Website</a>

Example 2: Using base64 encoded data: Note this one will work only for non top-level frames

// $userWebsite = "data:text/html;base64,PHNjcmlwdD5hbGVydCgiSGFja2VkISIpOzwvc2NyaXB0Pg==";

<a href="{{$userWebsite}}" >My Website</a>

the alert(‘Hacked!’) code will get executed when a user clicks on the My Website link in both cases..

Prevention tips:
  • Validate user provided links, in most cases, you need only to allow http/https schemas
  • As an extra layer of security, before outputting you can replace any link that is not starting with http/https schema with some “#broken-link” value.

3. XSS via Custom Directive

If you have custom blade directives in your code, you need to manually escape any output that should not be rendered as HTML in the code. For example the following custom directive is vulnerable because the name variable is not encoded and Laravel can’t do anything about it.

// Registering the directive code
Blade::directive('hello', function ($name) {
    return "<?php echo 'Hello ' . $name; ?>";
});

// user.blade.php file
// $name = 'John Doe <script>alert("xss");</script>';

@hello($name);
Prevention tips:

Use Laravel’s e function to escape any code that is user provided.

The above mentioned 3 vulnerabilities are the most common that we saw in different Laravel applications during our security checks. And as you see, this section addresses XSS attacks in Laravel’s scope, but to fully prevent XSS you also will need to make sure you front-end code which might be a React.js, Vue.js, vanilla javascript or old fashioned jQuery is also protects from XSS attacks.

📝 If you have a Laravel application that is running on production, check out also our Laravel applications security testing service.

Contact us today
for a free consultation.
Do not delay when it comes to security.
Contact us today for a free consultation.
    Thanks for contacting us!
    We will be in touch with you shortly.