우아한테크코스 테코톡

꾹이의 SSRF

https://youtu.be/wYIdOgrSW0E?si=bDIvHOkK9l_2fvMI

— 서버가 대신 요청하는 순간, 공격이 시작된다

이 글은 꾹이의 SSRF 영상을 보고 정리한 내용에 실무 관점에서 왜 위험한지, 왜 자주 터지는지를 보강한 글이다.

SSRF는 화려한 해킹 기법이 아니라, “서버가 너무 친절할 때” 발생하는 취약점이다.

꾹이의 SSRF


OWASP

  • OWASP(Open Worldwide Application Security Project)는 애플리케이션 보안을 연구·전파하는 비영리 국제 단체
  • OWASP에서 발표하는 자료 중 가장 널리 알려진 것이 OWASP TOP 10

    • OWASP TOP 10은 약 4~5년 주기로 발표
    • 실제 공격 통계 + 보안 전문가 의견을 바탕으로 가장 위험하고 빈번한 취약점 10가지를 정리

OWASP TOP 10 (2021)

  • 부적절한 인가
  • 암호화 실패
  • Injection (삽입 공격)
  • 안전하지 않은 설계
  • 보안 설정 미흡
  • 취약하고 업데이트되지 않은 컴포넌트 사용
  • 식별 및 인증 실패
  • 소프트웨어 및 데이터 무결성 실패
  • 보안 로깅 및 모니터링 실패
  • 서버 사이드 요청 위조 (SSRF)

👉 SSRF는 특히 클라우드 환경에서 위험도가 급격히 올라간다.


SSRF

  • SSRF(Server-Side Request Forgery)는 공격자가 서버가 대신 요청을 하도록 조작하는 공격

중요한 포인트는 이거다.

공격자는 직접 내부망에 접근하지 않는다 서버의 권한을 빌려 접근한다


SSRF 공격 흐름

  1. 공격자는 먼저 프라이빗 서브넷에 접근하려고 한다
  2. 이 서브넷은 외부 인터넷에서 직접 접근할 수 없다
  3. 공격자는 악의적인 요청을 보내 취약 서버가 대신 요청하도록 유도
  4. 취약 서버는 내부 데이터 서버로 요청
  5. 데이터 서버는 “신뢰된 서버 요청”이라 판단하고 응답
  6. 응답은 다시 공격자에게 전달된다

루프백 공격

  • 127.0.0.1, localhost를 이용
  • 취약 서버가 자기 자신에게 요청
  • 내부 관리자 API, 설정 정보 노출 가능

👉 신뢰 경계를 우회하는 구조가 SSRF의 본질이다.


어떠한 요청이 서버로 하여금 대신 요청하게 만드는가

SSRF는 “특별한 공격 요청”이 아니라 취약한 코드 설계에서 시작된다.

SSRF 취약점 예시 코드

@GetMapping("/fetch-data")
public ResponseEntity<String> fetchData(@RequestParam String url) {
    RestTemplate restTemplate = new RestTemplate();
    String response = restTemplate.getForObject(url, String.class);
    return ResponseEntity.ok(response);
}
  • url 파라미터는 외부 입력값
  • 서버는 이 값을 검증 없이 사용
  • 공격자는 내부 네트워크 주소를 주입 가능

공격 예시

  • http://localhost:8080/admin
  • http://127.0.0.1:8080/internal
  • http://169.254.169.254/latest/meta-data/

클라우드 환경에서 SSRF가 특히 위험한 이유

인스턴스 메타데이터 공격

  • http://169.254.169.254/latest/meta-data/
  • EC2 인스턴스 메타데이터 조회 주소

이 주소를 통해 노출될 수 있는 정보:

  • IAM Role
  • Security Credentials
  • Public IP
  • Security Group
  • 경우에 따라 S3 접근 권한

👉 SSRF = 클라우드 권한 탈취의 출발점

AWS뿐 아니라:

  • GCP
  • Azure 모두 유사한 메타데이터 서비스가 존재한다.

SSRF 공격 대응 방안

