보안

SSRF 공격 막는 내부망 접근 제어, 화이트리스트로 시스템을 보호하는 실전 점검법

강코의 코딩 일기 2026. 7. 9. 10:05
반응형

우리 팀의 중요한 시스템, SSRF 공격에 취약하진 않나요? 내부망 접근 통제와 화이트리스트 기반의 실전 방어 전략으로 안전한 개발 환경을 구축하는 방법을 기술 리더의 관점에서 자세히 알아봅니다.

안녕하세요, 팀의 기술과 운영을 이끌고 계신 테크 리더/엔지니어링 매니저님들!

다들 바쁜 와중에도 우리 팀 시스템의 보안은 늘 마음 한편에 자리 잡은 중요한 숙제일 겁니다. 특히 최근 웹 애플리케이션 보안에서 Server-Side Request Forgery (SSRF) 공격은 그 파급력 때문에 더욱 주의가 필요하죠. 외부에서 접근 불가능해야 할 내부 시스템이나 클라우드 메타데이터까지 접근을 허용하게 만들 수 있는 무서운 공격이거든요.

혹시 "우리 시스템은 괜찮을 거야" 하고 막연하게 생각하고 계시진 않나요? 개발자가 실수로 외부 URL을 허용하거나, 미처 생각지 못한 예외 케이스에서 SSRF 취약점이 발생할 수도 있답니다. 이런 상황에 대비하기 위해 우리 팀은 어떤 보안 정책을 세우고, 어떤 점들을 점검해야 할까요? 오늘은 기술 리더의 관점에서 SSRF 방어를 위한 내부망 접근 통제와 화이트리스트 점검 가이드를 실전 체크리스트 형태로 자세히 이야기해보려 합니다. 우리 팀 시스템을 더욱 견고하게 만드는 데 도움이 되었으면 좋겠습니다!


Server-Side Request Forgery (SSRF) 방어를 위한 내부망 접근 통제 및 화이트리스트 점검 가이드 - firearm, revolver, bullet, gun, weapon, handgun, crime, danger, shot, shoot, crime scene, shooting, security, criminal, murder, dangerous, defense, brown security, brown gun

Image by stevepb on Pixabay

SSRF, 대체 어떤 위협일까요?

먼저, SSRF가 정확히 어떤 공격인지 개념부터 확실히 짚고 넘어가시죠. SSRF(Server-Side Request Forgery)는 웹 서버가 외부 요청을 처리하는 과정에서, 공격자가 의도적으로 조작된 URL을 서버에 보내 내부망에 있는 자원이나 외부 서비스로 요청을 보내도록 유도하는 공격입니다. 즉, 서버가 공격자 대신 내부망의 다른 서버나 서비스에 접근하게 만드는 거죠.

예를 들어, 우리 서비스에 '이미지 URL을 입력하면 서버가 해당 이미지를 가져와 처리해주는 기능'이 있다고 해봅시다. 여기서 사용자가 외부 이미지 URL 대신, http://169.254.169.254/latest/meta-data/ 와 같은 AWS 메타데이터 서버 주소를 입력한다면 어떻게 될까요? 서버가 이 주소로 요청을 보내게 되고, 만약 방어가 제대로 되어 있지 않다면 공격자는 해당 서버의 중요한 정보(자격 증명 등)를 탈취할 수 있게 됩니다. 상상만 해도 아찔하죠?

이런 공격이 성공하면 다음과 같은 심각한 피해로 이어질 수 있습니다.

  • 내부망 정보 유출: 사내 인트라넷, DB 서버 등 외부에서 접근 불가능한 내부 시스템에 접근하여 민감한 정보를 탈취합니다.
  • 클라우드 메타데이터 접근: AWS, Azure, GCP 등 클라우드 환경에서 인스턴스의 자격 증명(Credential)을 탈취하여 클라우드 자원을 제어할 수 있게 됩니다.
  • 내부 시스템 포트 스캔: 내부망의 특정 IP 주소와 포트를 스캔하여 취약한 서비스를 찾아냅니다.
  • 다른 외부 서비스 공격: 내부망을 경유하여 다른 외부 서비스에 DoS(서비스 거부) 공격을 가하거나, 피싱 공격에 활용될 수 있습니다.

