Files
links/netscan/checks/ingress.py
T
2026-03-21 16:41:14 +11:00

94 lines
3.5 KiB
Python

import logging
import requests
from .base import Finding
logger = logging.getLogger(__name__)
CHECK_NAME = 'ingress_auth'
TIMEOUT = 10
def run(profile) -> list:
findings = []
domains = profile.domains or []
auth_host = profile.auth_provider_host
if not domains:
return [Finding(
check_name=CHECK_NAME,
severity='info',
title='No domains configured for ingress check',
detail='Add domains to the scan profile to enable ingress auth verification.',
raw={},
)]
for domain in domains:
raw = {'domain': domain, 'auth_provider_host': auth_host}
try:
resp = requests.get(f'https://{domain}/', allow_redirects=True, timeout=TIMEOUT,
headers={'User-Agent': 'NetScan/1.0'})
redirect_chain = [r.url for r in resp.history] + [resp.url]
raw['redirect_chain'] = redirect_chain
raw['final_url'] = resp.url
raw['status_code'] = resp.status_code
if auth_host:
passed_through_auth = any(auth_host in url for url in redirect_chain[:-1])
final_is_auth = auth_host in resp.url
if passed_through_auth or final_is_auth:
findings.append(Finding(
check_name=CHECK_NAME,
severity='ok',
title=f'{domain}: auth provider in redirect chain',
detail=f'Request passed through {auth_host} as expected.',
raw=raw,
))
else:
findings.append(Finding(
check_name=CHECK_NAME,
severity='critical',
title=f'{domain}: auth provider NOT in redirect chain',
detail=(
f'Expected redirect through {auth_host} but final URL is {resp.url}. '
'Authentication may be bypassed.'
),
raw=raw,
))
else:
findings.append(Finding(
check_name=CHECK_NAME,
severity='info',
title=f'{domain}: reachable (no auth provider configured)',
detail=f'Domain reached with status {resp.status_code}. Set auth_provider_host to verify auth.',
raw=raw,
))
except requests.exceptions.ConnectionError as e:
findings.append(Finding(
check_name=CHECK_NAME,
severity='warning',
title=f'{domain}: connection refused',
detail=f'Could not connect to https://{domain}/ — {e}',
raw={**raw, 'error': str(e)},
))
except requests.exceptions.Timeout:
findings.append(Finding(
check_name=CHECK_NAME,
severity='warning',
title=f'{domain}: request timed out',
detail=f'Request to https://{domain}/ timed out after {TIMEOUT}s.',
raw={**raw, 'error': 'timeout'},
))
except Exception as e:
logger.warning(f'Ingress check error for {domain}: {e}')
findings.append(Finding(
check_name=CHECK_NAME,
severity='warning',
title=f'{domain}: check error',
detail=str(e),
raw={**raw, 'error': str(e)},
))
return findings