서버 사이드 요청 위조(SSRF)란 무엇인가
서버 사이드 요청 위조는 웹 애플리케이션 보안에서 주목받는 취약점 중 하나입니다. 이 공격은 공격자가 취약한 서버를 프록시처럼 이용해 의도하지 않은 네트워크 요청을 발생시키는 기법을 의미합니다. 간단히 말해, 애플리케이션이 사용자 입력을 기반으로 외부 자원을 가져오는 기능을 가질 때, 그 입력값을 적절히 검증하지 않으면 발생할 수 있는 문제입니다. 사용자는 서버가 자신을 대신해 요청을 보낸다고 생각하지만, 예를 들어는 공격자가 조작한 목적지로 요청이 전송되는 구조입니다.
이 취약점의 위험성은 공격 경로가 외부에 국한되지 않고 내부 네트워크로까지 확장될 수 있다는 점에 있다. 외부에서 직접 접근이 불가능한 내부 시스템이라 하더라도, 서버를 매개로 한 간접 접근이 가능해지기 때문이다. 관련된 세부 자료 확인 내용을 살펴보면, 이러한 취약점을 통해 관리자 페이지나 데이터베이스와 같은 핵심 자원이 공격 대상이 되는 사례가 적지 않다. 그 결과 단순한 정보 유출 수준을 넘어, 내부 권한 상승이나 시스템 장악으로 이어질 가능성까지 존재하며, 전체 시스템 보안을 근본적으로 위협하는 심각한 결함으로 평가된다.
ssrf는 애플리케이션의 정상적인 기능을 악용한다는 점에서 방어가 까다롭습니다. 파일을 업로드하거나 URL에서 데이터를 가져오는 등의 일반적인 기능이 공격 벡터로 변모할 수 있습니다. 개발자는 외부 요청을 발생시키는 모든 로직에 대해 신중한 검토가 필요합니다. 사용자에게 제공되는 기능이 어떻게 오용될 수 있는지를 항상 염두에 두어야 합니다.
SSRF 공격이 발생하는 일반적인 시나리오
가장 흔한 경우는 애플리케이션이 사용자로부터 URL을 입력받아 해당 주소의 데이터를 처리할 때입니다. 프로필 이미지 URL을 입력받아 저장하거나, 웹페이지 미리보기 기능을 제공하는 서비스에서 이런 취약점이 나타날 수 있습니다. 공격자는 외부 도메인 대신 ‘http://localhost/admin’이나 ‘http://169.254.169.254/’ 같은 내부 메타데이터 서비스 주소를 입력합니다. 서버는 이 주소로 요청을 보내고, 그 응답을 공격자에게 노출시킬 수 있습니다.
또 다른 시나리오는 파일 업로드나 가져오기 기능과 연관됩니다. 일부 서비스는 사용자가 제공한 URL에서 파일을 다운로드하여 처리합니다. 이때 공격자가 ‘file://’ 프로토콜을 이용해 서버의 중요한 시스템 파일 경로를 지정하면, 해당 파일 내용이 유출될 위험이 있습니다. 서버 설정 파일이나 암호화 키 같은 민감 정보가 이 방법으로 탈취당할 수 있습니다.
최근에는 클라우드 환경에서의 SSRF 공격이 구체적으로 주목받고 있습니다. 많은 클라우드 인스턴스는 인스턴스 메타데이터 서비스를 통해 설정 정보나 임시 자격 증명을 제공합니다. 이 서비스는 일반적으로 인스턴스 내부에서만 접근 가능한 특수 IP 주소를 가지고 있습니다. 이와 같은 sSRF 취약점을 통해 공격자가 이 내부 엔드포인트에 요청을 보내면, 클라우드 자원을 제어할 수 있는 권한을 획득할 수 있는 치명적인 결과로 이어집니다.
SSRF 공격의 주요 유형과 목적
기본적인 유형은 데이터 유출에 초점을 맞춘 공격입니다. 공격자는 서버를 통해 내부 네트워크의 자원에 접근하여 응답을 외부로 전송하려고 시도합니다. 이는 내부 API 엔드포인트, 데이터베이스, 관리 콘솔 등 다양한 대상을 포함합니다. 성공할 경우 조직의 내부 구조에 대한 정보를 얻거나, 인증되지 않은 데이터를 추출할 수 있습니다.
더 적극적인 공격 유형은 서버 자체를 대상으로 합니다. 공격자는 ‘localhost’나 ‘127.0.0.1’을 목적지로 지정하여 서버가 자신에게 요청을 보내도록 유도할 수 있습니다. 이를 통해 서버의 내부 서비스 포트를 스캔하거나, 존재하지 않는 자원에 대한 요청을 반복시켜 서비스 거부 상태를 유발할 수도 있습니다. 서버의 리소스를 소모시키는 방식으로 운영에 지장을 줄 수 있습니다.
가장 위험한 유형은 공격 체인을 구성하는 데 SSRF를 활용하는 경우입니다. 예를 들어, 내부 시스템에서 발견한 또 다른 취약점을 공격하기 위한 발판으로 사용될 수 있습니다. SSRF로 획득한 정보나 자격 증명을 바탕으로, 이차 공격을 수행하여 전체 네트워크 제어권을 확보하는 것이 최종 목표가 될 수 있습니다. 이처럼 단일 취약점이 더 큰 보안 사고의 시발점이 될 수 있음을 이해해야 합니다.

