mirror of
https://github.com/wahyd4/links.git
synced 2026-08-08 21:04:53 +10:00
94 lines
3.5 KiB
Python
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
|