Skip to content

Commit 0c6e64f

Browse files
authored
Merge commit from fork
(security) Fix: Privilege Escalation Vulnerability in reNgine
2 parents b77d1e0 + fb2b59d commit 0c6e64f

File tree

6 files changed

+73
-7
lines changed

6 files changed

+73
-7
lines changed

web/api/permissions.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
from rest_framework.permissions import BasePermission
2+
from rest_framework.exceptions import PermissionDenied
3+
from rolepermissions.checkers import has_permission
4+
5+
class HasPermission(BasePermission):
6+
"""
7+
This is a custom permission class for DRF that checks if the user
8+
has the required permission.
9+
Usage in drf views:
10+
permission_classes = [HasPermission]
11+
permission_required = PERM_MODIFY_SCAN_CONFIGURATIONS
12+
"""
13+
14+
def has_permission(self, request, view):
15+
permission_code = getattr(view, 'permission_required', None)
16+
if not permission_code:
17+
raise PermissionDenied(detail="Permission is not specified for this view.")
18+
19+
if not has_permission(request.user, permission_code):
20+
raise PermissionDenied(detail="This user does not have enough permissions")
21+
return True

web/api/views.py

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
from django.core.exceptions import ObjectDoesNotExist
2020
from django.core.cache import cache
2121

22-
2322
from dashboard.models import *
2423
from recon_note.models import *
2524
from reNgine.celery import app
@@ -34,7 +33,8 @@
3433
from startScan.models import EndPoint
3534
from targetApp.models import *
3635
from api.shared_api_tasks import import_hackerone_programs_task, sync_bookmarked_programs_task
37-
from .serializers import *
36+
from api.permissions import *
37+
from api.serializers import *
3838

3939

4040
logger = logging.getLogger(__name__)
@@ -333,6 +333,9 @@ def clear_all(self, request):
333333

334334