SSRF 취약점을 탐지하고 확인하는 방법
SSRF 취약점을 확인하는 첫걸음은 애플리케이션에서 외부 자원을 로드하는 모든 기능을 식별하는 것입니다. URL 매개변수를 통한 이미지 로드, 데이터 가져오기, 파일 임포트, 웹훅 설정 등 사용자 입력이 최종 요청 주소에 영향을 미치는 지점을 찾아야 합니다. 이러한 기능은 공격 표면이 될 가능성이 높습니다. 수동 테스트나 자동화된 스캔 도구를 활용해 이러한 경로를 체계적으로 검토하는 과정이 필요합니다.
실제 테스트는 허용된 도메인 외부의 주소를 입력해 보는 것으로 시작할 수 있습니다. 공개적으로 접근 가능한 자신의 서버 주소나 인터넷 상의 무해한 엔드포인트를 입력하여, 서버가 실제로 그 주소로 요청을 보내는지 확인합니다. 요청이 발생했다면, 그 다음 단계로 내부 주소나 특수 프로토콜을 시도해 볼 수 있습니다. 테스트 시에는 대상 시스템의 운영을 방해하지 않도록 주의해야 합니다.
자동화된 도구를 사용하면 보다 광범위한 테스트가 가능합니다. OWASP ZAP이나 Burp Suite와 같은 보안 테스트 도구는 SSRF 취약점을 탐지하기 위한 기능을 내장하고 있습니다. 이러한 도구는 다양한 페이로드를 자동으로 생성하고 전송하여, 응답을 분석해 취약점 존재 여부를 판단합니다. 그럼에도 도구의 결과만으로 완벽한 판단을 내리기보다는, 발견된 문제점을 수동으로 재현하고 검증하는 과정이 반드시 수반되어야 합니다.
블랙리스트와 화이트리스트 기반 방어의 차이
SSRF를 방어하는 일반적인 접근법 중 하나는 블랙리스트를 사용하는 것입니다. 이 방법은 ‘localhost’, ‘127.0.0.1’, 내부 IP 대역, ‘file://’ 프로토콜 등 알려진 위험한 입력값을 거부하는 방식입니다. 그러나 이 방법은 근본적인 한계를 가지고 있습니다. 공격자는 ‘127.0.0.1’을 ‘0177.0.0.1’(8진수)이나 ‘2130706433’(10진수)로 변환하거나, 로컬호스트를 가리키는 다른 DNS 이름을 이용해 우회할 수 있습니다. 지속적으로 새로운 우회 기법이 등장하기 때문에 블랙리스트는 완전한 방어책이 될 수 없습니다.
보다 효과적인 전략은 화이트리스트 기반 접근법입니다. 애플리케이션이 접근해야 할 정상적인 외부 주소나 도메인 목록을 미리 정의하고, 사용자 입력이 이 목록에 포함되는지 검증하는 방식입니다. 예를 들어, 특정 CDN의 이미지 URL만 허용하도록 설정할 수 있습니다. 이 방법은 허용되지 않은 모든 요청을 기본적으로 차단하기 때문에 보안성이 훨씬 높습니다. 다만, 서비스의 유연성이 떨어질 수 있고, 허용 목록을 관리하는 추가 부담이 발생합니다.
현실적인 방어 체계는 두 방법을 혼용하는 경우가 많습니다. 화이트리스트를 기본으로 하되, 화이트리스트 내에서도 발생할 수 있는 위험을 블랙리스트로 추가 필터링합니다. 더욱이, 입력값 검증과 함께 네트워크 계층에서의 제어를 결합하는 다중 방어 계층을 구축하는 것이 바람직합니다. 단일한 방어 메커니즘에 의존하기보다는 여러 단계에서 검증이 이루어지도록 설계해야 합니다.
네트워크 계층에서의 추가 보안 조치
애플리케이션 수준의 검증만으로는 모든 SSRF 공격을 막기 어려울 수 있습니다. 따라서 운영 체제나 네트워크 방화벽 수준에서의 제한이 중요합니다. 서버는 외부로 나가는 네트워크 연결을 최소한으로 제한해야 합니다. 애플리케이션이 반드시 필요한 외부 도메인에만 연결할 수 있도록 아웃바운드 방화벽 규칙을 설정하는 것이 좋습니다. 특히 내부 네트워크 대역이나 메타데이터 서비스 IP로의 연결은 엄격히 차단해야 합니다.
클라우드 환경에서는 보안 그룹이나 VPC 설정을 활용할 수 있습니다. 애플리케이션 서버가 위치한 서브넷에서 다른 내부 서비스로의 불필요한 트래픽을 차단하는 규칙을 정의합니다. 또한, 많은 클라우드 제공자는 인스턴스 메타데이터 서비스에 대한 보안 강화 옵션을 제공합니다. 예를 들어, 메타데이터 서비스에 대한 접근을 특정 Hop Limit으로 제한하거나, IAM 역할을 사용하여 민감한 정보 노출을 최소화할 수 있습니다.
리버스 프록시나 API 게이트웨이를 도입하는 것도 고려해 볼 수 있는 방법입니다. 모든 외부 요청이 이 중간 계층을 통하도록 강제하면, 중앙에서 통합된 정책으로 요청을 검사하고 필터링할 수 있습니다. 이 계층에서 URL 스키마, 목적지 IP, 도메인 명을 철저히 검증함으로써, 백엔드 애플리케이션의 취약점이 직접적인 공격으로 이어지는 것을 방지할 수 있습니다.
개발 단계에서의 SSRF 예방 가이드라인
SSRF 취약점을 근본적으로 예방하려면 개발 단계에서부터 안전한 코딩 관행을 도입해야 합니다. 가장 중요한 원칙은 사용자 입력을 신뢰하지 않는 것입니다. 외부 자원을 가리키는 모든 사용자 제공 데이터는 잠재적으로 악성일 수 있다고 가정하고 처리해야 합니다. 입력값 검증은 허용 목록 방식을 우선으로 하여, 예상되는 정상적인 패턴만을 통과시켜야 합니다. 이러한 판단 과정에서 보안 담당자나 개발자가 과도한 차단이나 잘못된 예외 처리를 선택하는 경우도 많은데, 이는 잃는 고통의 뇌과학: 손실회피(Loss Aversion)가 합리적 베팅을 방해하는 신경학적 기전과 유사하게, 잠재적 손실에 대한 두려움이 합리적인 보안 설계를 흐릴 수 있기 때문입니다. 따라서 정규 표현식이나 전문 라이브러리를 활용해 도메인이나 IP 주소의 형식을 객관적으로, 일관되게 점검하는 것이 중요합니다.
외부 요청을 수행하는 라이브러리나 모듈을 선택할 때도 주의가 필요합니다. 가능하다면, 요청의 목적지를 제한할 수 있는 옵션을 제공하는 라이브러리를 사용하는 것이 좋습니다. 요청을 보내기 전에, 입력받은 URL을 파싱하여 호스트명, 포트, 스키마를 분리하고, 각 구성 요소에 대해 독립적인 검증 로직을 적용합니다. 흥미로운 점은 iP 주소의 경우, 공인 IP인지 사설 IP인지 여부를 확인하는 로직을 추가할 수 있습니다.
에러 메시지 관리도 보안에 중요한 영향을 미칩니다. SSRF 공격은 종종 블라인드 방식으로 진행됩니다, 공격자는 외부 요청의 결과를 직접 보지 못하지만, 서버의 응답 시간 차이나 에러 메시지의 미묘한 변화를 통해 내부 시스템의 존재 여부를 추론합니다. 따라서 외부 요청 실패 시에는 일관되고 정보가 적은 일반적인 에러 메시지만을 사용자에게 반환해야 합니다. 내부 네트워크 구조나 사용된 IP 주소에 대한 힌트를 절대로 노출해서는 안 됩니다.
안전한 URL 페처 및 파서 사용하기
프로그래밍 언어가 제공하는 기본 URL 파싱 함수는 때로 예상치 못한 동작을 할 수 있습니다. 예를 들어, ‘http://user@attacker.com@localhost/’ 같은 URL에서 호스트명을 무엇으로 판단할지에 따라 차이가 발생합니다. 따라서 SSRF 방어에 특화된 검증 로직을 구현하거나, 검증된 보안 라이브러리를 사용하는 것이 안전합니다. 이러한 라이브러리는 URL 오브스큐레이션 기법을 탐지하고, 표준화된 방식으로 최종 목적지 주소를 도출하는 데 도움을 줍니다.
요청을 보내기 직전에 한 번 더 검증하는 절차를 도입하는 것도 효과적입니다. 파싱된 호스트명을 DNS로 조회하여 얻은 실제 IP 주소가 허용되지 않는 대역에 속하는지 확인합니다. 이때, DNS 리바인딩 공격에 주의해야 합니다. 공격자가 짧은 TTL을 가진 도메인을 조작하여, DNS 조회 시점과 실제 연결 시점의 IP 주소가 달라지게 할 수 있습니다. 이를 방지하기 위해 DNS 조회 결과를 캐싱하거나, 연결 단계에서도 IP 주소를 재확인하는 메커니즘을 고려할 수 있습니다.
가능하다면, 사용자로부터 직접 URL을 입력받지 않는 대체 설계를 고민해 보는 것이 최선입니다. 예를 들어, 이미지 업로드 기능이라면 URL 입력 대신 파일 직접 업로드를 유도할 수 있습니다. 외부 데이터를 가져와야 하는 기능이라면, 사전에 검증된 공급자 목록에서 선택하도록 하는 방식으로 변경할 수 있습니다. 사용자 경험과 보안 요구사항 사이에서 현실적인 타협점을 찾는 과정이 필요합니다.
정기적인 보안 점검과 교육의 중요성
SSRF 취약점은 새로운 우회 기술과 클라우드 서비스의 발전에 따라 그 형태가 계속 진화하고 있습니다. 따라서 한 번 구현한 방어 로직이 영원히 유효하다고 생각해서는 안 됩니다. 정기적인 보안 코드 리뷰와 취약점 스캔을 통해 애플리케이션을 지속적으로 점검해야 합니다. 특히 외부 요청과 관련된 코드는 변경 사항이 있을 때마다 집중적인 검토 대상이 되어야 합니다.
개발자와 운영자에 대한 보안 인식 교육은 기술적 조치만큼 중요합니다. 이처럼 sSRF의 위험성, 발생 메커니즘, 일반적인 공격 패턴을 이해하면, 코드를 작성하거나 기능을 설계할 때 자연스럽게 보안을 고려할 수 있습니다. 새로운 보안 패치나 권고 사항이 발표되었을 때 이를 팀 내부에서 신속히 공유하고 적용하는 문화를 조성하는 것이 장기적인 보안 수준을 높이는 길입니다.
보안은 단순한 기능 추가가 아니라 시스템 설계 전반에 걸친 철학이어야 합니다. 이처럼 sSRF 방어를 위해서는 입력 검증, 네트워크 격리, 에러 처리, 로깅, 모니터링 등 여러 요소가 조화를 이루어야 합니다. 사고 발생 후 대응하는 것보다 사전에 예방하는 데 자원을 투자하는 것이 훨씬 효율적입니다. 꾸준한 관심과 체계적인 접근이 결국 가장 강력한 방어 수단이 됩니다.