Skip to content

Commit 2ab7983

Browse files
Merge pull request #205 from cert-ee/bugfix/various-bugfixes
Bugfix/various bugfixes
2 parents bf74525 + 68c0d80 commit 2ab7983

File tree

19 files changed

+96
-95
lines changed

19 files changed

+96
-95
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,6 @@ bower_components/
6464
.sass-cache/
6565
cuckoo/web/src/package-lock.json
6666
*.map
67+
68+
# Vagrant
69+
.vagrant

common/cuckoo/common/misp.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,9 @@ def find_events(self, value, type_attribute=None, limit=1, to_ids=1, publish_tim
186186
for attribute in attributes['Attribute']
187187
]
188188
except (ValueError, TypeError) as e:
189-
return []
189+
raise MispError(
190+
f"Failure while reading MISP response JSON. Error: {e}"
191+
)
190192

191193
def find_file_md5(self, md5, limit=1, to_ids=1, publish_timestamp="365d"):
192194
return self.find_events(

core/cuckoo/scripts/cleanup.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ def main(ctx, cwd, debug):
124124
return
125125

126126
@main.command()
127-
@click.argument("days", type=int)
127+
@click.argument("hours", type=int)
128128
@click.option("--yes", is_flag=True, help="Skip confirmation screen")
129129
@click.pass_context
130130
def remotestorage(ctx, days, yes):
@@ -147,7 +147,7 @@ def remotestorage(ctx, days, yes):
147147

148148

149149
@main.command("delete")
150-
@click.argument("state", type=string)
150+
@click.argument("state", type=str)
151151
@click.argument("hours", type=int)
152152
@click.option("--yes", is_flag=True, help="Skip confirmation screen")
153153
@click.pass_context

core/cuckoo/taskqueue.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ def _query_tasks(self, platform=None, os_version=None, limit=5):
178178

179179
def count_unscheduled(self):
180180
return self._ses.query(
181-
QueuedTask.id
181+
sqlalchemy.func.count(QueuedTask.id)
182182
).filter_by(scheduled=False).count()
183183

184184
def get_unscheduled_tasks(self, platform=None, os_version=None):

machineries/cuckoo/machineries/modules/proxmox.py

-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
from time import sleep
21
from dataclasses import dataclass
32

43
from cuckoo.common import machines
@@ -130,11 +129,6 @@ def state(self, machine):
130129
prox = self._create_proxmoxer_connection()
131130
current_status = prox.nodes(vm.node_name).qemu(vm.vm_id)\
132131
.status.current.get()
133-
# prevents spamming during starting and stoping VMs,
134-
# which leads to "too many redirection"-exception
135-
log.debug("Waiting for status to change...")
136-
sleep(5)
137-
138132
if current_status is None:
139133
raise errors.MachineryConnectionError(
140134
f"Error while getting status of {machine.label} "

processing/cuckoo/processing/config.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,12 @@ def constraints(self, value):
7777
"mhr.yaml": {
7878
"enabled": config.Boolean(default_val=False),
7979
"timeout": config.Int(default_val=60, min_value=0),
80-
"url": config.HTTPUrl(default_val="https://hash.cymru.com/v2/"),
80+
"url": config.HTTPUrl(),
8181
"user": config.String(allow_empty=True),
8282
"password": config.String(allow_empty=True),
8383
"min_suspicious": config.Int(default_val=10, min_value=1),
84-
"min_malicious": config.Int(default_val=17, min_value=1),
85-
},
84+
"min_malicious": config.Int(default_val=30, min_value=1),
85+
},
8686
"misp.yaml": {
8787
"processing": {
8888
"enabled": config.Boolean(default_val=False),

processing/cuckoo/processing/pre/mhr.py

+2-4
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ def _request_json(self, url, **kwargs):
5454
"""Wrapper around doing a request and parsing its JSON output."""
5555
try:
5656
r = requests.get(url, auth=HTTPBasicAuth(self.user, self.password),
57-
timeout=self.timeout, **kwargs)
57+
timeout=self.timeout, verify=False, **kwargs)
5858
return r.json() if r.status_code == 200 else {}
5959
except (requests.ConnectionError, ValueError) as e:
6060
self.ctx.log.error(
@@ -78,7 +78,6 @@ def _handle_file_target(self):
7878

7979

8080
def start(self):
81-
info = None
8281
antivirus_detection_rate = None
8382
if self.ctx.analysis.category == "file":
8483
info = self._handle_file_target()
@@ -96,7 +95,6 @@ def start(self):
9695
score = Scores.SUSPICIOUS
9796
else:
9897
return {}
99-
10098
if score:
10199
iocs = [
102100
IOC(antivirus="MHR", result=info["antivirus_detection_rate"])
@@ -108,7 +106,7 @@ def start(self):
108106
short_description="MHR sources report this target as "
109107
"malicious",
110108
description=f"{info['antivirus_detection_rate']} percentage of tested MHR antivirus engines"
111-
f" detect this target as malicious",
109+
f"detect this target as malicious",
112110
iocs=iocs
113111
)
114112

processing/cuckoo/processing/pre/static.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ def start(self):
4040

4141
for ext, handler_subkey in self._EXTENSION_HANDLER.items():
4242

43-
if not target.filename.lower().endswith(ext):
43+
if not target.filename.endswith(ext):
4444
continue
4545

4646
handler, subkey = handler_subkey

processing/cuckoo/processing/reporting/disk.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def report_identification(self):
3737

3838
def report_pre_analysis(self):
3939
include_result = [
40-
"virustotal", "irma", "static", "misp", "intelmq", "command"
40+
"virustotal", "irma", "mhr", "static", "misp", "intelmq", "command"
4141
]
4242

4343
# Pre might change settings such as launch args for specific chosen

processing/cuckoo/processing/reporting/elastic.py

-1
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,6 @@ def _update_analysis(self):
204204
try:
205205
update_analysis(
206206
analysis_id=self.ctx.analysis.id,
207-
score=self.ctx.analysis.score,
208207
tags=self.ctx.tag_tracker.tags,
209208
families=self.ctx.family_tracker.families,
210209
ttps=[t.id for t in self.ctx.ttp_tracker.ttps]

processing/cuckoo/processing/static/pe.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ def sha256(self):
4848

4949
@property
5050
def sha512(self):
51-
return self._cert_fingerprint_str(hashes.SHA256())
51+
return self._cert_fingerprint_str(hashes.SHA512())
5252

5353
@property
5454
def serial_number(self):

processing/cuckoo/processing/worker.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -220,8 +220,8 @@ def _handle_processing(processing_classes, ctx):
220220
processing_instances = make_plugin_instances(processing_classes, ctx)
221221
except PluginError as e:
222222
ctx.set_failed()
223-
ctx.errtracker.fatal_exception(e)
224-
ctx.log.exception(
223+
ctx.errtracker.add_error(e)
224+
ctx.log.error(
225225
"Processing cancelled. Failure during processing plugin "
226226
"initialization", error=e
227227
)
@@ -232,7 +232,7 @@ def _handle_processing(processing_classes, ctx):
232232
except CancelProcessing as e:
233233
ctx.set_failed()
234234
ctx.log.error("Processing cancelled", error=e)
235-
ctx.errtracker.fatal_exception(e)
235+
ctx.errtracker.fatal_error(e)
236236
return False
237237
except Exception as e:
238238
ctx.set_failed()

web/cuckoo/web/submit/urls.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
name="Submit/settings"
1919
),
2020
path(
21-
"re/<analysis_id:analysis_id>/", views.Resubmit.as_view(),
21+
"resubmit/<analysis_id:analysis_id>/", views.Resubmit.as_view(),
2222
name="Submit/resubmit"
2323
),
2424
]

web/cuckoo/web/submit/views.py

+67-63
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from django.shortcuts import render, redirect
1313
from django.views import View
1414
import re
15+
import logging
1516

1617
from cuckoo.common import submit, analyses
1718
from cuckoo.common.config import cfg
@@ -20,7 +21,6 @@
2021
)
2122
from cuckoo.common.storage import AnalysisPaths
2223

23-
2424
def _validate_website_url(website):
2525
"""Validate website into valid URL"""
2626
msg = f"Cannot validate this URL: {website}"
@@ -32,18 +32,6 @@ def _validate_website_url(website):
3232
return website
3333

3434

35-
def _validate_analysis_id(analysis_id):
36-
"""Validate analysis id"""
37-
ANALYSIS_ID_REGEX = "[0-9]{8}-[A-Z0-9]{6}"
38-
39-
msg = f"Cannot validate this analysis_id: {analysis_id}"
40-
complied_regex = re.compile(ANALYSIS_ID_REGEX)
41-
match = complied_regex.fullmatch(analysis_id)
42-
if not match:
43-
raise ValidationError(message=msg)
44-
return analysis_id
45-
46-
4735
def _make_web_platforms(available_platforms):
4836
fallbacks = cfg(
4937
"analysissettings.yaml", "platform", "fallback_platforms"
@@ -138,56 +126,6 @@ def post(self, request):
138126

139127
return redirect("Submit/waitidentify", analysis_id=analysis_id)
140128

141-
class Resubmit(View):
142-
143-
def get(self, request, *args, **kwargs):
144-
analysis_id = kwargs.get("analysis_id")
145-
146-
if analysis_id:
147-
try:
148-
analysis_id = _validate_analysis_id(analysis_id)
149-
except ValidationError as e:
150-
return render(
151-
request, template_name="submit/index.html.jinja2",
152-
status=400, context={"error": str(e)}
153-
)
154-
else:
155-
return HttpResponseBadRequest()
156-
157-
analysis = retriever.get_analysis(analysis_id).analysis
158-
159-
160-
try:
161-
s_maker = submit.settings_maker.new_settings()
162-
s_maker.set_manual(True)
163-
164-
password = analysis.settings.password
165-
if password:
166-
s_maker.set_password(password)
167-
168-
settings = s_maker.make_settings()
169-
if analysis.category == "file":
170-
submit_path = AnalysisPaths.submitted_file(analysis_id, resolve=True)
171-
analysis_id = submit.file(
172-
submit_path, settings, file_name=analysis.target.target
173-
)
174-
else:
175-
analysis_id = submit.url(analysis.target.target, settings)
176-
except submit.SubmissionError as e:
177-
return render(
178-
request, template_name="submit/index.html.jinja2",
179-
status=400, context={"error": str(e)}
180-
)
181-
182-
try:
183-
submit.notify()
184-
except submit.SubmissionError as e:
185-
return HttpResponseServerError(
186-
f"Failed to notify Cuckoo of new analysis {analysis_id}. {e}."
187-
)
188-
189-
return redirect("Submit/waitidentify", analysis_id=analysis_id)
190-
191129

192130
class WaitIdentify(View):
193131

@@ -241,3 +179,69 @@ def get(self, request, analysis_id):
241179
request, template_name="submit/settings.html.jinja2",
242180
context=context
243181
)
182+
183+
184+
185+
def _validate_analysis_id(analysis_id):
186+
"""Validate analysis id"""
187+
ANALYSIS_ID_REGEX = "[0-9]{8}-[A-Z0-9]{6}"
188+
189+
#msg = "Cannot validate analysis_id": %s" % analysis_id
190+
msg = f"Cannot validate this analysis_id: {analysis_id}"
191+
complied_regex = re.compile(ANALYSIS_ID_REGEX)
192+
match = complied_regex.fullmatch(analysis_id)
193+
if not match:
194+
raise ValidationError(message=msg)
195+
return analysis_id
196+
197+
class Resubmit(View):
198+
199+
def get(self, request, *args, **kwargs):
200+
analysis_id = kwargs.get("analysis_id")
201+
#analysis_id = request.GET.get("analysis_id")
202+
203+
if analysis_id:
204+
try:
205+
analysis_id = _validate_analysis_id(analysis_id)
206+
except ValidationError as e:
207+
return render(
208+
request, template_name="submit/index.html.jinja2",
209+
status=400, context={"error": str(e)}
210+
)
211+
else:
212+
return HttpResponseBadRequest()
213+
214+
analysis = retriever.get_analysis(analysis_id).analysis
215+
216+
217+
try:
218+
s_maker = submit.settings_maker.new_settings()
219+
s_maker.set_manual(True)
220+
221+
password = analysis.settings.password
222+
if password:
223+
s_maker.set_password(password)
224+
225+
settings = s_maker.make_settings()
226+
if analysis.category == "file":
227+
submit_path = AnalysisPaths.submitted_file(analysis_id, resolve=True)
228+
analysis_id = submit.file(
229+
submit_path, settings, file_name=analysis.target.target
230+
)
231+
else:
232+
analysis_id = submit.url(analysis.target.target, settings)
233+
except submit.SubmissionError as e:
234+
return render(
235+
request, template_name="submit/index.html.jinja2",
236+
status=400, context={"error": str(e)}
237+
)
238+
239+
try:
240+
submit.notify()
241+
except submit.SubmissionError as e:
242+
logging.error(f"Failed to notify Cuckoo of new analysis {analysis_id}. Exception: {e}")
243+
return HttpResponseServerError(
244+
"Failed to notify Cuckoo of new analysis. Please try again later."
245+
)
246+
247+
return redirect("Submit/waitidentify", analysis_id=analysis_id)

web/cuckoo/web/templates/analysis/components/mhr.html.jinja2

+3-3
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
</thead>
99
<tbody>
1010
<tr>
11-
<td {{ pre.mhr.antivirus_detection_rate }}</td>
12-
<td>{{ pre.mhr.last_run_date|formatisodatetime }}</td>
11+
<td>{{ pre.mhr.antivirus_detection_rate|default('', True) }}</td>
12+
<td>{{ pre.mhr.last_run_date|formatisodatetime if pre.mhr.last_run_date }}</td>
1313
</tr>
1414
</tbody>
1515
</table>
16-
{% endcall %}
16+
{% endcall %}

web/cuckoo/web/templates/analysis/components/summary.html.jinja2

+1-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@
7474
</div>
7575
{% endif %}
7676
{% if (("submittedfiledownload" | feature_enabled) and (filedownload_allowed is sameas true) and (analysis.category == "file")) %}
77-
<a href="{{ url('Analysis/submittedfile', args=[analysis.id]) }}" class="button is-small has-margin-y">Download submitted file</a>
77+
<a href="{{ url('Analysis/submittedfile', args=[analysis.id]) }}" class="button is-small has-margin-y">Download submitted file {{filedownload_allowed}}</a>
7878
{% endif %}
7979
<a onclick="deleteSubmission('{{ analysis.id}}')" class="button is-small has-margin-y">Delete analysis</a>
8080
<a onclick="reSubmission('{{ analysis.id}}')" class="button is-small has-margin-y">Resubmit</a>

web/cuckoo/web/templates/analysis/index.html.jinja2

+1-1
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@
135135

136136
{# tab: static.mhr #}
137137
{% if pre.mhr is defined %}
138-
{% if pre.mhr.antivirus_detection_rate %}
138+
{% if pre.mhr %}
139139
<div role="region" id="mhr" hidden>
140140
{% include "analysis/components/mhr.html.jinja2" %}
141141
</div>

web/cuckoo/web/templates/analysis/static.html.jinja2

+2-2
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,8 @@
9696
{% endif %}
9797
{# tab: static.irma #}
9898
{% if pre.irma %}
99-
<div id="tab-irma">
100-
{% call ui_box(title="IRMA Antivirus Engines", has_padding=False, collapsed=True) %}
99+
<div id="tab-irma" >
100+
{% call ui_box(title="IRMA Antivirus Engines", has_padding=False, hidden=True) %}
101101
{{ render_table(
102102
data=pre.irma.probe_results.antivirus,
103103
cols=["engine_name","result"],

web/cuckoo/web/templates/partial/analysis-index.html.jinja2

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
This file is included in the analysis and task views to display the navigation
33
sidebar.
44
#}
5+
{% from 'macros.html.jinja2' import color_class %}
56
<ul class="list is-index">
67
<li>
78
<p class="label">Analysis</p>

0 commit comments

Comments
 (0)