이처럼 SSRF는 단순한 정보 유출을 넘어, 전체 시스템의 통제권을 빼앗거나 더 큰 공격의 발판이 될 수 있는 치명적인 위협입니다. 그렇기 때문에 우리 팀의 모든 개발자는 물론, 기술 리더님들도 이 위협에 대한 명확한 이해와 방어 전략 수립이 필수적입니다.


우리 시스템, SSRF 공격에 얼마나 취약한가요?

SSRF 공격을 효과적으로 방어하기 위해선 먼저 우리 시스템이 어떤 지점에서 취약할 수 있는지 파악하는 것이 중요합니다. 기술 리더로서 팀원들과 함께 다음 체크리스트를 점검해 보세요. 아마 의외의 지점에서 취약점을 발견할 수도 있을 겁니다.

SSRF 취약점 발생 가능성이 높은 기능 체크리스트

우리 서비스에 아래와 같은 기능이 있다면, SSRF 공격에 노출될 가능성이 높으니 특별히 신경 써서 점검해야 합니다.

  1. 외부 URL을 입력받아 처리하는 기능:
    • 웹훅(Webhook) URL 등록
    • 이미지, 동영상 등 미디어 파일 URL을 입력받아 서버에서 처리 (썸네일 생성, 미리 보기 등)
    • PDF, 문서 파일 URL을 입력받아 서버에서 변환/처리
    • 사용자가 제공한 URL의 콘텐츠를 파싱하여 보여주는 기능 (예: 외부 기사 미리 보기)
    • 원격 서버에서 파일 가져오기 (Import/Fetch) 기능
  2. 서버 간 통신이 활발한 내부 API:
    • 마이크로서비스 아키텍처에서 서비스 간 통신 시, 요청 URL이 사용자 입력에 의해 일부 변경될 수 있는 경우
    • 백엔드에서 다른 백엔드 서비스로 요청을 전달하는 프록시(Proxy) 역할의 API
  3. 클라우드 환경에서 운영되는 서비스:
    • 클라우드 메타데이터 서비스(AWS IMDS, GCP Metadata Service 등) 접근 가능성이 있는 경우
    • 관리자 페이지나 내부 도구에서 URL 파라미터를 통해 서버 요청을 수행하는 경우

이런 기능들을 단순히 "보안팀에서 다 해줬겠지" 하고 넘어가서는 안 됩니다. 개발 과정에서 새로운 기능이 추가되거나 기존 기능이 변경될 때마다 이러한 취약점이 재발할 수 있거든요. 팀 내 코드 리뷰 프로세스에서 SSRF 관련 보안 가이드를 필수적으로 포함하고 있는지 확인하는 것도 중요합니다.


내부망 접근 통제, 방어의 첫걸음

SSRF 방어의 가장 기본적이면서도 강력한 방법은 바로 내부망 접근 통제입니다. 외부에서 들어온 요청이 서버 측에서 처리될 때, 불필요한 내부 자원에는 아예 접근할 수 없도록 네트워크 레벨에서 차단하는 거죠. 이는 마치 집 대문을 잠그는 것과 비슷합니다.

방화벽/보안 그룹 설정 핵심 체크리스트

