security
CHAPTER 60 / 84
읽기 약 2분
FUNCTION
에러 핸들링과 안전한 스크립트
핵심 개념
보안 도구는 예외 상황이 많다 — 네트워크 타임아웃, 권한 거부, 잘못된 입력을 안전하게 처리한다.
본문
구체적인 예외 잡기
# ⚠️ 이 코드는 허가된 환경에서만 사용하세요.
import socket
# ❌ 너무 광범위 — 디버깅 어려움
def bad_check(host, port):
try:
socket.create_connection((host, port), timeout=2)
return True
except Exception: # 모든 예외를 삼킴
return False
# ✅ 예외별로 다른 의미
def good_check(host: str, port: int, timeout: float = 2.0) -> tuple[bool, str]:
try:
socket.create_connection((host, port), timeout=timeout)
return True, 'open'
except socket.timeout:
return False, 'timeout'
except ConnectionRefusedError:
return False, 'refused'
except socket.gaierror:
return False, 'dns_error'
except OSError as e:
return False, f'os_error: {e}'logging — print 대신 사용
import logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s [%(levelname)s] %(name)s: %(message)s',
handlers=[
logging.FileHandler('security_scan.log', encoding='utf-8'),
logging.StreamHandler(), # 콘솔 + 파일 동시 출력
],
)
log = logging.getLogger('whitehat')
def scan(host: str, port: int):
log.info(f'스캔 시작: {host}:{port}')
ok, reason = good_check(host, port)
if ok:
log.warning(f'포트 열림: {host}:{port}')
else:
log.debug(f'포트 닫힘 ({reason}): {host}:{port}')
return ok사용자 입력 검증
import ipaddress
def validate_target(target: str) -> str:
"""스캔 대상 IP 검증 — 사설망 또는 자기 IP만 허용."""
try:
ip = ipaddress.ip_address(target)
except ValueError:
raise ValueError(f'유효하지 않은 IP: {target}')
if ip.is_global:
raise PermissionError(f'공용 IP는 허가된 환경에서만 — 거부: {target}')
if not (ip.is_private or ip.is_loopback):
raise PermissionError(f'사설망/루프백만 허용: {target}')
return str(ip)
# 테스트
for t in ['127.0.0.1', '192.168.1.10', '8.8.8.8', '10.0.0.1', 'invalid']:
try:
ok = validate_target(t)
print(f'✅ {t}')
except (ValueError, PermissionError) as e:
print(f'❌ {t}: {e}')타임아웃에 강한 포트 체크
import socket
import logging
from concurrent.futures import ThreadPoolExecutor, as_completed
log = logging.getLogger('whitehat.portscan')
def check_port(host: str, port: int, timeout: float = 1.0) -> tuple[int, bool, str]:
"""단일 포트 체크 — 어떤 예외도 누설 안 함."""
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(timeout)
try:
s.connect((host, port))
return port, True, 'open'
except socket.timeout:
return port, False, 'timeout'
except ConnectionRefusedError:
return port, False, 'refused'
except OSError as e:
return port, False, f'error:{e.errno}'
finally:
s.close()
def scan_ports(host: str, ports: list[int], workers: int = 50) -> list[int]:
"""병렬 포트 스캔 — 예외에도 끝까지 완료."""
open_ports = []
with ThreadPoolExecutor(max_workers=workers) as ex:
futures = {ex.submit(check_port, host, p): p for p in ports}
for fut in as_completed(futures):
try:
port, ok, reason = fut.result()
if ok:
open_ports.append(port)
log.info(f'{host}:{port} {reason}')
except Exception as e:
# 절대 도달 안 함 (check_port가 모든 예외 처리) — 안전망
log.error(f'예상 못한 예외: {e}')
return sorted(open_ports)안전한 보안 스크립트 7원칙
- 구체적 예외만 잡기 —
except Exception:금지 - logging 사용 — print는 운영 환경에서 쓸 수 없음
- 타임아웃 모든 네트워크 작업에 설정
- 사용자 입력 검증 — 화이트리스트 방식
- finally로 리소스 정리
- 민감 정보 로깅 금지 — 비밀번호·토큰
- 법적 경계 명시 — 코드 상단에 허가 환경 명시 주석
AI 프롬프트
🤖 AI에게 잘 물어보는 법 — 모델·전략별 프롬프트
Claude
무료: Sonnet 4.6 / Pro $20/mo: Opus 4.6
내 보안 스크립트의 try/except 처리에서 광범위 예외와 누락된 finally를 찾아 프로덕션 수준으로 개선해줘.
ChatGPT
무료: GPT-5.5 / Plus $20/mo: GPT-5.5 Pro
Python 보안 도구의 7가지 안전 원칙(예외/로깅/타임아웃/검증/finally/민감정보/법적경계)을 실전 코드로 보여줘.
Gemini
무료: 2.5 Flash / Pro $19.99/mo: 3.1 Pro
내 포트 스캔 스크립트 전체를 분석해서 에러 핸들링·동시성·로깅 측면에서 운영 가능 수준인지 종합 리포트로 만들어줘.
Grok
무료: Grok 4.1 / SuperGrok $30/mo
2026년 보안 도구 개발에서 logging vs structlog vs loguru 어떤 게 표준이 되었는지 솔직히 알려줘.
⭐ 이것만 기억하세요
에러 핸들링과 안전한 스크립트는 이 3가지만 확실히 잡으세요
1.구체적인 예외 처리(socket.timeout/ConnectionRefusedError 등)로 실패 원인을 정확히 진단할 수 있다
2.logging + 입력 검증 + 타임아웃 — 이 3가지로 보안 스크립트를 운영 가능 수준으로 끌어올린다
3.다음 챕터부터 모듈 2 — Requests로 HTTP 프로토콜과 웹 보안을 다룬다
공유하기
진행도 60 / 84