Skip to content

Commit

Permalink
Merge branch 'release/2.1.1' into fix/259-nuclei-scan
Browse files Browse the repository at this point in the history
  • Loading branch information
psyray committed Feb 12, 2025
2 parents e023685 + 900b2d6 commit 28de22c
Show file tree
Hide file tree
Showing 21 changed files with 1,169 additions and 578 deletions.
102 changes: 58 additions & 44 deletions web/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -272,27 +272,6 @@ def get_description(self, vulnerability):
return vulnerability.name


class VisualisePortSerializer(serializers.ModelSerializer):

description = serializers.SerializerMethodField('get_description')
title = serializers.SerializerMethodField('get_title')

class Meta:
model = Port
fields = [
'description',
'is_uncommon',
'title',
]

def get_description(self, port):
return str(port.number) + "/" + str(port.service_name)

def get_title(self, port):
if port.is_uncommon:
return "Uncommon Port"


class VisualiseTechnologySerializer(serializers.ModelSerializer):

description = serializers.SerializerMethodField('get_description')
Expand All @@ -306,29 +285,41 @@ class Meta:
def get_description(self, tech):
return tech.name

class VisualisePortSerializer(serializers.ModelSerializer):
description = serializers.SerializerMethodField()
title = serializers.SerializerMethodField()
is_uncommon = serializers.SerializerMethodField()

class VisualiseIpSerializer(serializers.ModelSerializer):
class Meta:
model = Port
fields = ['description', 'title', 'is_uncommon']

description = serializers.SerializerMethodField('get_description')
children = serializers.SerializerMethodField('get_children')
def get_description(self, port):
return f"{port.number}/{port.service_name}/{port.service_name}"

class Meta:
model = IpAddress
fields = [
'description',
'children'
]
def get_title(self, port):
if port.is_uncommon:
return "Uncommon Port"
return "Port"

def get_description(self, Ip):
return Ip.address
def get_is_uncommon(self, port):
return port.is_uncommon

def get_children(self, ip):
port = Port.objects.filter(
ports__in=IpAddress.objects.filter(
address=ip))
serializer = VisualisePortSerializer(port, many=True)
return serializer.data
class VisualiseIpSerializer(serializers.ModelSerializer):
description = serializers.SerializerMethodField('get_description')
children = serializers.SerializerMethodField('get_children')

class Meta:
model = IpAddress
fields = ['description', 'children']

def get_description(self, ip):
return ip.address

def get_children(self, ip):
ports = ip.ports.all()
serializer = VisualisePortSerializer(ports, many=True)
return serializer.data

class VisualiseEndpointSerializer(serializers.ModelSerializer):

Expand Down Expand Up @@ -376,7 +367,11 @@ def get_children(self, subdomain_name):
)

ips = IpAddress.objects.filter(ip_addresses__in=subdomains)
ip_serializer = VisualiseIpSerializer(ips, many=True)
ip_serializer = VisualiseIpSerializer(
ips,
many=True,
context={'scan_id': scan_history.id}
)

# endpoint = EndPoint.objects.filter(
# scan_history=self.context.get('scan_history')).filter(
Expand Down Expand Up @@ -816,12 +811,31 @@ class Meta:


class IpSerializer(serializers.ModelSerializer):
ports = PortSerializer(many=True)
subdomain_count = serializers.SerializerMethodField()
subdomain_names = serializers.SerializerMethodField()

ports = PortSerializer(many=True)

class Meta:
model = IpAddress
fields = '__all__'
class Meta:
model = IpAddress
fields = '__all__'

def get_base_subdomain_query(self, obj):
query = Subdomain.objects.filter(ip_addresses=obj)
scan_id = self.context.get('scan_id')
target_id = self.context.get('target_id')

if scan_id:
query = query.filter(scan_history_id=scan_id)
elif target_id:
query = query.filter(target_domain_id=target_id)

return query.distinct('name')

def get_subdomain_count(self, obj):
return self.get_base_subdomain_query(obj).count()

def get_subdomain_names(self, obj):
return list(self.get_base_subdomain_query(obj).values_list('name', flat=True))


class DirectoryFileSerializer(serializers.ModelSerializer):
Expand Down
8 changes: 8 additions & 0 deletions web/api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@
'queryIps/',
ListIPs.as_view(),
name='listIPs'),
path(
'queryIp/',
GetIpDetails.as_view(),
name='getIpDetails'),
path(
'queryInterestingSubdomains/',
QueryInterestingSubdomains.as_view(),
Expand Down Expand Up @@ -243,6 +247,10 @@
'action/create/project',
CreateProjectApi.as_view(),
name='create_project'),
path(
'uncommon-web-ports/',
UncommonWebPortsView.as_view(),
name='uncommonWebPorts'),
]

urlpatterns += router.urls
135 changes: 100 additions & 35 deletions web/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,11 @@ def get(self, request):
})

ip_addrs = subdomain.ip_addresses.all()
open_ports = ', '.join(f'{port.number}/{port.service_name}' for ip in ip_addrs for port in ip.ports.all())
open_ports = ', '.join(
f'{port.number}/{port.service_name}'
for ip in ip_addrs
for port in ip.ports.all()
)
tech_used = ', '.join(tech.name for tech in subdomain.technologies.all())