클라우드 환경이든 온프레미스 환경이든, 방화벽이나 보안 그룹(Security Group)은 핵심 방어선입니다. 다음 질문에 답해보세요.

  1. 최소 권한 원칙 적용 여부:
    • 우리 웹 서버가 내부망의 모든 IP 대역에 접근할 수 있도록 허용되어 있진 않나요?
    • 웹 서버가 정말 필요한 내부 서비스(DB, 캐시, 인증 서버 등)에만 특정 포트로 접근하도록 최소한의 규칙이 설정되어 있나요?
    • 특히, 127.0.0.1 (localhost), 0.0.0.0, 169.254.169.254 (클라우드 메타데이터 IP) 등 민감한 IP 주소로의 아웃바운드(Outbound) 트래픽이 차단되어 있나요?
  2. 아웃바운드 트래픽 통제:
    • 웹 서버에서 외부로 나가는 모든 트래픽을 허용하고 있진 않나요?
    • 꼭 필요한 외부 도메인이나 IP 대역으로만 트래픽이 나가도록 화이트리스트 기반의 아웃바운드 규칙이 적용되어 있나요?
  3. 내부망 IP 대역 차단:
    • 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 등 사설 IP 대역으로의 접근이 명시적으로 차단되어 있나요?

이러한 네트워크 규칙은 초기 설정이 매우 중요하며, 변경 사항이 발생할 때마다 철저한 검토와 테스트가 필요합니다. 팀의 인프라 담당자와 긴밀히 협력하여 주기적으로 점검해야 하죠.

네트워크 세분화(Network Segmentation) 전략

하나의 거대한 네트워크에 모든 서버를 몰아넣는 것은 보안상 좋지 않습니다. 네트워크 세분화는 마치 건물을 여러 개의 방으로 나누어 각 방마다 출입 통제를 하는 것과 같습니다. 웹 서버, DB 서버, 캐시 서버, 관리자 도구 서버 등을 각각 다른 네트워크 서브넷에 배치하고, 각 서브넷 간의 통신을 엄격하게 제어하는 거죠.

예를 들어, 프론트엔드 웹 서버는 DMZ(Demilitarized Zone)에, 애플리케이션 서버는 내부 네트워크에, DB 서버는 더 깊숙한 내부 네트워크에 위치시켜 서로 다른 보안 그룹과 라우팅 정책을 적용할 수 있습니다. 이렇게 하면 설령 웹 서버가 SSRF 공격에 노출되더라도, 공격자가 접근할 수 있는 내부 자원의 범위가 크게 줄어들게 됩니다.


Server-Side Request Forgery (SSRF) 방어를 위한 내부망 접근 통제 및 화이트리스트 점검 가이드 - server, technology, web, data, internet, network, computer, digital, communication, business, hardware, information, connection, database, cloud, system, computing, storage, security, center, equipment, infrastructure, global, design, hosting, tech, icon, service, rack, line, datacenter, connect, room, 3d, gray business, gray computer, gray technology, gray laptop, gray data, gray clouds, gray network, gray community, gray room, gray internet, gray digital, gray communication, gray tech, gray security, gray company, gray information, gray web, gray global, gray server, gray service, server, server, database, hosting, hosting, hosting, hosting, hosting

Image by QuinceCreative on Pixabay

화이트리스트 기반의 외부 요청 검증

네트워크 레벨에서의 통제는 중요하지만, 애플리케이션 레벨에서의 방어도 필수적입니다. 바로 화이트리스트(Whitelist) 기반의 외부 요청 검증이죠. "무엇이든 허용하고, 위험한 것만 막는" 블랙리스트 방식은 우회될 가능성이 높기 때문에, "허용된 것만 허용하고, 나머지는 모두 차단하는" 화이트리스트 방식이 훨씬 안전합니다.

URL 파싱 및 유효성 검사 기준

