diff --git a/web/api/serializers.py b/web/api/serializers.py
index bf4d1a28..6bf15711 100644
--- a/web/api/serializers.py
+++ b/web/api/serializers.py
@@ -7,6 +7,19 @@ from scanEngine.models import *
from django.db.models import F, JSONField, Value
+class OnlySubdomainNameSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = Subdomain
+ fields = ['name', 'id']
+
+
+class ScanHistorySerializer(serializers.ModelSerializer):
+ class Meta:
+ model = ScanHistory
+ fields = '__all__'
+ depth = 1
+
+
class OrganizationSerializer(serializers.ModelSerializer):
class Meta:
diff --git a/web/api/urls.py b/web/api/urls.py
index ce7d9f07..8baa76ce 100644
--- a/web/api/urls.py
+++ b/web/api/urls.py
@@ -6,9 +6,9 @@ from .views import *
app_name = 'api'
router = routers.DefaultRouter()
-router.register(r'scanHistory', SubdomainViewset)
+router.register(r'listDatatableSubdomain', SubdomainDatatableViewSet)
-router.register(r'listSubdomains', ListSubdomainsViewSet)
+router.register(r'listSubdomains', SubdomainsViewSet)
router.register(r'listEndpoints', EndPointViewSet)
@@ -44,6 +44,7 @@ urlpatterns = [
path('queryTargetsInOrganization/', ListTargetsInOrganization.as_view(), name='queryTargetsInOrganization'),
path('listOrganizations/', ListOrganizations.as_view(), name='listOrganizations'),
path('listEngines/', ListEngines.as_view(), name='listEngines'),
+ path('listScanHistory/', ListScanHistory.as_view(), name='listScanHistory'),
]
urlpatterns += router.urls
diff --git a/web/api/views.py b/web/api/views.py
index ce3da009..a9941470 100644
--- a/web/api/views.py
+++ b/web/api/views.py
@@ -17,6 +17,14 @@ from startScan.models import *
from targetApp.models import *
+class ListScanHistory(APIView):
+ def get(self, request, format=None):
+ req = self.request
+ scan_history = ScanHistory.objects.all().order_by('-start_scan_date')
+ scan_history = ScanHistorySerializer(scan_history, many=True)
+ return Response({'scan_histories': scan_history.data})
+
+
class ListEngines(APIView):
def get(self, request, format=None):
req = self.request
@@ -207,27 +215,25 @@ class ListSubdomains(APIView):
ip_address = req.query_params.get('ip_address')
port = req.query_params.get('port')
tech = req.query_params.get('tech')
- if scan_id and ip_address:
- subdomain = Subdomain.objects.filter(
- ip_addresses__address=ip_address).filter(
- scan_history__id=scan_id)
- serializer = SubdomainSerializer(subdomain, many=True)
- return Response({"subdomains": serializer.data})
- elif scan_id and tech:
- subdomain = Subdomain.objects.filter(
- technologies__name=tech).filter(
- scan_history__id=scan_id)
- serializer = SubdomainSerializer(subdomain, many=True)
- return Response({"subdomains": serializer.data})
- elif scan_id and port:
- subdomain = Subdomain.objects.filter(
+ subdomain_query = Subdomain.objects.filter(scan_history__id=scan_id)
+
+ if ip_address:
+ subdomain_query = subdomain_query.filter(ip_addresses__address=ip_address)
+
+ if tech:
+ subdomain_query = subdomain_query.filter(technologies__name=tech)
+
+ if port:
+ subdomain_query = subdomain_query.filter(
ip_addresses__in=IpAddress.objects.filter(
ports__in=Port.objects.filter(
- number=port))).filter(
- scan_history=scan_id)
- serializer = SubdomainSerializer(subdomain, many=True)
- return Response({"subdomains": serializer.data})
+ number=port)))
+ if 'no_lookup_interesting' in req.query_params:
+ serializer = OnlySubdomainNameSerializer(subdomain_query, many=True)
+ else:
+ serializer = SubdomainSerializer(subdomain_query, many=True)
+ return Response({"subdomains": serializer.data})
class ListOsintUsers(APIView):
def get(self, request, format=None):
@@ -299,7 +305,7 @@ class IpAddressViewSet(viewsets.ModelViewSet):
queryset, self.request, view=self)
-class ListSubdomainsViewSet(viewsets.ModelViewSet):
+class SubdomainsViewSet(viewsets.ModelViewSet):
queryset = Subdomain.objects.none()
serializer_class = SubdomainSerializer
@@ -500,7 +506,7 @@ class InterestingEndpointViewSet(viewsets.ModelViewSet):
queryset, self.request, view=self)
-class SubdomainViewset(viewsets.ModelViewSet):
+class SubdomainDatatableViewSet(viewsets.ModelViewSet):
queryset = Subdomain.objects.none()
serializer_class = SubdomainSerializer
diff --git a/web/reNgine/settings.py b/web/reNgine/settings.py
index e4bcbab4..92364eaf 100644
--- a/web/reNgine/settings.py
+++ b/web/reNgine/settings.py
@@ -33,6 +33,7 @@ INSTALLED_APPS = [
'targetApp.apps.TargetappConfig',
'scanEngine.apps.ScanengineConfig',
'startScan.apps.StartscanConfig',
+ 'recon_note.apps.ReconNoteConfig',
'django_ace',
'django_celery_beat',
'mathfilters',
diff --git a/web/recon_note/__init__.py b/web/recon_note/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/web/recon_note/admin.py b/web/recon_note/admin.py
new file mode 100644
index 00000000..5f4b6b71
--- /dev/null
+++ b/web/recon_note/admin.py
@@ -0,0 +1,4 @@
+from django.contrib import admin
+from recon_note.models import *
+
+admin.site.register(TodoNote)
diff --git a/web/recon_note/apps.py b/web/recon_note/apps.py
new file mode 100644
index 00000000..951dfce1
--- /dev/null
+++ b/web/recon_note/apps.py
@@ -0,0 +1,6 @@
+from django.apps import AppConfig
+
+
+class ReconNoteConfig(AppConfig):
+ default_auto_field = 'django.db.models.BigAutoField'
+ name = 'recon_note'
diff --git a/web/recon_note/migrations/0001_initial.py b/web/recon_note/migrations/0001_initial.py
new file mode 100644
index 00000000..06a4c4cf
--- /dev/null
+++ b/web/recon_note/migrations/0001_initial.py
@@ -0,0 +1,26 @@
+# Generated by Django 3.2.4 on 2021-07-22 06:09
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ('startScan', '0058_delete_todonote'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='TodoNote',
+ fields=[
+ ('id', models.AutoField(primary_key=True, serialize=False)),
+ ('title', models.CharField(blank=True, max_length=1000, null=True)),
+ ('description', models.TextField(blank=True, null=True)),
+ ('scan_history', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='startScan.scanhistory')),
+ ('subdomain', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='startScan.subdomain')),
+ ],
+ ),
+ ]
diff --git a/web/recon_note/migrations/0002_auto_20210722_0611.py b/web/recon_note/migrations/0002_auto_20210722_0611.py
new file mode 100644
index 00000000..ed83df47
--- /dev/null
+++ b/web/recon_note/migrations/0002_auto_20210722_0611.py
@@ -0,0 +1,23 @@
+# Generated by Django 3.2.4 on 2021-07-22 06:11
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('recon_note', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='todonote',
+ name='is_done',
+ field=models.BooleanField(default=False),
+ ),
+ migrations.AddField(
+ model_name='todonote',
+ name='is_important',
+ field=models.BooleanField(default=False),
+ ),
+ ]
diff --git a/web/recon_note/migrations/__init__.py b/web/recon_note/migrations/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/web/recon_note/models.py b/web/recon_note/models.py
new file mode 100644
index 00000000..f80f63f2
--- /dev/null
+++ b/web/recon_note/models.py
@@ -0,0 +1,21 @@
+from django.db import models
+from startScan.models import *
+
+class TodoNote(models.Model):
+ id = models.AutoField(primary_key=True)
+ title = models.CharField(max_length=1000, null=True, blank=True)
+ description = models.TextField(null=True, blank=True)
+ scan_history = models.ForeignKey(
+ ScanHistory,
+ on_delete=models.CASCADE,
+ null=True,
+ blank=True
+ )
+ subdomain = models.ForeignKey(
+ Subdomain,
+ on_delete=models.CASCADE,
+ null=True,
+ blank=True
+ )
+ is_done = models.BooleanField(default=False)
+ is_important = models.BooleanField(default=False)
diff --git a/web/recon_note/tests.py b/web/recon_note/tests.py
new file mode 100644
index 00000000..7ce503c2
--- /dev/null
+++ b/web/recon_note/tests.py
@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.
diff --git a/web/recon_note/views.py b/web/recon_note/views.py
new file mode 100644
index 00000000..91ea44a2
--- /dev/null
+++ b/web/recon_note/views.py
@@ -0,0 +1,3 @@
+from django.shortcuts import render
+
+# Create your views here.
diff --git a/web/scanEngine/models.py b/web/scanEngine/models.py
index c5c46800..d6f58d6e 100644
--- a/web/scanEngine/models.py
+++ b/web/scanEngine/models.py
@@ -1,6 +1,5 @@
from django.db import models
-
class EngineType(models.Model):
id = models.AutoField(primary_key=True)
engine_name = models.CharField(max_length=200)
diff --git a/web/startScan/migrations/0057_todonote.py b/web/startScan/migrations/0057_todonote.py
new file mode 100644
index 00000000..763178d0
--- /dev/null
+++ b/web/startScan/migrations/0057_todonote.py
@@ -0,0 +1,24 @@
+# Generated by Django 3.2.4 on 2021-07-22 05:59
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('startScan', '0056_email_password'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='TodoNote',
+ fields=[
+ ('id', models.AutoField(primary_key=True, serialize=False)),
+ ('title', models.CharField(blank=True, max_length=1000, null=True)),
+ ('description', models.TextField(blank=True, null=True)),
+ ('scan_history', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='startScan.scanhistory')),
+ ('subdomain', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='startScan.subdomain')),
+ ],
+ ),
+ ]
diff --git a/web/startScan/migrations/0058_delete_todonote.py b/web/startScan/migrations/0058_delete_todonote.py
new file mode 100644
index 00000000..64317842
--- /dev/null
+++ b/web/startScan/migrations/0058_delete_todonote.py
@@ -0,0 +1,16 @@
+# Generated by Django 3.2.4 on 2021-07-22 06:04
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('startScan', '0057_todonote'),
+ ]
+
+ operations = [
+ migrations.DeleteModel(
+ name='TodoNote',
+ ),
+ ]
diff --git a/web/startScan/templates/startScan/detail_scan.html b/web/startScan/templates/startScan/detail_scan.html
index 05028dae..d250691f 100644
--- a/web/startScan/templates/startScan/detail_scan.html
+++ b/web/startScan/templates/startScan/detail_scan.html
@@ -879,7 +879,7 @@ Detailed Scan Results for {{history.domain.name}}
"lengthMenu": [20, 50, 100, 500, 1000],
"pageLength": 20,
'serverSide': true,
- "ajax": '/api/scanHistory/?scan_id={{scan_history_id}}&format=datatables',
+ "ajax": '/api/listDatatableSubdomain/?scan_id={{scan_history_id}}&format=datatables',
"order": [[ 8, "desc" ]],
"columns": [
{'data': 'id'},
diff --git a/web/targetApp/static/targetApp/js/todo.js b/web/targetApp/static/targetApp/js/todo.js
index 5cffec8a..6d515ebc 100644
--- a/web/targetApp/static/targetApp/js/todo.js
+++ b/web/targetApp/static/targetApp/js/todo.js
@@ -107,6 +107,9 @@ $('#addTask').on('click', function(event) {
const ps = new PerfectScrollbar('.todo-box-scroll', {
suppressScrollX : true
});
+
+ populateScanHistory();
+
});
const ps = new PerfectScrollbar('.todo-box-scroll', {
suppressScrollX : true
@@ -143,55 +146,18 @@ function importantDropdown() {
});
}
-function priorityDropdown() {
- $('.priority-dropdown .dropdown-menu .dropdown-item').on('click', function(event) {
-
- var getClass = $(this).attr('class').split(' ')[1];
- var getDropdownClass = $(this).parents('.p-dropdown').children('.dropdown-toggle').attr('class').split(' ')[1];
- $(this).parents('.p-dropdown').children('.dropdown-toggle').removeClass(getDropdownClass);
-
- $(this).parents('.p-dropdown').children('.dropdown-toggle').addClass(getClass);
- })
-}
-
-function editDropdown() {
- $('.action-dropdown .dropdown-menu .edit.dropdown-item').click(function() {
-
- event.preventDefault();
-
- var $_outerThis = $(this);
-
- $('.add-tsk').hide();
- $('.edit-tsk').show();
-
- var $_taskTitle = $_outerThis.parents('.todo-item').children().find('.todo-heading').text();
- var $_taskText = $_outerThis.parents('.todo-item').children().find('.todo-text').text();
-
- $('#task').val($_taskTitle);
- $('#taskdescription').val($_taskText);
-
- $('.edit-tsk').off('click').on('click', function(event) {
- var $_innerThis = $(this);
- var $_task = document.getElementById('task').value;
- var $_taskDescription = document.getElementById('taskdescription').value;
- var $_taskDescriptionText = document.getElementById('taskdescription').value;
- var $_taskEditedTitle = $_outerThis.parents('.todo-item').children().find('.todo-heading').html($_task);
- var $_taskEditedText = $_outerThis.parents('.todo-item').children().find('.todo-text').html($_taskDescriptionText);
- $('#addTaskModal').modal('hide');
- })
- $('#addTaskModal').modal('show');
- })
-}
-
function todoItem() {
$('.todo-item .todo-content').on('click', function(event) {
event.preventDefault();
var $_taskTitle = $(this).find('.todo-heading').text();
+
+ var $_taskTarget = $(this).find('.target').text();
+
var $todoDescription = $(this).find('.todo-text').text();
$('.task-heading').text($_taskTitle);
- $('.task-text').html($todoDescription);
+ $('.task-text').html(`${$_taskTarget}
` + $todoDescription);
$('#todoShowListItem').modal('show');
});
@@ -210,8 +176,6 @@ var $btns = $('.list-actions').click(function() {
checkCheckbox();
importantDropdown();
-priorityDropdown();
-editDropdown();
todoItem();
$(".add-tsk").click(function(){
@@ -220,6 +184,20 @@ $(".add-tsk").click(function(){
var $_taskDescriptionText = document.getElementById('taskdescription').value;
+ var $_taskScanHistory = $("#scanHistoryIDropdown option:selected").text();
+
+ var $_taskSubdomain = $("#subdomainDropdown option:selected").text();
+
+ var $_targetText = '';
+
+ if ($_taskScanHistory != 'Choose Scan History...') {
+ $_targetText = $_taskScanHistory;
+ }
+
+ if ($_taskSubdomain != 'Choose Subdomain...') {
+ $_targetText += ' Subdomain : ' + $_taskSubdomain;
+ }
+
$html = '
'+$_targetText+''+ "
"+$_taskDescriptionText+"
"+ 'Target: example.com
+Domain: example.com, Scanned 2 hours ago, Subdomain: hello.ns.hackerone.com
Need to identify documentation page, use xyz wordlist and start dir bruteforce.