본문 바로가기
시큐어코딩/JAVA

[시큐어코딩]Java에서 서버사이드 요청 위조(SSRF) 완벽 대응 가이드

by ICT리더 리치 2025. 4. 8.

SSRF(Server-Side Request Forgery)는 공격자가 서버로 하여금 내부 네트워크, 외부 URL, 민감 자원에 대한 요청을 하도록 유도하는 대표적인 보안 취약점 중 하나입니다. 특히 클라우드와 마이크로서비스 아키텍처(MSA) 환경에서 심각한 피해를 일으킬 수 있습니다.

이번 포스팅에서는 Java + Spring Boot 환경에서 발생할 수 있는 SSRF 취약점을 실제 사례와 함께 분석하고, 보안 설정, 화이트리스트 구성, 외부 라이브러리 검증 등을 포함한 실무 대응 전략을 소개합니다.

취약한 URL 처리 방식, RestTemplate 등의 비검증 사용, 클라우드 메타데이터 접근 문제 등을 단계별로 점검하여 SSRF 취약점을 완전히 차단할 수 있도록 도와드리겠습니다.

1. SSRF 취약점이란?

SSRF(Server-Side Request Forgery)란 공격자가 클라이언트가 아닌 서버 측 요청 기능을 악용해 내부 시스템이나 외부 URL로 의도치 않은 요청을 보내게 만드는 공격 기법입니다. 예를 들어 서버가 입력값을 이용해 외부 URL에 요청을 보내는 기능이 있다면, 공격자는 이 입력값을 조작하여 서버가 http://localhost:8080/admin 또는 http://169.254.169.254(AWS 메타데이터 주소)로 접근하도록 만들 수 있습니다.

이 취약점은 다음과 같은 상황에서 자주 발생합니다:

  • 이미지 URL을 입력받아 서버가 프록시 역할을 할 때
  • WebHook, RSS, 외부 API 연동 등으로 입력 URL을 서버가 호출할 때
  • 클라우드 인프라의 메타데이터 주소로 접근 가능한 경우

SSRF는 단순 요청 위조에서 끝나는 것이 아니라, 내부망 스캐닝, 민감 정보 접근, 인증 우회, 서비스 연결망 탐지 등 2차 공격으로 이어질 수 있기 때문에, 개발 시 입력값 검증, 화이트리스트 기반 필터링, 네트워크 정책 등을 반드시 고려해야 합니다.

2. 취약한 코드 예제 – URL 검증 없이 요청 수행

아래 코드는 사용자가 전달한 url 파라미터를 그대로 사용하여 서버에서 외부 요청을 수행합니다. 입력값에 대한 검증 없이 RestTemplate이나 HttpURLConnection을 사용할 경우, 내부 시스템이나 클라우드 메타데이터에 접근할 수 있는 위험한 SSRF 취약점이 발생할 수 있습니다.

@GetMapping(\"/fetch\")
public ResponseEntity<String> fetch(@RequestParam String url) {
    RestTemplate restTemplate = new RestTemplate();
    String result = restTemplate.getForObject(url, String.class); // 검증 없음
    return ResponseEntity.ok(result);
}

※ 공격자가 http://localhost:8080/admin 또는 http://169.254.169.254/latest/meta-data/ 등 민감한 내부 주소를 입력할 경우, 서버는 내부 리소스를 대신 호출하게 되어 정보 유출이나 내부 스캔 등의 공격에 노출될 수 있습니다.

3. 안전한 코드 예제 – 화이트리스트 기반 SSRF 차단

다음 예제는 사용자로부터 전달받은 URL을 직접 사용하지 않고, 사전에 등록된 도메인 화이트리스트에 포함된 URL만 호출하도록 제한합니다. 또한 내부 IP 및 로컬 주소에 대한 정규식 필터링도 포함되어 있습니다.

@GetMapping(\"/safe-fetch\")
public ResponseEntity<String> safeFetch(@RequestParam String url) throws URISyntaxException {
    URI uri = new URI(url);
    String host = uri.getHost();

    // 1. 내부 IP, 로컬호스트 필터링
    if (host.matches(\"^(localhost|127\\\\.0\\\\.0\\\\.1|0:0:0:0:0:0:0:1|169\\\\.254\\\\..*)$\")) {
        return ResponseEntity.status(HttpStatus.FORBIDDEN).body(\"내부 주소 접근 차단됨\");
    }

    // 2. 허용 도메인 목록 설정
    List<String> allowList = Arrays.asList(\"api.example.com\", \"news.example.org\");
    if (!allowList.contains(host)) {
        return ResponseEntity.status(HttpStatus.FORBIDDEN).body(\"허용되지 않은 외부 주소입니다\");
    }

    // 3. 요청 수행
    RestTemplate restTemplate = new RestTemplate();
    String result = restTemplate.getForObject(uri.toString(), String.class);
    return ResponseEntity.ok(result);
}

※ URI 객체를 사용해 도메인을 추출하고, 내부 IP 패턴을 필터링함으로써 의도하지 않은 내부망 접근을 차단합니다. 프로덕션 환경에서는 DNS 재확인, 네트워크 계층의 접근 제한(Security Group, 방화벽 등)도 병행되어야 합니다.

4. 실무 Q&A – 서버사이드 요청 위조 대응

Q URL 검증만으로 SSRF를 완벽히 막을 수 있나요?

아닙니다. URL 필터링은 기본이고, 네트워크 계층에서 메타데이터 주소나 내부망 접근 자체를 방어하는 것이 핵심입니다. 클라우드 환경이라면 보안그룹과 VPC 설정이 매우 중요합니다.

Q SSRF 필터는 Spring Security로도 설정할 수 있나요?

Spring Security 자체로 URL 검증은 어렵지만, 필터나 인터셉터를 활용해 외부 요청 전 HostURI 검사를 적용할 수 있습니다. 다만 사용자 입력 전처리 단계에서 방지하는 것이 더 안전합니다.

Q SSRF는 클라우드 환경에서 더 위험한가요?

그렇습니다. AWS의 경우 169.254.169.254 메타데이터 서비스에 접근해 인스턴스 권한을 탈취할 수 있기 때문에, IAM 역할 보호 및 네트워크 격리가 중요합니다. GCP, Azure도 유사한 경로가 존재합니다.

Q SSRF 방어를 위한 오픈소스 도구가 있나요?

SSRFMap, NoSSRF, SSRF-Detector 등과 같은 도구를 통해 요청 패턴을 검출하고, 우회된 URL 형태도 탐지할 수 있습니다. 네트워크 레벨에서 WAF와 IDS 조합도 효과적입니다.

5. 핵심 요약

  • SSRF는 서버가 외부 URL을 호출할 때 발생하는 심각한 보안 취약점입니다.
  • RestTemplate, HttpClient 사용 시 사용자 입력값을 검증하지 않으면 내부망이 노출될 수 있습니다.
  • URI 파싱 및 호스트 필터링, 내부 IP 차단, 도메인 화이트리스트 설정이 핵심 방어 전략입니다.
  • 클라우드 환경에서는 메타데이터 보호, VPC 방화벽 구성, IAM 권한 설정을 병행해야 합니다.
  • 실제 운영 서비스에는 SSRF 탐지 도구 및 요청 로깅도 함께 구성하는 것이 좋습니다.
반응형