사용자로부터 외부 URL을 입력받는 기능이 있다면, 서버에서 해당 URL을 요청하기 전에 반드시 철저하게 검증해야 합니다. 다음은 중요한 검증 기준입니다.

  1. 허용된 스킴(Scheme)만 허용: http, https 스킴만 허용하고, file://, gopher://, ftp:// 등 잠재적으로 위험한 스킴은 차단해야 합니다.
  2. 허용된 도메인/IP만 허용: 우리 서비스가 외부 요청을 보내야 하는 도메인(예: api.external-service.com)이나 IP 대역만 명시적으로 허용하고, 나머지는 모두 차단합니다. 와일드카드(*.example.com) 사용 시에도 신중해야 합니다.
  3. 내부망 IP 주소 차단: URL이 내부망 IP 주소(10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)나 루프백 주소(127.0.0.1)를 가리키는지 확인하여 차단해야 합니다. 클라우드 메타데이터 IP(169.254.169.254)도 예외 없이 차단해야 합니다.
  4. 리다이렉션 방지: 초기 요청 URL은 안전하더라도, 서버가 응답하는 리다이렉션(3xx 응답)을 통해 내부망으로 우회될 수 있습니다. HTTP 클라이언트 설정에서 리다이렉션을 자동으로 따르지 않도록 설정하고, 필요하다면 리다이렉션된 URL도 다시 검증해야 합니다.
  5. URL 인코딩/디코딩 주의: 공격자는 URL 인코딩을 사용하여 필터를 우회할 수 있습니다. URL을 파싱하기 전에 반드시 적절히 디코딩하고, 파싱 후에는 다시 인코딩된 형태로 검증하는 로직을 고려해야 합니다.

이러한 검증 로직은 개발자가 직접 구현해야 하며, 모든 외부 요청 지점에 일관되게 적용되어야 합니다. 팀 내에서 표준화된 URL 검증 라이브러리나 모듈을 만들어 재사용하는 것을 권장합니다.

DNS 룩업과 IP 주소 검증

URL 검증 시 도메인 이름을 화이트리스트에 추가하는 것만으로는 충분하지 않습니다. 공격자는 DNS Rebinding 공격을 통해 안전한 도메인처럼 보이게 한 후, 실제 요청 시에는 내부망 IP로 해석되도록 할 수 있거든요. 따라서 URL 파싱 후, 해당 도메인의 IP 주소를 DNS 룩업(DNS Lookup)하여 이 IP 주소가 화이트리스트에 있는지, 혹은 블랙리스트(내부망 IP, 메타데이터 IP 등)에 포함되지 않는지 한 번 더 검증하는 과정이 필요합니다.


import re
import ipaddress
import socket

# 허용할 도메인 리스트 (화이트리스트)
ALLOWED_DOMAINS = [
    "example.com",
    "api.external-service.com"
]

# 내부망 및 민감한 IP 대역 (블랙리스트)
# 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 127.0.0.1/8, 169.254.169.254/32
BLACKLISTED_IP_RANGES = [
    ipaddress.ip_network("10.0.0.0/8"),
    ipaddress.ip_network("172.16.0.0/12"),
    ipaddress.ip_network("192.168.0.0/16"),
    ipaddress.ip_network("127.0.0.1/8"),
    ipaddress.ip_network("169.254.169.254/32")
]

def is_safe_url(url):
    try:
        # 1. URL 파싱 (예시: 간단한 정규식, 실제로는 urlparse 라이브러리 사용 권장)
        match = re.match(r"^(https?)://([a-zA-Z0-9.-]+)(:\d+)?(/.*)?$", url)
        if not match:
            print("Invalid URL format.")
            return False

        scheme = match.group(1)
        host = match.group(2)

        # 2. 허용된 스킴 검증
        if scheme not in ["http", "https"]:
            print(f"Disallowed scheme: {scheme}")
            return False

        # 3. 도메인 화이트리스트 검증
        if host not in ALLOWED_DOMAINS:
            print(f"Disallowed domain: {host}")
            return False

        # 4. DNS 룩업 및 IP 주소 검증
        # 주의: 실제 요청 시에는 IP 주소가 변경될 수 있으므로, 요청 직전에 다시 검증해야 함
        ip_addresses = socket.gethostbyname_ex(host)[2] # 도메인에 해당하는 모든 IP 주소 가져오기
        
        for ip_str in ip_addresses:
            ip_obj = ipaddress.ip_address(ip_str)
            for blacklisted_range in BLACKLISTED_IP_RANGES:
                if ip_obj in blacklisted_range:
                    print(f"Resolved IP {ip_str} is in a blacklisted range.")
                    return False

        return True

    except Exception as e:
        print(f"Error during URL validation: {e}")
        return False

