Insecure or unset HTTP headers - Accept - PHP

Insecure or unset HTTP headers - Accept - PHP

Need

Enforcement of secure and restricted HTTP headers - Accept

Context

  • Usage of PHP for server-side scripting and web development
  • Usage of Request for making HTTP requests

Description

Non compliant code

        public function get(Request $request)
{
    $content = $request->getContent();
    //...
}
        
        

In the above code snippet, we have a method get() in a controller that gets a request and directly uses its content. This method does not set or check the 'Accept' HTTP header of the request.

The 'Accept' header is used by HTTP clients to tell the server what content types they'll accept. The server will then send back a response, which will include a content-type in the HTTP header to tell the client what the content type of the returned content actually is.

In this code, since there is no 'Accept' header being set or checked, the server could potentially send back a response containing any type of content. An attacker could exploit this to send a request with a malicious content type, causing the application to behave in unexpected ways. This is a security vulnerability as it can lead to issues such as Cross-Site Scripting (XSS) or other injection attacks.

Steps

  • Validate the 'Accept' header of the incoming request to ensure it's of the expected type.
  • Set a default 'Accept' header if it's not provided in the request.
  • Reject requests with 'Accept' headers that are not of the expected type.
  • Implement a middleware to handle the validation of the 'Accept' header for all incoming requests.

Compliant code

        getAcceptableContentTypes();

        if (empty($acceptable) || !in_array('application/json', $acceptable)) {
            return response()->json(['error' => 'Invalid Accept header'], 406);
        }

        return $next($request);
    }
}
        
        

The above code is a middleware that checks the 'Accept' header of every incoming request.

The getAcceptableContentTypes() method is used to get the acceptable content types from the request. If the 'Accept' header is not set or if it's not 'application/json', the middleware returns a 406 Not Acceptable status code with an error message.

If the 'Accept' header is 'application/json', the middleware passes the request to the next middleware in the stack or to the controller if there are no more middlewares.

To use this middleware, you need to register it in the app/Http/Kernel.php file:

                protected $routeMiddleware = [
    // ...
    'check.accept' => \\App\\Http\\Middleware\\CheckAcceptHeader::class,
];

            


Then, you can apply it to your routes:

                Route::get('/endpoint', 'Controller@method')->middleware('check.accept');

            


This way, all requests to '/endpoint' will have to pass through the CheckAcceptHeader middleware before reaching the Controller@method. If the 'Accept' header is not 'application/json', the request will be rejected with a 406 status code.

References