[s2n] 스캐너 메인 엔진 scanner.py 구현하기
November 05, 2025
1. 설계 개요
목표: CLI나 라이브러리로 Scanner를 호출하면
- (선택) DVWA Adapter로 로그인/인증 수행
- (선택) httpClient를 공유 세션으로 만들어서 플러그인에 전달
- 플러그인들을 순차로 실행해 Finding들을 모아 ScanReport를 변환
이런 기능을 가진 core 엔진을 만드는 것.
2. 함수 설계
(1) __init__(...) - 초기화
목적: 스캐너 인스턴스 초기화, 외부 자원 (Plugin, auth_adapter, http_client, config 등) 주입
- Plugins: 선택적으로 플러그인을 직접 전달
- auth_adapter: DVWA Adapter
- http_client
- config, timeout, logger, on_finding 콜백 (! 결정 필요)
출력: 없음 (객체 상태 초기화용) 핵심 로직: 인자 저장, 내부 플러그인 리스트 초기화, 로거 준비
(2) discover_plugins() - 플러그인 찾기 / 로드
목적: 전달된 plugins가 있으면 그걸 쓰고, 없으면 s2n.core.s2nscanner.plugins 패키지 아래의 모듈들을 동적으로 찾아 로드해서 플러그인 인스턴스 목록을 구성함
입력: 없음 (객체 상태 사용) 출력: List[PluginSpec] (로드된 플러그인 인스턴스들) 알고리즘:
- 만약 생성자에서 plugins가 주어졌으면 그것을 인스턴스화/정규화해서 반환
- 아니면 pkgutil.iter_modules로 s2n.core.s2nscanner.plugins 내부 모듈명들을 열거.
- 각 모듈을 importlib.import_module로 import -> 모듈 안의 플러그인을 찾아 인스턴스화하거나 모듈 자체를 플러그인으로 사용
- 예외는 로거에 남기고 계속되어야 함
(3) _authenticate() - 인증/로그인 관리
목적: auth_adapter가 제공되면 타겟으로 로그인/토큰 획득 등을 수행해 http_client에 인증 정보가 적용되도록 함
입력: target_url 출력: 성공 여부 bool 알고리즘:
-
run_target() 호출 시:
- auth_adapter 있으면 auth_adapter.login() 시도 - 실패 시 로그 남기고 skip - 성공 시 http_clinet = auth_adapter.http
- 없으면 내부 httpclient 기본 생성
- 발견된 http_client를 플러그인에 전달
-
각 플러그인에 대해
- plugin.initialize(config, http_client)
- plugin.scan(target, http_client) plugin.teardown()
(4) run_target(target) - 한 타겟 전체 스캔
목적: 인증된 세션을 사용해 한 타겟을 모든 플러그인으로 스캔하고 결과 수집
입력: target (스캔할 URL) 출력: List[Finding] 각 플러그인이 발견한 취약점 결과들의 리스트
알고리즘:
-
_authenicate() 호출 -> 인증 시도
- 실패: 로그 남기고 스캔 중단 (return 빈 리스트)
-
인증 성공 불필요 -> 유효한 http_client 확보 - 각 플러그인 순회하며 다음 단계 수행:
- plugin.initialize(config, http_client) 호출 -> 플러그인 내부 설정 및 세션 연결 준비
- plugin.scan(target, http_client) 호출 -> 타겟 URL에 대한 검사 실행
- 반환된 Finding 객체들을 findings 리스트에 추가
- (선택) on_finding 콜백 있으면 각 Finding을 실시간 전달
- plugin.teardown()으로 자원 정리
- 모든 프러그인 실행 후 findings 반환
(5) run(targets) - 전체 스캔 조율
목적: 여러 타겟 리스트를 받아 run_target()을 반복 실행하고, 전체 결과를 하나의 ScanReport로 통합
입력: targets: 문자열 리스트 (사이트나 경로) 출력: ScanReport 스캔 전체 요약
알고리즘:
- ScanReport 객체 초기화
- discover_plugins() 호출 -> 사용할 플러그인 목록 확보
- targets 리스트 순회:
- 각 타겟에 대해 run_target(target) 실행
- 반환된 findings를 report.findings에 누적
- 모든 타겟 실행 후 finished_at = 현재 시각 기록
- 최종 레포트 반환