Skip to content

Commit 3e327b8

Browse files
committed
Use more logical route binding to not reveal resources on the API unless authenticated.
1 parent 1754448 commit 3e327b8

File tree

4 files changed

+72
-35
lines changed

4 files changed

+72
-35
lines changed

app/Http/Kernel.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use Illuminate\View\Middleware\ShareErrorsFromSession;
2020
use Pterodactyl\Http\Middleware\RedirectIfAuthenticated;
2121
use Illuminate\Auth\Middleware\AuthenticateWithBasicAuth;
22+
use Pterodactyl\Http\Middleware\Api\ApiSubstituteBindings;
2223
use Illuminate\Foundation\Http\Middleware\ValidatePostSize;
2324
use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse;
2425
use Pterodactyl\Http\Middleware\Server\AuthenticateAsSubuser;
@@ -68,7 +69,7 @@ class Kernel extends HttpKernel
6869
],
6970
'api' => [
7071
'throttle:120,1',
71-
SubstituteBindings::class,
72+
ApiSubstituteBindings::class,
7273
SetSessionDriver::class,
7374
AuthenticateKey::class,
7475
AuthenticateUser::class,
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<?php
2+
3+
namespace Pterodactyl\Http\Middleware\Api;
4+
5+
use Closure;
6+
use ReflectionMethod;
7+
use Illuminate\Container\Container;
8+
use Illuminate\Routing\ImplicitRouteBinding;
9+
use Illuminate\Contracts\Routing\UrlRoutable;
10+
use Illuminate\Routing\Middleware\SubstituteBindings;
11+
12+
class ApiSubstituteBindings extends SubstituteBindings
13+
{
14+
/**
15+
* Perform substitution of route parameters without triggering
16+
* a 404 error if a model is not found.
17+
*
18+
* @param \Illuminate\Http\Request $request
19+
* @param \Closure $next
20+
* @return mixed
21+
*/
22+
public function handle($request, Closure $next)
23+
{
24+
$route = $request->route();
25+
26+
$this->router->substituteBindings($route);
27+
$this->resolveForRoute($route);
28+
29+
return $next($request);
30+
}
31+
32+
/**
33+
* Resolve the implicit route bindings for the given route. This function
34+
* overrides Laravel's default inn \Illuminate\Routing\ImplictRouteBinding
35+
* to not throw a 404 error when a model is not found.
36+
*
37+
* If a model is not found using the provided information, the binding is
38+
* replaced with null which is then checked in the form requests on API
39+
* routes. This avoids a potential imformation leak on API routes for
40+
* unauthenticated users.
41+
*
42+
* @param \Illuminate\Routing\Route $route
43+
*/
44+
protected function resolveForRoute($route)
45+
{
46+
$parameters = $route->parameters();
47+
48+
// Avoid having to copy and paste the entirety of that class into this middleware
49+
// by using reflection to access a protected method.
50+
$reflection = new ReflectionMethod(ImplicitRouteBinding::class, 'getParameterName');
51+
$reflection->setAccessible(true);
52+
53+
foreach ($route->signatureParameters(UrlRoutable::class) as $parameter) {
54+
if (! $parameterName = $reflection->invokeArgs(null, [$parameter->name, $parameters])) {
55+
continue;
56+
}
57+
58+
$parameterValue = $parameters[$parameterName];
59+
60+
if ($parameterValue instanceof UrlRoutable) {
61+
continue;
62+
}
63+
64+
// Try to find an existing model, if one is not found simply bind the
65+
// parameter as null.
66+
$instance = Container::getInstance()->make($parameter->getClass()->name);
67+
$route->setParameter($parameterName, $instance->resolveRouteBinding($parameterValue));
68+
}
69+
}
70+
}

app/Providers/RouteServiceProvider.php

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,6 @@ class RouteServiceProvider extends ServiceProvider
1616
*/
1717
protected $namespace = 'Pterodactyl\Http\Controllers';
1818

19-
/**
20-
* Define your route model bindings, pattern filters, etc.
21-
*/
22-
public function boot()
23-
{
24-
parent::boot();
25-
}
26-
2719
/**
2820
* Define the routes for the application.
2921
*/

routes/api-application.php

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,5 @@
11
<?php
22

3-
use Pterodactyl\Models\Node;
4-
use Pterodactyl\Models\User;
5-
use Pterodactyl\Models\Server;
6-
use Pterodactyl\Models\Location;
7-
use Pterodactyl\Models\Allocation;
8-
93
/*
104
|--------------------------------------------------------------------------
115
| User Controller Routes
@@ -15,10 +9,6 @@
159
|
1610
*/
1711
Route::group(['prefix' => '/users'], function () {
18-
Route::bind('user', function ($value) {
19-
return User::find($value) ?? new User;
20-
});
21-
2212
Route::get('/', 'Users\UserController@index')->name('api.application.users');
2313
Route::get('/{user}', 'Users\UserController@view')->name('api.applications.users.view');
2414

@@ -37,10 +27,6 @@
3727
|
3828
*/
3929
Route::group(['prefix' => '/nodes'], function () {
40-
Route::bind('node', function ($value) {
41-
return Node::find($value) ?? new Node;
42-
});
43-
4430
Route::get('/', 'Nodes\NodeController@index')->name('api.application.nodes');
4531
Route::get('/{node}', 'Nodes\NodeController@view')->name('api.application.nodes.view');
4632

@@ -50,10 +36,6 @@
5036
Route::delete('/{node}', 'Nodes\NodeController@delete');
5137

5238
Route::group(['prefix' => '/{node}/allocations'], function () {
53-
Route::bind('allocation', function ($value) {
54-
return Allocation::find($value) ?? new Allocation;
55-
});
56-
5739
Route::get('/', 'Nodes\AllocationController@index')->name('api.application.allocations');
5840

5941
Route::delete('/{allocation}', 'Nodes\AllocationController@delete')->name('api.application.allocations.view');
@@ -69,10 +51,6 @@
6951
|
7052
*/
7153
Route::group(['prefix' => '/locations'], function () {
72-
Route::bind('location', function ($value) {
73-
return Location::find($value) ?? new Location;
74-
});
75-
7654
Route::get('/', 'Locations\LocationController@index')->name('api.applications.locations');
7755
Route::get('/{location}', 'Locations\LocationController@view')->name('api.application.locations.view');
7856

@@ -91,10 +69,6 @@
9169
|
9270
*/
9371
Route::group(['prefix' => '/servers'], function () {
94-
Route::bind('server', function ($value) {
95-
return Server::find($value) ?? new Server;
96-
});
97-
9872
Route::get('/', 'Servers\ServerController@index')->name('api.application.servers');
9973
Route::get('/{server}', 'Servers\ServerController@view')->name('api.application.servers.view');
10074

0 commit comments

Comments
 (0)