Why does this Laravel CSRF vulnerability work?

chrismsnz here...

Long story short, DarkLighting is pretty much right.

Input::get() usually reads from request parameters, but if the request is JSON then it reads from the JSON body. JSON allows you to specify the type of data so instead of a CSRF token string, I sent an int(0) which will pass that loose comparison most of the time.

The other trick is that usually you cannot send JSON requests cross-site, due to the CORS check in browsers. However, Laravel has a very poor JSON check, it basically checks to see if the string '/json' is anywhere in the content type and if its there, runs the whole request through a JSON parser and feeds it into Input.

Therefore you can exploit it using something like this (jquery example)

$.ajax("http://<laravel app>/sensitiveaction", {
    type: 'post',
    contentType: 'application/x-www-form-urlencoded; charset=UTF-8; /json',
    data: '{"sensitiveparam": "sensitive", "_token": 0}',
});

It looks like it was a private disclosure, so it seems that we will not know this for sure unless someone takes the time to analyze the framework code (or @chrismsnz decides to explain it to us).

But from what i could tell, it seems like Session::token() returns a string and Input::get() returns a mixed object.

By the rather short explanation they gave, the researcher found a way to make the variable contain arbitrary data using JSON, but the value did not have the correct type (string). As the framework was only checking for the correct value, he was able to bypass the filter.

Tags:

Php

Csrf

Laravel