Skip to content

Commit

Permalink
Refactoring / FIX #144 #11 #22
Browse files Browse the repository at this point in the history
  • Loading branch information
Marius-Patrowl committed Jan 7, 2022
1 parent 1998c9b commit e3a70aa
Show file tree
Hide file tree
Showing 31 changed files with 2,585 additions and 1,531 deletions.
82 changes: 81 additions & 1 deletion backend_app/vpratings/apis.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
from .models import VPRating, VPR_METRICS
from .serializers import VPRatingSerializer
from .utils import _refresh_vprating, _calc_vprating

from datetime import datetime, date
from itertools import chain

class VPRatingSet(viewsets.ModelViewSet):
"""API endpoint that allows ratings to be viewed or edited."""
Expand All @@ -24,6 +25,85 @@ def get_vprating_metrics(self):
return JsonResponse(VPR_METRICS)


@api_view(['GET'])
@permission_classes([IsAuthenticated])
def get_vuln_vector(self, vuln_id):

vuln = get_object_or_404(Vuln, id=vuln_id)
try:
org_id = self.session.get('org_id', None)
org = organization.get_current_organization(user=self.user, org_id=org_id)
except Exception:
return JsonResponse("error: unable to get the organization", safe=False, status=500)

vector = ""
today_date = date.today()

# Vulnerability
vector = vector + vuln.cvss_vector

if vuln.is_confirmed is True:
vector += "/CL:Y"

if type(vuln.published) is datetime:
published_date = vuln.published.date()
delta = today_date - published_date
vector += "/VX:" + str(delta.days)

ea_metrics = ['unknown', 'private', 'public']
em_metrics = ['unknown', 'unproven', 'poc', 'functional']
et_metrics = ['unknown', 'low', 'medium', 'high', 'trusted']
ea_idx = ea_max_idx = 0
em_idx = em_max_idx = 0
et_idx = et_max_idx = 0
ex_max_days = 0

exploits = list(
chain(
vuln.exploitmetadata_set.all(),
vuln.orgexploitmetadata_set.filter(organization=org)
)
)

for exploit in exploits:
e = model_to_dict(exploit)

ea_idx = ea_metrics.index(e['availability'])
if ea_idx > ea_max_idx:
ea_max_idx = ea_idx

em_idx = em_metrics.index(e['maturity'])
if em_idx > em_max_idx:
em_max_idx = em_idx

et_idx = et_metrics.index(e['trust_level'])
if et_idx > et_max_idx:
et_max_idx = et_idx

if type(e['published']) is datetime:
published_date = e['published'].date()
delta_published_date = today_date - published_date
if delta_published_date.days > ex_max_days:
ex_max_days = delta_published_date.days

ea_vectors = ['X', 'R', 'U']
em_vectors = ['X', 'U', 'P', 'F']
et_vectors = ['X', 'L', 'M', 'H', 'H']

vector += "/EA:" + str(ea_vectors[ea_max_idx])
vector += "/EM:" + str(em_vectors[em_max_idx])
vector += "/ET:" + str(et_vectors[et_max_idx])
vector += "/EX:" + str(ex_max_days)

if vuln.is_in_the_news:
vector += "/N:Y"

if vuln.is_in_the_wild:
vector += "/W:Y"

return JsonResponse(vector, safe=False)


@api_view(['GET'])
@permission_classes([IsAuthenticated])
def get_vprating_by_cveid(self, cve_id):
Expand Down
1 change: 1 addition & 0 deletions backend_app/vpratings/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@
# path('calc/<int:vuln_id>', apis.refresh_vprating_by_id, name='refresh_vprating_by_id'),
path('metrics', apis.get_vprating_metrics, name='get_vprating_metrics'),
path('calc/<int:vuln_id>', apis.calc_vprating_by_vulnid, name='refresh_vprating_by_id'),
path('vector/<vuln_id>', apis.get_vuln_vector, name="get_vuln_vector"),
]
35 changes: 35 additions & 0 deletions backend_app/vulns/apis.py
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,40 @@ def export_vuln_sendmail(self, vuln_id):
"reason": "No valid email provided"}, safe=False)


@api_view(['GET'])
@permission_classes([IsAuthenticated])
def get_number_exploits_threats(self, vuln_id):
vuln = get_object_or_404(Vuln, id=vuln_id)
try:
org_id = self.session.get('org_id', None)
org = organization.get_current_organization(user=self.user, org_id=org_id)
except Exception:
return JsonResponse({
"status": "error",
"reason": "Unable to get the organization"}, safe=False, status=500)

# Get exploits
len_exploits = len(vuln.exploitmetadata_set.all())
# Get org exploits
len_org_exploits = len(vuln.orgexploitmetadata_set.filter(organization=org))
# Count exploits
exploit_count = len_exploits + len_org_exploits

# Get public threats
len_threats = len(vuln.threatmetadata_set.all())
# Get org threats
len_org_threats = len(vuln.orgthreatmetadata_set.filter(organization=org))
# Count threats
threat_count = len_org_threats + len_threats

res = {
"count_threat": threat_count,
"count_exploit": exploit_count
}

return JsonResponse(res, safe=False)


@api_view(['GET'])
@permission_classes([IsAuthenticated])
def get_exploits(self, vuln_id):
Expand Down Expand Up @@ -599,6 +633,7 @@ def get_threats(self, vuln_id):
t = model_to_dict(threat)
t['scope'] = 'private'
res.append(t)

return JsonResponse(res, safe=False)


