Use more logical route binding to not reveal resources on the API unless authenticated.

This commit is contained in:
Dane Everitt 2018-01-20 15:33:04 -06:00
parent 17544481b5
commit 3e327b8b0e
No known key found for this signature in database
GPG key ID: EEA66103B3D71F53
4 changed files with 72 additions and 35 deletions

View file

@ -19,6 +19,7 @@ use Pterodactyl\Http\Middleware\AccessingValidServer;
use Illuminate\View\Middleware\ShareErrorsFromSession;
use Pterodactyl\Http\Middleware\RedirectIfAuthenticated;
use Illuminate\Auth\Middleware\AuthenticateWithBasicAuth;
use Pterodactyl\Http\Middleware\Api\ApiSubstituteBindings;
use Illuminate\Foundation\Http\Middleware\ValidatePostSize;
use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse;
use Pterodactyl\Http\Middleware\Server\AuthenticateAsSubuser;
@ -68,7 +69,7 @@ class Kernel extends HttpKernel
],
'api' => [
'throttle:120,1',
SubstituteBindings::class,
ApiSubstituteBindings::class,
SetSessionDriver::class,
AuthenticateKey::class,
AuthenticateUser::class,

View file

@ -0,0 +1,70 @@
<?php
namespace Pterodactyl\Http\Middleware\Api;
use Closure;
use ReflectionMethod;
use Illuminate\Container\Container;
use Illuminate\Routing\ImplicitRouteBinding;
use Illuminate\Contracts\Routing\UrlRoutable;
use Illuminate\Routing\Middleware\SubstituteBindings;
class ApiSubstituteBindings extends SubstituteBindings
{
/**
* Perform substitution of route parameters without triggering
* a 404 error if a model is not found.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
$route = $request->route();
$this->router->substituteBindings($route);
$this->resolveForRoute($route);
return $next($request);
}
/**
* Resolve the implicit route bindings for the given route. This function
* overrides Laravel's default inn \Illuminate\Routing\ImplictRouteBinding
* to not throw a 404 error when a model is not found.
*
* If a model is not found using the provided information, the binding is
* replaced with null which is then checked in the form requests on API
* routes. This avoids a potential imformation leak on API routes for
* unauthenticated users.
*
* @param \Illuminate\Routing\Route $route
*/
protected function resolveForRoute($route)
{
$parameters = $route->parameters();
// Avoid having to copy and paste the entirety of that class into this middleware
// by using reflection to access a protected method.
$reflection = new ReflectionMethod(ImplicitRouteBinding::class, 'getParameterName');
$reflection->setAccessible(true);
foreach ($route->signatureParameters(UrlRoutable::class) as $parameter) {
if (! $parameterName = $reflection->invokeArgs(null, [$parameter->name, $parameters])) {
continue;
}
$parameterValue = $parameters[$parameterName];
if ($parameterValue instanceof UrlRoutable) {
continue;
}
// Try to find an existing model, if one is not found simply bind the
// parameter as null.
$instance = Container::getInstance()->make($parameter->getClass()->name);
$route->setParameter($parameterName, $instance->resolveRouteBinding($parameterValue));
}
}
}

View file

@ -16,14 +16,6 @@ class RouteServiceProvider extends ServiceProvider
*/
protected $namespace = 'Pterodactyl\Http\Controllers';
/**
* Define your route model bindings, pattern filters, etc.
*/
public function boot()
{
parent::boot();
}
/**
* Define the routes for the application.
*/

View file

@ -1,11 +1,5 @@
<?php
use Pterodactyl\Models\Node;
use Pterodactyl\Models\User;
use Pterodactyl\Models\Server;
use Pterodactyl\Models\Location;
use Pterodactyl\Models\Allocation;
/*
|--------------------------------------------------------------------------
| User Controller Routes
@ -15,10 +9,6 @@ use Pterodactyl\Models\Allocation;
|
*/
Route::group(['prefix' => '/users'], function () {
Route::bind('user', function ($value) {
return User::find($value) ?? new User;
});
Route::get('/', 'Users\UserController@index')->name('api.application.users');
Route::get('/{user}', 'Users\UserController@view')->name('api.applications.users.view');
@ -37,10 +27,6 @@ Route::group(['prefix' => '/users'], function () {
|
*/
Route::group(['prefix' => '/nodes'], function () {
Route::bind('node', function ($value) {
return Node::find($value) ?? new Node;
});
Route::get('/', 'Nodes\NodeController@index')->name('api.application.nodes');
Route::get('/{node}', 'Nodes\NodeController@view')->name('api.application.nodes.view');
@ -50,10 +36,6 @@ Route::group(['prefix' => '/nodes'], function () {
Route::delete('/{node}', 'Nodes\NodeController@delete');
Route::group(['prefix' => '/{node}/allocations'], function () {
Route::bind('allocation', function ($value) {
return Allocation::find($value) ?? new Allocation;
});
Route::get('/', 'Nodes\AllocationController@index')->name('api.application.allocations');
Route::delete('/{allocation}', 'Nodes\AllocationController@delete')->name('api.application.allocations.view');
@ -69,10 +51,6 @@ Route::group(['prefix' => '/nodes'], function () {
|
*/
Route::group(['prefix' => '/locations'], function () {
Route::bind('location', function ($value) {
return Location::find($value) ?? new Location;
});
Route::get('/', 'Locations\LocationController@index')->name('api.applications.locations');
Route::get('/{location}', 'Locations\LocationController@view')->name('api.application.locations.view');
@ -91,10 +69,6 @@ Route::group(['prefix' => '/locations'], function () {
|
*/
Route::group(['prefix' => '/servers'], function () {
Route::bind('server', function ($value) {
return Server::find($value) ?? new Server;
});
Route::get('/', 'Servers\ServerController@index')->name('api.application.servers');
Route::get('/{server}', 'Servers\ServerController@view')->name('api.application.servers.view');