Skip to content

Commit 6fff5e6

Browse files
authored
Update scanner error handling to cover edge cases related to unreachable domains and invalid implementations (canada-ca#2534)
1 parent 6007dd0 commit 6fff5e6

4 files changed

Lines changed: 30 additions & 50 deletions

File tree

services/scanners/https/https_scanner.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,14 +53,14 @@ def process_results(results):
5353
report = {"error": "missing"}
5454

5555
else:
56-
# Assumes that HTTPS would be technically present, with or without issues
57-
if results["Downgrades HTTPS"]:
56+
if results["Valid HTTPS"]:
57+
https = "Valid HTTPS" # Yes
58+
elif results["HTTPS Bad Chain"]:
59+
https = "Bad Chain" # Yes
60+
elif results["Downgrades HTTPS"]:
5861
https = "Downgrades HTTPS" # No
5962
else:
60-
if results["Valid HTTPS"]:
61-
https = "Valid HTTPS" # Yes
62-
elif results["HTTPS Bad Chain"]:
63-
https = "Bad Chain" # Yes
63+
https = "No HTTPS"
6464

6565
report["implementation"] = https
6666

services/scanners/results/result_processor.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -198,9 +198,7 @@ def process_ssl(results, guidance, domain_key, uuid, db):
198198
acceptable_curves = []
199199
weak_curves = []
200200

201-
if results.get("error") == "missing":
202-
negative_tags.append("ssl2")
203-
elif results.get("error") == "unreachable":
201+
if results.get("error") == "unreachable":
204202
neutral_tags.append("ssl9")
205203
else:
206204
for cipher in results["cipher_list"]:

services/scanners/ssl/requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ pretend
1010
uvloop
1111
httptools
1212
scapy
13+
sockets

services/scanners/ssl/ssl_scanner.py

Lines changed: 22 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from starlette.applications import Starlette
1616
from starlette.routing import Route, Mount, WebSocketRoute
1717
from starlette.responses import Response
18+
from socket import gaierror
1819
from sslyze.server_connectivity import ServerConnectivityTester
1920
from sslyze.errors import ConnectionToServerFailed, ServerHostnameCouldNotBeResolved
2021
from sslyze.plugins.scan_commands import ScanCommand
@@ -114,16 +115,24 @@ def get_supported_tls(highest_supported, domain):
114115
def scan_ssl(domain):
115116
try:
116117
server_info = get_server_info(domain)
118+
119+
highest_tls_supported = str(
120+
server_info.tls_probing_result.highest_tls_version_supported
121+
).split(".")[1]
122+
123+
tls_supported = get_supported_tls(highest_tls_supported, domain)
117124
except ConnectionToServerFailed as e:
118125
logging.error(f"Failed to connect to {domain}: {e.error_message}")
119126
RES_QUEUE.put({})
120127
return
121-
122-
highest_tls_supported = str(
123-
server_info.tls_probing_result.highest_tls_version_supported
124-
).split(".")[1]
125-
126-
tls_supported = get_supported_tls(highest_tls_supported, domain)
128+
except ServerHostnameCouldNotBeResolved as e:
129+
logging.error(f"{domain} could not be resolved: {e.error_message}")
130+
RES_QUEUE.put({})
131+
return
132+
except gaierror as e:
133+
logging.error(f"Could not retrieve address info for {domain} {e.error_message}")
134+
RES_QUEUE.put({})
135+
return
127136

128137
scanner = Scanner()
129138

@@ -212,8 +221,9 @@ def scan_ssl(domain):
212221
logging.info("Parsing Elliptic Curve Scan results...")
213222
res["supports_ecdh_key_exchange"] = result.supports_ecdh_key_exchange
214223
res["supported_curves"] = []
215-
for curve in result.supported_curves:
216-
res["supported_curves"].append(curve.name)
224+
if result.supported_curves:
225+
for curve in result.supported_curves:
226+
res["supported_curves"].append(curve.name)
217227

218228
RES_QUEUE.put(res)
219229

@@ -222,11 +232,8 @@ def process_results(results):
222232
logging.info("Processing SSL scan results...")
223233
report = {}
224234

225-
# Get cipher/protocol data via sslyze for a host.
226-
227235
if results == {}:
228-
report = {"error": "missing"}
229-
236+
report = {"error": "unreachable"}
230237
else:
231238
for version in [
232239
"SSL_2_0",
@@ -250,7 +257,7 @@ def process_results(results):
250257
report["supports_ecdh_key_exchange"] = results.get(
251258
"supports_ecdh_key_exchange", False
252259
)
253-
report["supported_curves"] = results["supported_curves"]
260+
report["supported_curves"] = results.get("supported_curves", [])
254261

255262
logging.info(f"Processed SSL scan results: {str(report)}")
256263
return report
@@ -294,34 +301,8 @@ async def scan(scan_request):
294301

295302
logging.info("Performing scan...")
296303

297-
try:
298-
p = Process(target=scan_ssl, args=(domain,))
299-
wait_timeout(p, TIMEOUT)
300-
301-
except ServerHostnameCouldNotBeResolved as e:
302-
logging.error(f"The designated domain could not be resolved: ({type(e).__name__}: {str(e)})")
303-
dispatch_results(
304-
{
305-
"scan_type": "ssl",
306-
"uuid": uuid,
307-
"domain_key": domain_key,
308-
"results": {"error": "unreachable"},
309-
},
310-
server_client,
311-
)
312-
return Response("Designated domain could not be resolved", status_code=500)
313-
314-
except ScanTimeoutException:
315-
dispatch_results(
316-
{
317-
"scan_type": "ssl",
318-
"uuid": uuid,
319-
"domain_key": domain_key,
320-
"results": {"error": "unreachable"},
321-
},
322-
server_client,
323-
)
324-
return Response("Timeout occurred while scanning", status_code=500)
304+
p = Process(target=scan_ssl, args=(domain,))
305+
wait_timeout(p, TIMEOUT)
325306

326307
scan_results = RES_QUEUE.get()
327308

0 commit comments

Comments
 (0)