Let's assume you have input
<input type="text" name="product[name]">
and you have the following code in your controller to validate it and save to db
$this->validate($request, ['product.name' => 'required']);
Product::create([name => $request->input('product.name']);
By changing input name from "product[name]" to "product.name" attacker can save NULL value to db, as $request->input('product.name'] returns NULL for input named "product.name".
But null won't pass the required validation rule, no?
Could'nt reproduce this with
$this->validate($request, ['product.name' => 'required']);
Also tried:
$validator = \Validator::make($request->all(), [
'product.name' => 'required',
]);
if ($validator->fails()) {
dd('fails');
}
dd($request->input('product.name').' passes');
Test results:
//As form-data
product[name] => 14
"14 passes"
product.name => 15
"fails"
product.name => 15
product[name] => 14
"14 passes"
product.name => null
product[name] => 14
"14 passes"
product[name] => 14
product.name => 15
"14 passes"
product[name] => 14
product.name => null
"14 passes"
product[name] => null
product.name => 15
"fails"
product.name => 15
product[name] => null
"fails"
product[name] => null
product.name => null
"fails"
product.name => null
product[name] => null
"fails"
If som1 could reproduce this please share an example, looks like input as well as the validator does'nt even read the field sent as product.name, this way it does'nt passes the validation...
Seems to be impossible to recreate this issue with regular html form, as PHP server by default converts dots and spaces in variable names to underscores, and it seems like Laravel relies on this feature. But with an "application/json" request type it is possible to bypass this conversion and present Validator with an input containing a dot in a name, which will pass validation. The following code returns "true":
$validator = Validator::make(
['product.name' => 'somevalue'],
['product.name' => 'required']
);
dd($validator->passes());
To recreate live scenario:
Add validator to your controller
$this->validate($request, [
'product.name' => 'required',
]);
dd('passes, and product name is ', $request->input('product.name') );
Send ajax "application/json" request with e.g. jQuery ajax:
$.ajax({
beforeSend: function (xhr) {
xhr.setRequestHeader("X-XSRF-TOKEN", 'YOUR LARAVEL TOKEN ENCRYPTED')
},
method: "POST",
url: 'http://yoursite.com/path_to_controller_route',
contentType: 'application/json',
data: '{"product.name":"any value here only to pass the required rule"}'
})
You will get:
"passes, and product name is "
null
@denho , @themsaid
Confirmed, passes with this:
"application/json"
{"product.name":"any value here only to pass the required rule"}
"passes, and product name is "
null
This issue doesn't exist anymore in laravel 5.3, we replace the dot in attribute names with -> before starting any check.
Most helpful comment
Seems to be impossible to recreate this issue with regular html form, as PHP server by default converts dots and spaces in variable names to underscores, and it seems like Laravel relies on this feature. But with an "application/json" request type it is possible to bypass this conversion and present Validator with an input containing a dot in a name, which will pass validation. The following code returns "true":
To recreate live scenario:
Add validator to your controller
Send ajax "application/json" request with e.g. jQuery ajax:
You will get:
"passes, and product name is " null