블랙 리스트

  • 예외적으로 차단할 대상을 지정하는 방식
  • 차단 권장 항목

    • IP 주소
    • 도메인
    • URL 패턴
    • 호스트 이름
    • 포트 번호
    • 프로토콜
    • IP 대역
@GetMapping("/fetch-data")
public ResponseEntity<String> fetchData(@RequestParam String url) {
    if (isBlacklisted(url)) {
        return ResponseEntity.status(HttpStatus.FORBIDDEN)
            .body("Access to this URL is forbidden.");
    }
    RestTemplate restTemplate = new RestTemplate();
    String response = restTemplate.getForObject(url, String.class);
    return ResponseEntity.ok(response);
}

블랙리스트의 한계

  • “알고 있는 위험”만 막을 수 있다
  • 우회 경로가 존재

블랙리스트 회피 방식 (리다이렉트)

  • 공격자는 중간 서버를 준비
  • 취약 서버는 공격자 서버로 요청
  • 공격자 서버는 302 Redirect로 내부 주소 반환
  • 취약 서버가 리다이렉트를 따라가며 내부 접근
// 공격자가 예시로 이렇게 취약 서버에 이렇게 요청 com?url=http://attacker.com/redirect
@GetMapping("/redirect")
public ResponseEntity<Void> redirectToMetadata() {
    HttpHeaders headers = new HttpHeaders();
    headers.setLocation(
        URI.create("http://169.254.169.254/latest/meta-data/")
    );
    return ResponseEntity.status(HttpStatus.FOUND)
        .headers(headers)
        .build();
}

👉 리다이렉트 차단은 필수


화이트 리스트

  • 명시적으로 허용된 요청만 통과
  • 보안 수준은 상대적으로 높음
@GetMapping("/fetch-data")
public ResponseEntity<String> fetchData(@RequestParam String url) {
    if (!isSafe(url)) {
        return ResponseEntity.status(HttpStatus.FORBIDDEN)
            .body("Access to this URL is forbidden.");
    }
    RestTemplate restTemplate = new RestTemplate();
    String response = restTemplate.getForObject(url, String.class);
    return ResponseEntity.ok(response);
}

화이트리스트 회피 — DNS Rebinding

  1. 공격자는 자신의 DNS 서버 사용
  2. 최초 DNS 응답 → 정상 IP (TTL 매우 짧음)
  3. 서버는 검증 통과
  4. TTL 만료
  5. 재조회 시 내부 IP 반환
  6. 서버는 내부 서비스로 요청

👉 검증 시점과 요청 시점의 IP 불일치가 공격 포인트


IMDSv2 (AWS 기준)

  • Instance Metadata Service Version 2
  • EC2 기본 설정이 IMDSv1(Optional)인 경우 SSRF에 취약

IMDSv1

  • GET 요청만으로 메타데이터 조회 가능

IMDSv2

  • PUT 요청으로 토큰 발급
  • 토큰을 헤더에 포함해야 접근 가능
  • 단순 GET 기반 SSRF 방어 효과 큼

Metadata Hop Limit

  • 요청이 거칠 수 있는 네트워크 hop 제한
  • 기본값: 1

공격자 서버 → 취약 서버 → 메타데이터 → hop 초과로 차단

👉 리다이렉트 기반 SSRF 방어 가능


코드를 설계할 때 반드시 인지해야 할 점

  • 외부 입력으로 URL을 받는 순간 SSRF 가능성 존재
  • HTTP Client(RestTemplate, WebClient) 사용 시 항상 의심
  • IDE 경고, SAST 분석 결과 무시하지 않기
  • “이 요청은 정말 서버가 해야 하는가?” 질문하기

정리

  • SSRF는 서버의 권한을 악용하는 공격
  • 단일 방어책은 존재하지 않는다
  • 블랙리스트 + 화이트리스트 + 리다이렉트 차단
  • 클라우드 환경에서는 IMDSv2 필수
  • 무엇보다 설계 단계에서의 인식이 가장 중요

SSRF는 서버가 너무 믿어준 결과다.



© 2020. All rights reserved.

SIKSIK