input_data = f'''
Expand Down Expand Up @@ -507,14 +511,14 @@ def post(self, request):
.exclude(vuln_count=0)[:limit]
)

if most_vulnerable_subdomains:
response['status'] = True
response['result'] = (
SubdomainSerializer(
most_vulnerable_subdomains,
many=True)
.data
)
if most_vulnerable_subdomains:
response['status'] = True
response['result'] = (
SubdomainSerializer(
most_vulnerable_subdomains,
many=True)
.data
)

elif target_id:
subdomain_query = subdomains.filter(target_domain__id=target_id)
Expand Down Expand Up @@ -1583,32 +1587,42 @@ def get(self, request, format=None):


class ListPorts(APIView):
def get(self, request, format=None):
req = self.request
scan_id = safe_int_cast(req.query_params.get('scan_id'))
target_id = safe_int_cast(req.query_params.get('target_id'))
ip_address = req.query_params.get('ip_address')
def get(self, request, format=None):
req = self.request
scan_id = safe_int_cast(req.query_params.get('scan_id'))
target_id = safe_int_cast(req.query_params.get('target_id'))
ip_address = req.query_params.get('ip_address')

if target_id:
port = Port.objects.filter(
ports__in=IpAddress.objects.filter(
ip_addresses__in=Subdomain.objects.filter(
target_domain__id=target_id))).distinct()
elif scan_id:
port = Port.objects.filter(
ports__in=IpAddress.objects.filter(
ip_addresses__in=Subdomain.objects.filter(
scan_history__id=scan_id))).distinct()
else:
port = Port.objects.filter(
ports__in=IpAddress.objects.filter(
ip_addresses__in=Subdomain.objects.all())).distinct()
# Build the base query
port_query = Port.objects.all()

if ip_address:
port = port.filter(ports__address=ip_address).distinct()
# Filter based on parameters
if target_id:
port_query = port_query.filter(
ip_address__ip_addresses__target_domain__id=target_id
)
elif scan_id:
port_query = port_query.filter(
ip_address__ip_addresses__scan_history__id=scan_id
)

if ip_address:
port_query = port_query.filter(
ip_address__address=ip_address
)

serializer = PortSerializer(port, many=True)
return Response({"ports": serializer.data})
# Grouping information
ports_data = []
ports_data.extend(
{
'number': port.number,
'service_name': port.service_name,
'description': port.description,
'is_uncommon': port.is_uncommon,
}
for port in port_query.distinct()
)
return Response({"ports": ports_data})


class ListSubdomains(APIView):
Expand Down Expand Up @@ -1638,9 +1652,8 @@ def get(self, request, format=None):

if port:
subdomain_query = subdomain_query.filter(
ip_addresses__in=IpAddress.objects.filter(
ports__in=Port.objects.filter(
number=port)))
ip_addresses__ports__number=port
).distinct('name')

if 'only_important' in req.query_params:
subdomain_query = subdomain_query.filter(is_important=True)
Expand Down Expand Up @@ -2052,6 +2065,12 @@ def get_queryset(self):
if name:
self.queryset = self.queryset.filter(name=name)

# Prefetching necessary relations for get_ports_by_ip
self.queryset = self.queryset.prefetch_related(
'ip_addresses',
'ip_addresses__ports',
)

return self.queryset

def filter_queryset(self, qs):
Expand Down Expand Up @@ -2891,3 +2910,49 @@ def special_lookup(self, search_value):
print(e)

return qs

class GetIpDetails(APIView):
def get(self, request, format=None):
req = self.request
ip_address = req.query_params.get('ip_address')
scan_id = safe_int_cast(req.query_params.get('scan_id'))
target_id = safe_int_cast(req.query_params.get('target_id'))

if not ip_address:
return Response({"error": "IP address is required"}, status=400)

# Build the base query
ip_query = IpAddress.objects.filter(address=ip_address)

if scan_id:
ip_query = ip_query.filter(
ip_addresses__scan_history__id=scan_id
)
elif target_id:
ip_query = ip_query.filter(
ip_addresses__target_domain__id=target_id
)

# Preloading relations to optimize performance
ip_query = ip_query.prefetch_related(
'ports',
'ip_addresses',
).distinct()


if not ip_query.exists():
return Response({"error": "IP not found"}, status=404)

serializer = IpSerializer(
ip_query.first(),
context={'scan_id': scan_id}
)
return Response(serializer.data)

class UncommonWebPortsView(APIView):
def get(self, request):
from reNgine.definitions import UNCOMMON_WEB_PORTS
return Response({
'uncommon_web_ports': UNCOMMON_WEB_PORTS,
'common_web_ports': [80, 443]
})
12 changes: 10 additions & 2 deletions web/dashboard/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,16 @@ def index(request, slug):
ip_addresses = IpAddress.objects.filter(ip_addresses__in=subdomains)

context['total_ips'] = ip_addresses.count()
context['most_used_port'] = Port.objects.filter(ports__in=ip_addresses).annotate(count=Count('ports')).order_by('-count')[:7]
context['most_used_ip'] = ip_addresses.annotate(count=Count('ip_addresses')).order_by('-count').exclude(ip_addresses__isnull=True)[:7]
context['most_used_port'] = Port.objects.filter(
ports__in=ip_addresses
).annotate(
count=Count('ports')
).order_by('-count')[:7]
context['most_used_ip'] = ip_addresses.annotate(
count=Count('ip_addresses')
).order_by('-count').exclude(
ip_addresses__isnull=True
)[:7]
context['most_used_tech'] = Technology.objects.filter(technologies__in=subdomains).annotate(count=Count('technologies')).order_by('-count')[:7]

context['most_common_cve'] = CveId.objects.filter(cve_ids__in=vulnerabilities).annotate(nused=Count('cve_ids')).order_by('-nused').values('name', 'nused')[:7]
Expand Down
Loading

0 comments on commit 28de22c

Please sign in to comment.