Squashed commit from '565g-9j4m-wqmr-cross-team-idor-logs-fix'

This commit is contained in:
Andras Bacsai 2026-03-10 22:11:52 +01:00
parent c15bcd5634
commit 6fbb5e626a
4 changed files with 105 additions and 8 deletions

View file

@ -45,10 +45,10 @@ public function mount()
if ($this->resource === null) {
if (isset($parameters['service_uuid'])) {
$this->resource = Service::where('uuid', $parameters['service_uuid'])->first();
$this->resource = Service::ownedByCurrentTeam()->where('uuid', $parameters['service_uuid'])->first();
} elseif (isset($parameters['stack_service_uuid'])) {
$this->resource = ServiceApplication::where('uuid', $parameters['stack_service_uuid'])->first()
?? ServiceDatabase::where('uuid', $parameters['stack_service_uuid'])->first();
$this->resource = ServiceApplication::ownedByCurrentTeam()->where('uuid', $parameters['stack_service_uuid'])->first()
?? ServiceDatabase::ownedByCurrentTeam()->where('uuid', $parameters['stack_service_uuid'])->first();
}
}

View file

@ -38,7 +38,7 @@ public function mount()
$this->servers = collect();
if (data_get($this->parameters, 'application_uuid')) {
$this->type = 'application';
$this->resource = Application::where('uuid', $this->parameters['application_uuid'])->firstOrFail();
$this->resource = Application::ownedByCurrentTeam()->where('uuid', $this->parameters['application_uuid'])->firstOrFail();
if ($this->resource->destination->server->isFunctional()) {
$this->servers = $this->servers->push($this->resource->destination->server);
}
@ -61,14 +61,14 @@ public function mount()
$this->loadContainers();
} elseif (data_get($this->parameters, 'service_uuid')) {
$this->type = 'service';
$this->resource = Service::where('uuid', $this->parameters['service_uuid'])->firstOrFail();
$this->resource = Service::ownedByCurrentTeam()->where('uuid', $this->parameters['service_uuid'])->firstOrFail();
if ($this->resource->server->isFunctional()) {
$this->servers = $this->servers->push($this->resource->server);
}
$this->loadContainers();
} elseif (data_get($this->parameters, 'server_uuid')) {
$this->type = 'server';
$this->resource = Server::where('uuid', $this->parameters['server_uuid'])->firstOrFail();
$this->resource = Server::ownedByCurrentTeam()->where('uuid', $this->parameters['server_uuid'])->firstOrFail();
$this->servers = $this->servers->push($this->resource);
}
$this->servers = $this->servers->sortByDesc(fn ($server) => $server->isTerminalEnabled());

View file

@ -106,7 +106,7 @@ public function mount()
$this->query = request()->query();
if (data_get($this->parameters, 'application_uuid')) {
$this->type = 'application';
$this->resource = Application::where('uuid', $this->parameters['application_uuid'])->firstOrFail();
$this->resource = Application::ownedByCurrentTeam()->where('uuid', $this->parameters['application_uuid'])->firstOrFail();
$this->status = $this->resource->status;
if ($this->resource->destination->server->isFunctional()) {
$server = $this->resource->destination->server;
@ -133,7 +133,7 @@ public function mount()
$this->containers->push($this->container);
} elseif (data_get($this->parameters, 'service_uuid')) {
$this->type = 'service';
$this->resource = Service::where('uuid', $this->parameters['service_uuid'])->firstOrFail();
$this->resource = Service::ownedByCurrentTeam()->where('uuid', $this->parameters['service_uuid'])->firstOrFail();
$this->resource->applications()->get()->each(function ($application) {
$this->containers->push(data_get($application, 'name').'-'.data_get($this->resource, 'uuid'));
});

View file

@ -0,0 +1,97 @@
<?php
use App\Models\Application;
use App\Models\Environment;
use App\Models\Project;
use App\Models\Server;
use App\Models\Service;
use App\Models\StandaloneDocker;
use App\Models\Team;
use App\Models\User;
beforeEach(function () {
// Attacker: Team A
$this->userA = User::factory()->create();
$this->teamA = Team::factory()->create();
$this->userA->teams()->attach($this->teamA, ['role' => 'owner']);
$this->serverA = Server::factory()->create(['team_id' => $this->teamA->id]);
$this->destinationA = StandaloneDocker::factory()->create(['server_id' => $this->serverA->id]);
$this->projectA = Project::factory()->create(['team_id' => $this->teamA->id]);
$this->environmentA = Environment::factory()->create(['project_id' => $this->projectA->id]);
// Victim: Team B
$this->teamB = Team::factory()->create();
$this->serverB = Server::factory()->create(['team_id' => $this->teamB->id]);
$this->destinationB = StandaloneDocker::factory()->create(['server_id' => $this->serverB->id]);
$this->projectB = Project::factory()->create(['team_id' => $this->teamB->id]);
$this->environmentB = Environment::factory()->create(['project_id' => $this->projectB->id]);
$this->victimApplication = Application::factory()->create([
'environment_id' => $this->environmentB->id,
'destination_id' => $this->destinationB->id,
'destination_type' => $this->destinationB->getMorphClass(),
]);
$this->victimService = Service::factory()->create([
'environment_id' => $this->environmentB->id,
'destination_id' => $this->destinationB->id,
'destination_type' => StandaloneDocker::class,
]);
// Act as attacker
$this->actingAs($this->userA);
session(['currentTeam' => $this->teamA]);
});
test('cannot access logs of application from another team', function () {
$response = $this->get(route('project.application.logs', [
'project_uuid' => $this->projectA->uuid,
'environment_uuid' => $this->environmentA->uuid,
'application_uuid' => $this->victimApplication->uuid,
]));
$response->assertStatus(404);
});
test('cannot access logs of service from another team', function () {
$response = $this->get(route('project.service.logs', [
'project_uuid' => $this->projectA->uuid,
'environment_uuid' => $this->environmentA->uuid,
'service_uuid' => $this->victimService->uuid,
]));
$response->assertStatus(404);
});
test('can access logs of own application', function () {
$ownApplication = Application::factory()->create([
'environment_id' => $this->environmentA->id,
'destination_id' => $this->destinationA->id,
'destination_type' => $this->destinationA->getMorphClass(),
]);
$response = $this->get(route('project.application.logs', [
'project_uuid' => $this->projectA->uuid,
'environment_uuid' => $this->environmentA->uuid,
'application_uuid' => $ownApplication->uuid,
]));
$response->assertStatus(200);
});
test('can access logs of own service', function () {
$ownService = Service::factory()->create([
'environment_id' => $this->environmentA->id,
'destination_id' => $this->destinationA->id,
'destination_type' => StandaloneDocker::class,
]);
$response = $this->get(route('project.service.logs', [
'project_uuid' => $this->projectA->uuid,
'environment_uuid' => $this->environmentA->uuid,
'service_uuid' => $ownService->uuid,
]));
$response->assertStatus(200);
});