Expand Down
1 change: 1 addition & 0 deletions backend_app/vulns/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
path('<vuln_id>/refresh_score', apis.refresh_vuln_score, name='refresh_vuln_score'),
path('<vuln_id>/history', apis.get_vuln_history, name='get_vuln_history'),
path('<vuln_id>/cpes', apis.get_vuln_cpes, name='get_vuln_cpes'),
path('<vuln_id>/counter', apis.get_number_exploits_threats, name='get_number_exploits_threats'),
path('<vuln_id>/exploits', apis.get_exploits, name='get_exploits'),
path('<vuln_id>/exploits/add', apis.add_exploit, name='add_exploit'),
path('<vuln_id>/exploits/edit', apis.edit_exploit, name='edit_exploit'),
Expand Down
7 changes: 7 additions & 0 deletions frontend/src/common/colors.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ export default {
} else {
return 'grey';
}
},
getNumberColor(number) {
if ( number > 0 ){
return "deep-orange";
} else {
return "grey"
}
}
},
mounted() {
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/pages/Homepage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ export default {
},
viewVuln(item) {
this.$router.push({ 'name': 'VulnDetails', 'params': { 'vuln_id': item.id } });
this.$router.push({ 'name': 'Vuln', 'params': { 'vuln_id': item.id } });
},
viewVulns() {
this.$router.push({ 'name': 'Vulns' });
Expand Down
1 change: 1 addition & 0 deletions frontend/src/components/pages/Ratings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,7 @@
import Colors from "../../common/colors";
import Scores from "../../common/scores";
import moment from 'moment';
export default {
name: "Ratings",
mixins: [Colors, Scores],
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/pages/Search.vue
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,7 @@ export default {
});
},
viewVuln(vuln_id) {
this.$router.push({ 'name': 'VulnDetails', 'params': { 'vuln_id': vuln_id } });
this.$router.push({ 'name': 'Vuln', 'params': { 'vuln_id': vuln_id } });
},
downloadVuln(vuln_id, format='json') {
this.$api.get('/api/vulns/'+vuln_id+'/export/'+format, {responseType: 'arraybuffer'}).then(res => {
Expand Down
151 changes: 151 additions & 0 deletions frontend/src/components/pages/Vuln.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
<template>
<div>
<v-tabs
left
background-color="white"
color="deep-orange accent-4"
>

<!-- Summary -->
<v-tab>Summary</v-tab>
<v-tab>
<v-badge
:color = getNumberColor(this.counter.count_exploit)
:content='this.count_exploit'
>
Exploits
</v-badge>
</v-tab>
<v-tab>
<v-badge
:color = getNumberColor(this.counter.count_threat)
:content='this.count_threat'
>
Threat activities
</v-badge>
</v-tab>


<!-- Information Vulnerability -->
<v-tab-item>
<VulnDetails
:vuln_id = this.vuln_id
@OpenSnackBar = this.modifySnackBar
/>
</v-tab-item>

<!-- Exploits -->
<v-tab-item>
<VulnerabilityExploit
:vuln_id = this.vuln_id
@OpenSnackBar = this.modifySnackBar
@UpdateCounter = this.getCountThreatsExploits
/>
</v-tab-item>

<!-- Threat -->
<v-tab-item>
<VulnerabilityThreat
:vuln_id = this.vuln_id
@OpenSnackBar = this.modifySnackBar
@UpdateCounter = this.getCountThreatsExploits
/>
</v-tab-item>


</v-tabs>
<SnackBar
:snack = snack
/>
</div>
</template>

<script>
import VulnDetails from "@/components/vulnerability/vulnerabilityDetails/VulnDetails.vue";
import VulnerabilityExploit from "@/components/vulnerability/exploit/VulnerabilityExploit.vue";
import VulnerabilityThreat from "@/components/vulnerability/threat/VulnerabilityThreat.vue";
import Colors from "@/common/colors";
import SnackBar from "@/components/vulnerability/snackBar/SnackBar.vue"
export default {
mixins: [
Colors,
],
components: {
VulnDetails,
VulnerabilityExploit,
VulnerabilityThreat,
SnackBar
},
data: () => ({
vuln_id: "",
snack: {
open: false,
color: '',
text: '',
},
counter: {
count_exploit: 0,
count_threat: 0,
}
}),
beforeRouteUpdate(to) {
this.vuln_id = to.params.vuln_id;
},
mounted() {
this.vuln_id = this.$router.currentRoute.params.vuln_id;
this.getDataFromApi(this.vuln_id)
},
computed: {
count_exploit(){
return this.counter.count_exploit === 0 ? "0" : this.counter.count_exploit
},
count_threat(){
return this.counter.count_threat === 0 ? "0" : this.counter.count_threat
}
},
methods: {
modifySnackBar(value) {
this.snack = value
},
getDataFromApi(vuln_id) {
return new Promise((resolve, reject) => {
let counter = this.getCountThreatsExploits(vuln_id);
setTimeout(() => {
this.loading = false;
resolve({ counter });
}, 300);
});
},
getCountThreatsExploits(vuln_id) {
this.loading = true;
this.$api.get('/api/vulns/'+vuln_id+'/counter').then(res => {
if (res && res.status === 200) {
this.counter = res.data;
}
return this.counter;
}).catch(e => {
this.counter = {
count_exploit: 0,
count_threat: 0,
};
this.loading = false;
swal.fire({
title: 'Error',
text: 'Unable to get counter',
showConfirmButton: false,
showCloseButton: false,
timer: 3000
});
});
this.loading = false;
}
}
}
</script>

<style>
</style>
Loading

0 comments on commit e3a70aa

Please sign in to comment.