Skip to content

Commit f41ee6a

Browse files
committed
test(auth): add privilege escalation security tests
Eight tests covering the C1 (IDOR), C2 (mass assignment), and M1 (sensitive fillable fields) vulnerabilities. Includes both negative cases verifying non-admin users are blocked and positive cases confirming administrators retain access.
1 parent e0c5e09 commit f41ee6a

1 file changed

Lines changed: 179 additions & 0 deletions

File tree

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
<?php
2+
3+
namespace Tests\Feature;
4+
5+
use App\Models\Role;
6+
use App\Models\User;
7+
use Illuminate\Foundation\Testing\RefreshDatabase;
8+
use Tests\TestCase;
9+
10+
class PrivilegeEscalationTest extends TestCase
11+
{
12+
use RefreshDatabase;
13+
14+
/**
15+
* C1: Restarter cannot edit another user's profile info.
16+
*/
17+
public function test_restarter_cannot_edit_another_users_info(): void
18+
{
19+
$attacker = User::factory()->restarter()->create();
20+
$victim = User::factory()->restarter()->create();
21+
22+
$this->actingAs($attacker);
23+
24+
$response = $this->post('/profile/edit-info', [
25+
'id' => $victim->id,
26+
'email' => $victim->email,
27+
'name' => 'Hacked Name',
28+
'country' => $victim->country_code,
29+
'townCity' => $victim->location,
30+
'age' => $victim->age,
31+
'gender' => $victim->gender,
32+
'biography' => 'hacked',
33+
]);
34+
35+
$response->assertStatus(403);
36+
$this->assertNotEquals('Hacked Name', $victim->fresh()->name);
37+
}
38+
39+
/**
40+
* C1: Restarter cannot change another user's password.
41+
*/
42+
public function test_restarter_cannot_change_another_users_password(): void
43+
{
44+
$attacker = User::factory()->restarter()->create();
45+
$victim = User::factory()->restarter()->create();
46+
47+
$this->actingAs($attacker);
48+
49+
$response = $this->post('/profile/edit-password', [
50+
'id' => $victim->id,
51+
'current-password' => 'secret',
52+
'new-password' => 'hacked123',
53+
'new-password-repeat' => 'hacked123',
54+
]);
55+
56+
$response->assertStatus(403);
57+
}
58+
59+
/**
60+
* C1: Restarter cannot change another user's photo.
61+
*/
62+
public function test_restarter_cannot_change_another_users_photo(): void
63+
{
64+
$attacker = User::factory()->restarter()->create();
65+
$victim = User::factory()->restarter()->create();
66+
67+
$this->actingAs($attacker);
68+
69+
$response = $this->post('/profile/edit-photo', [
70+
'id' => $victim->id,
71+
]);
72+
73+
$response->assertStatus(403);
74+
}
75+
76+
/**
77+
* C1: Restarter cannot access admin edit settings.
78+
*/
79+
public function test_restarter_cannot_access_admin_edit_settings(): void
80+
{
81+
$attacker = User::factory()->restarter()->create();
82+
83+
$this->actingAs($attacker);
84+
85+
$response = $this->post('/profile/edit-admin-settings', [
86+
'id' => $attacker->id,
87+
'user_role' => Role::ROOT,
88+
]);
89+
90+
$response->assertStatus(403);
91+
$this->assertEquals(Role::RESTARTER, $attacker->fresh()->role);
92+
}
93+
94+
/**
95+
* C1 positive: Admin CAN change role via admin edit settings.
96+
*/
97+
public function test_admin_can_change_role_via_admin_edit(): void
98+
{
99+
$admin = User::factory()->administrator()->create();
100+
$user = User::factory()->restarter()->create();
101+
102+
$this->actingAs($admin);
103+
104+
$response = $this->post('/profile/edit-admin-settings', [
105+
'id' => $user->id,
106+
'user_role' => Role::HOST,
107+
'assigned_groups' => [],
108+
'preferences' => [],
109+
'permissions' => [],
110+
]);
111+
112+
$response->assertSessionHas('message');
113+
$this->assertEquals(Role::HOST, $user->fresh()->role);
114+
}
115+
116+
/**
117+
* C1 positive: Admin CAN edit another user's info.
118+
*/
119+
public function test_admin_can_edit_another_users_info(): void
120+
{
121+
$admin = User::factory()->administrator()->create();
122+
$user = User::factory()->restarter()->create();
123+
124+
$this->actingAs($admin);
125+
126+
$response = $this->post('/profile/edit-info', [
127+
'id' => $user->id,
128+
'email' => $user->email,
129+
'name' => 'Updated By Admin',
130+
'country' => $user->country_code,
131+
'townCity' => $user->location,
132+
'age' => $user->age,
133+
'gender' => $user->gender,
134+
'biography' => $user->biography,
135+
]);
136+
137+
$response->assertRedirect();
138+
$this->assertEquals('Updated By Admin', $user->fresh()->name);
139+
}
140+
141+
/**
142+
* C2/M1: User cannot escalate role via /user/edit endpoint.
143+
*/
144+
public function test_user_cannot_escalate_role_via_edit_endpoint(): void
145+
{
146+
$admin = User::factory()->administrator()->create();
147+
$user = User::factory()->restarter()->create();
148+
149+
$this->actingAs($admin);
150+
151+
$response = $this->post("/user/edit/{$user->id}", [
152+
'name' => $user->name,
153+
'email' => $user->email,
154+
'role' => Role::ROOT,
155+
]);
156+
157+
$this->assertNotEquals(Role::ROOT, $user->fresh()->role);
158+
}
159+
160+
/**
161+
* C2/M1: User cannot overwrite api_token via /user/edit endpoint.
162+
*/
163+
public function test_user_cannot_overwrite_api_token_via_edit_endpoint(): void
164+
{
165+
$admin = User::factory()->administrator()->create();
166+
$user = User::factory()->restarter()->create();
167+
$originalToken = $user->api_token;
168+
169+
$this->actingAs($admin);
170+
171+
$response = $this->post("/user/edit/{$user->id}", [
172+
'name' => $user->name,
173+
'email' => $user->email,
174+
'api_token' => 'stolen_token_value',
175+
]);
176+
177+
$this->assertEquals($originalToken, $user->fresh()->api_token);
178+
}
179+
}

0 commit comments

Comments
 (0)