# 예시
print(f"Validating https://example.com: {is_safe_url('https://example.com')}")
print(f"Validating http://api.external-service.com: {is_safe_url('http://api.external-service.com')}")
print(f"Validating file:///etc/passwd: {is_safe_url('file:///etc/passwd')}")
print(f"Validating https://malicious.com: {is_safe_url('https://malicious.com')}") # Not in ALLOWED_DOMAINS
print(f"Validating http://127.0.0.1: {is_safe_url('http://127.0.0.1')}") # Resolved IP is blacklisted (if example.com resolves to 127.0.0.1 this would catch it)
print(f"Validating http://169.254.169.254: {is_safe_url('http://169.254.169.254')}") # Resolved IP is blacklisted

위 코드는 파이썬 예시입니다. 실제 프로덕션 환경에서는 urllib.parse 같은 더 강력한 라이브러리를 사용하고, 엣지 케이스를 더욱 꼼꼼히 다뤄야 합니다. 중요한 점은, DNS 룩업 결과를 신뢰하기 전에 IP 주소 자체를 검증해야 한다는 것입니다.

화이트리스트와 블랙리스트 방식의 차이점을 표로 비교해보면 그 중요성이 더욱 명확해집니다.

구분 화이트리스트 (White List) 블랙리스트 (Black List)
정의 명시적으로 허용된 항목만 통과시키고, 나머지는 모두 차단 명시적으로 차단된 항목을 제외하고, 나머지는 모두 통과
보안 강도 높음 (미확인된 위협에 대한 기본 방어) 낮음 (새로운 공격 패턴에 취약)
관리 용이성 초기 설정이 까다로울 수 있으나, 관리 용이 (보안 강화 시) 초기 설정은 쉬우나, 지속적인 업데이트 필요 (공격 패턴 추가)
SSRF 방어 적합성 매우 적합 (내부망 접근 등 예측 불가능한 공격 차단에 효과적) 부적합 (다양한 우회 기법에 취약)

Server-Side Request Forgery (SSRF) 방어를 위한 내부망 접근 통제 및 화이트리스트 점검 가이드 - security, data, privacy policy, internet, hacker, crime, password, business, server, information, protection, code, network, computer, cyber, privacy policy, hacker, hacker, hacker, hacker, hacker, server, server, server, server, server

Image by Schluesseldienst on Pixabay

SSRF 방어, 운영 시 고려할 점들