335335
class OllamaManager(APIView):
336+
permission_classes = [HasPermission]
337+
permission_required = PERM_MODIFY_SYSTEM_CONFIGURATIONS
338+
336339
def get(self, request):
337340
"""
338341
API to download Ollama Models
@@ -474,6 +477,9 @@ def get(self, request):
474477

475478

476479
class CreateProjectApi(APIView):
480+
permission_classes = [HasPermission]
481+
permission_required = PERM_MODIFY_TARGETS
482+
477483
def get(self, request):
478484
req = self.request
479485
project_name = req.query_params.get('name')
@@ -915,6 +921,9 @@ def post(self, request):
915921

916922

917923
class AddTarget(APIView):
924+
permission_classes = [HasPermission]
925+
permission_required = PERM_MODIFY_TARGETS
926+
918927
def post(self, request):
919928
req = self.request
920929
data = req.data
@@ -1050,6 +1059,9 @@ def post(self, request):
10501059

10511060

10521061
class DeleteMultipleRows(APIView):
1062+
permission_classes = [HasPermission]
1063+
permission_required = PERM_MODIFY_TARGETS
1064+
10531065
def post(self, request):
10541066
req = self.request
10551067
data = req.data
@@ -1069,6 +1081,9 @@ def post(self, request):
10691081

10701082

10711083
class StopScan(APIView):
1084+
permission_classes = [HasPermission]
1085+
permission_required = PERM_INITATE_SCANS_SUBSCANS
1086+
10721087
def post(self, request):
10731088
req = self.request
10741089
data = req.data
@@ -1166,6 +1181,9 @@ def abort_subscan(subscan):
11661181

11671182

11681183
class InitiateSubTask(APIView):
1184+
permission_classes = [HasPermission]
1185+
permission_required = PERM_INITATE_SCANS_SUBSCANS
1186+
11691187
def post(self, request):
11701188
req = self.request
11711189
data = req.data
@@ -1185,6 +1203,9 @@ def post(self, request):
11851203

11861204

11871205
class DeleteSubdomain(APIView):
1206+
permission_classes = [HasPermission]
1207+
permission_required = PERM_MODIFY_SCAN_RESULTS
1208+
11881209
def post(self, request):
11891210
req = self.request
11901211
for id in req.data['subdomain_ids']:
@@ -1193,6 +1214,9 @@ def post(self, request):
11931214

11941215

11951216
class DeleteVulnerability(APIView):
1217+
permission_classes = [HasPermission]
1218+
permission_required = PERM_MODIFY_SCAN_RESULTS
1219+
11961220
def post(self, request):
11971221
req = self.request
11981222
for id in req.data['vulnerability_ids']:
@@ -1262,6 +1286,9 @@ def get(self, request):
12621286

12631287

12641288
class UninstallTool(APIView):
1289+
permission_classes = [HasPermission]
1290+
permission_required = PERM_MODIFY_SYSTEM_CONFIGURATIONS
1291+
12651292
def get(self, request):
12661293
req = self.request
12671294
tool_id = req.query_params.get('tool_id')
@@ -1300,6 +1327,9 @@ def get(self, request):
13001327

13011328

13021329
class UpdateTool(APIView):
1330+
permission_classes = [HasPermission]
1331+
permission_required = PERM_MODIFY_SYSTEM_CONFIGURATIONS
1332+
13031333
def get(self, request):
13041334
req = self.request
13051335
tool_id = req.query_params.get('tool_id')
@@ -1332,6 +1362,9 @@ def get(self, request):
13321362
return Response({'status': False, 'message': str(e)})
13331363

13341364
class GetExternalToolCurrentVersion(APIView):
1365+
permission_classes = [HasPermission]
1366+
permission_required = PERM_MODIFY_SYSTEM_CONFIGURATIONS
1367+
13351368
def get(self, request):
13361369
req = self.request
13371370
# toolname is also the command
@@ -1368,6 +1401,9 @@ def get(self, request):
13681401

13691402

13701403
class GithubToolCheckGetLatestRelease(APIView):
1404+
permission_classes = [HasPermission]
1405+
permission_required = PERM_MODIFY_SYSTEM_CONFIGURATIONS
1406+
13711407
def get(self, request):
13721408
req = self.request
13731409

web/dashboard/templates/dashboard/projects.html

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
{% extends 'base/base.html' %}
22
{% load humanize %}
33
{% load static %}
4+
{% load permission_tags %}
5+
46

57
{% block title %}
68
Projects
@@ -49,7 +51,11 @@ <h5 class="m-0 fw-normal">{{project.name}}</h5>
4951
{% if current_project.slug == project.slug %}
5052
<span class="badge bg-info text-white">Current Project cannot be deleted.</span>
5153
{% else %}
52-
<a href="#" onclick="delete_project({{project.id}}, '{{project.name}}')" class="btn btn-xs btn-danger"><i class="mdi mdi-trash-can-outline"></i></a>
54+
{% if request.user|can:'modify_targets' %}
55+
<a href="#" onclick="delete_project({{project.id}}, '{{project.name}}')" class="btn btn-xs btn-danger"><i class="mdi mdi-trash-can-outline"></i></a>
56+
{% else %}
57+
<button class="btn btn-xs btn-danger" disabled data-toggle="tooltip" title="Not enough permission"><i class="mdi mdi-trash-can-outline"></i></button>
58+
{% endif %}
5359
{% endif %}
5460
</td>
5561
</tr>
@@ -69,7 +75,7 @@ <h5 class="m-0 fw-normal">{{project.name}}</h5>
6975
function delete_project(id, project_name){
7076
const delAPI = "../../delete/project/" + id;
7177
swal.queue([{
72-
title: 'Are you sure you want to delete '+project_name +'?',
78+
title: 'Are you sure you want to delete '+ project_name +'?',
7379
text: "You won't be able to revert this, all targets and scan results also will be deleted!",
7480
type: 'warning',
7581
showCancelButton: true,
@@ -94,7 +100,7 @@ <h5 class="m-0 fw-normal">{{project.name}}</h5>
94100
.catch(function() {
95101
swal.insertQueueStep({
96102
type: 'error',
97-
title: 'Oops! Unable to delete the target!'
103+
title: 'Oops! Unable to delete the project!'
98104
})
99105
})
100106
}

web/dashboard/views.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,7 @@ def projects(request, slug):
295295
return render(request, 'dashboard/projects.html', context)
296296

297297

298+
@has_permission_decorator(PERM_MODIFY_TARGETS, redirect_url=FOUR_OH_FOUR_URL)
298299
def delete_project(request, id):
299300
obj = get_object_or_404(Project, id=id)
300301
if request.method == "POST":

web/reNgine/definitions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,7 @@
442442
# Roles and Permissions
443443
PERM_MODIFY_SYSTEM_CONFIGURATIONS = 'modify_system_configurations'
444444
PERM_MODIFY_SCAN_CONFIGURATIONS = 'modify_scan_configurations'
445-
PERM_MODIFY_TARGETS = 'modify_targets'
445+
PERM_MODIFY_TARGETS = 'modify_targets' # projects and targets
446446
PERM_MODIFY_SCAN_RESULTS = 'modify_scan_results'
447447
PERM_MODIFY_WORDLISTS = 'modify_wordlists'
448448
PERM_MODIFY_INTERESTING_LOOKUP = 'modify_interesting_lookup'

web/templates/base/_items/top_bar.html

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@ <h5 class="text-overflow mb-2">Search History</h5>
3535
</a>
3636
{% endfor %}
3737
<div class="dropdown-divider"></div>
38-
<a href="#" onclick="add_project_modal()" class="dropdown-item"><i class="mdi mdi-account-plus"></i> Create New Project</a>
38+
{% if request.user|can:'modify_targets' %}
39+
<a href="#" onclick="add_project_modal()" class="dropdown-item"><i class="mdi mdi-account-plus"></i> Create New Project</a>
40+
{% endif %}
3941
</div>
4042
</li>
4143
{% if user|can:'modify_targets' or user|can:'modify_scan_configurations' or user|can:'modify_system_configurations' or user|can:'modify_wordlists' %}

0 commit comments

Comments
 (0)