SSRF 방어는 한 번 구축으로 끝나는 것이 아니라, 지속적인 관심과 노력이 필요한 영역입니다. 기술 리더로서 팀 운영 관점에서 다음 사항들을 고려해 보세요.

  1. 정기적인 보안 감사 및 점검:
    • 우리 팀의 모든 외부 요청 기능을 주기적으로 점검하고, SSRF 취약점이 없는지 보안 감사(Security Audit)를 수행해야 합니다.
    • 새로운 기능이 추가되거나 기존 기능이 변경될 때마다 SSRF 방어 로직이 제대로 적용되었는지 코드 리뷰 시 필수적으로 확인하는 프로세스를 마련해야 합니다.
    • 자동화된 SAST(Static Application Security Testing)DAST(Dynamic Application Security Testing) 도구를 활용하여 취약점을 조기에 발견하는 것도 좋은 방법입니다.
  2. 팀원 교육 및 인식 제고:
    • 모든 개발팀원이 SSRF 공격의 위험성과 방어 방법에 대해 충분히 인지하고 있어야 합니다. 정기적인 보안 교육을 통해 최신 공격 트렌드와 방어 기술을 공유하는 것이 중요합니다.
    • 특히 신규 입사자 온보딩 시 보안 교육을 필수로 포함하여, 처음부터 안전한 개발 습관을 형성할 수 있도록 도와야 합니다.
  3. 클라우드 환경 보안 설정 재확인:
    • 클라우드 환경에서는 IAM(Identity and Access Management) 정책을 통해 인스턴스의 권한을 최소화하고, 메타데이터 서비스 접근을 제한하는 설정(예: AWS IMDSv2 강제 사용)을 적극적으로 활용해야 합니다.
    • 클라우드 보안 그룹/네트워크 ACL(Access Control List) 설정이 위에서 언급한 내부망 접근 통제 원칙을 철저히 따르고 있는지 주기적으로 검토해야 합니다.
  4. 로깅 및 모니터링 강화:
    • SSRF 공격 시도나 비정상적인 외부 요청이 발생했을 때 이를 즉시 감지할 수 있도록 로깅 및 모니터링 시스템을 구축해야 합니다.
    • 의심스러운 IP 주소나 내부망 IP로의 요청 시도를 로그에 기록하고, 특정 패턴이 감지되면 알림을 발생시키도록 설정하는 것이 좋습니다.

이러한 운영상의 고려 사항들은 단순히 '기술적인 문제'를 넘어 '팀 문화'의 영역이기도 합니다. 기술 리더님께서 솔선수범하여 보안의 중요성을 강조하고, 팀원들이 적극적으로 참여할 수 있는 환경을 만들어주시는 것이 가장 중요합니다.


마무리하며: 안전한 시스템을 위한 지속적인 노력

SSRF는 웹 애플리케이션에서 발생할 수 있는 여러 보안 위협 중 하나일 뿐입니다. 하지만 그 잠재적인 파급력을 고려했을 때, 결코 소홀히 할 수 없는 부분이죠. 오늘 다룬 내부망 접근 통제와 화이트리스트 기반의 외부 요청 검증은 SSRF 방어를 위한 가장 효과적인 두 가지 축이라고 할 수 있습니다.

기술 리더로서 이 가이드를 통해 우리 팀 시스템의 보안 상태를 점검하고, 필요한 개선 사항을 발견하는 데 도움이 되셨기를 바랍니다. 개발팀원들과 함께 이 체크리스트를 공유하고, 논의하며, 실제 시스템에 적용해나가는 과정 자체가 팀의 보안 수준을 한 단계 끌어올리는 귀한 경험이 될 겁니다.

보안은 개발 과정의 마지막 단계가 아니라, 기획부터 개발, 배포, 운영의 모든 단계에서 함께 고려되어야 할 필수 요소입니다. 지속적인 관심과 투자로 더욱 안전하고 신뢰할 수 있는 서비스를 만들어나가시길 응원합니다!

혹시 우리 팀에서는 SSRF 방어를 위해 어떤 특별한 노력을 하고 계신가요? 아니면 이 가이드 외에 더 효과적인 방법이 있다면 댓글로 공유해주세요. 함께 더 나은 보안 환경을 만들어나가요!

📌 함께 읽으면 좋은 글

  • [보안] OAuth 2.0 및 OIDC 기반 인증/인가 시스템: 성공적인 설계 및 구현 전략
  • [보안] OWASP Top 10: 웹 애플리케이션 취약점 분석 및 방어 전략 완벽 가이드
  • [클라우드 인프라] AWS VPC Flow Logs, 당신이 모르는 치명적 함정: 네트워크 가시성 확보의 본질적 접근법

이 글이 도움이 되셨다면 공감(♥)댓글로 응원해 주세요!
궁금한 점이나 다루었으면 하는 주제가 있다면 댓글로 남겨주세요.

반응형