서버 측 요청 위조 (SSRF)

사이버 보안Beginner
지금 연습하기

소개

서버 측 요청 위조 (SSRF, Server-Side Request Forgery) 는 공격자가 서버 측 애플리케이션을 유도하여 공격자가 선택한 임의의 도메인으로 HTTP 요청을 보내게 만드는 웹 보안 취약점입니다.

핵심은 공격자가 직접 요청을 보내는 것이 아니라 서버가 요청을 수행한다는 점입니다. 즉, 해당 요청은 서버의 네트워크 위치, 신뢰 관계, 그리고 내부 전용 대상에 대한 접근 권한을 그대로 상속받게 됩니다.

일반적인 SSRF 공격에서 공격자는 서버가 조직 인프라 내의 내부 전용 서비스에 연결하도록 만들 수 있습니다. 다른 경우에는 서버가 임의의 외부 시스템에 연결하도록 강제하여 인증 자격 증명과 같은 민감한 데이터를 유출할 수도 있습니다.

이 실습에서는 시뮬레이션된 취약한 웹 애플리케이션과 상호 작용합니다. SSRF 취약점을 식별하는 방법, 기본적인 보안 필터가 악성 요청을 차단하려는 방식을 관찰하는 방법, 이러한 필터를 우회하는 방법, 그리고 궁극적으로 민감한 내부 데이터와 시뮬레이션된 클라우드 메타데이터를 추출하는 방법을 배웁니다. 공유 실습 환경과의 호환성을 유지하기 위해, 시뮬레이션된 메타데이터 서비스는 포트 80 대신 권한이 필요 없는 높은 포트를 사용합니다.

URL 매개변수 식별

이 단계에서는 외부 URL 에서 데이터를 가져오는 애플리케이션 기능을 찾아 잠재적인 SSRF 취약점을 식별하는 방법을 배웁니다.

많은 웹 애플리케이션은 다른 서버에서 리소스를 가져와야 합니다. 예를 들어, 애플리케이션이 소셜 미디어 사이트에서 프로필 사진을 가져오거나 타사 API 에서 데이터를 검색할 수 있습니다. 애플리케이션이 사용자 입력으로 URL 을 받아 적절한 검증 없이 이를 가져오는 경우, SSRF 에 취약할 수 있습니다.

이것이 바로 SSRF 가 종종 합법적인 "URL 가져오기" 기능에서 나타나는 이유입니다. 위험한 동작이 제품 관점에서는 정상적으로 보이는 워크플로우 내부에 숨겨져 있기 때문입니다.

포트 8080에서 실행되는 취약한 웹 애플리케이션이 준비되어 있습니다. 이 애플리케이션에는 url 매개변수를 허용하는 /check 엔드포인트가 있습니다. 이 엔드포인트는 외부 웹사이트의 상태를 확인하도록 설계되었습니다.

http://example.com과 같이 안전한 외부 웹사이트를 가져오도록 애플리케이션에 요청하여 이 기능을 테스트할 수 있습니다. 터미널에서 curl 명령을 사용하여 취약한 애플리케이션에 HTTP GET 요청을 보냅니다. curl이 생소하다면, 요청을 보내고 서버의 응답을 터미널에 출력하는 간단한 명령줄 웹 브라우저라고 생각하면 됩니다.

curl "http://localhost:8080/check?url=http://example.com"

이 명령을 실행하면 포트 8080에서 실행 중인 취약한 애플리케이션이 요청을 수신하고, url 매개변수를 추출한 뒤 http://example.com으로 자체 HTTP 요청을 보냅니다. 그런 다음 HTML 응답을 다시 반환합니다.

<!doctype html>
<html>
<head>
    <title>Example Domain</title>
...

서버가 요청된 URL 의 콘텐츠를 성공적으로 가져와 반환하는 것을 확인함으로써, url 매개변수가 실제로 처리되고 서버 측 요청을 만드는 데 사용되고 있음을 확인했습니다. 이것이 SSRF 취약점의 첫 번째 징후입니다.

Localhost(127.0.0.1) 를 대상으로 SSRF 테스트

이 단계에서는 SSRF 취약점을 악용하여 서버에서 실행 중인 내부 서비스에 접근을 시도합니다.

SSRF 의 주요 위험은 요청을 수행하는 서버가 네트워크상에서 특권적인 위치에 있는 경우가 많다는 점입니다. 이 서버는 공용 인터넷에 노출되지 않은 내부 서비스에 접근할 수 있습니다. 이 시나리오에서는 포트 5000에서 실행되는 내부 관리자 패널이 있습니다. 이 관리자 패널은 127.0.0.1(localhost) 에 바인딩되어 있어, 다른 기기가 아닌 서버 자체에서만 접근할 수 있습니다. 127.0.0.1은 컴퓨터가 자기 자신과 통신하는 것으로 생각하면 됩니다.

공격자로서 당신은 포트 8080의 SSRF 취약점을 사용하여 서버가 당신을 대신해 포트 5000의 관리자 패널에 접근하도록 속일 수 있습니다.

해당 로컬 URL 을 취약한 /check 엔드포인트에 전달하여 내부 관리자 패널에 접근을 시도해 보세요.

curl "http://localhost:8080/check?url=http://127.0.0.1:5000/admin"

이 명령을 실행하면 요청이 성공하지 않는 것을 알 수 있습니다. 대신 오류 메시지가 표시됩니다.

Error: Localhost access is blocked by WAF!

개발자들은 종종 SSRF 공격을 방지하기 위해 웹 애플리케이션 방화벽 (WAF) 이나 입력 필터를 구현합니다. 이 경우, 애플리케이션은 제공된 URL 에 127.0.0.1 또는 localhost라는 문자열이 포함되어 있는지 확인합니다. 귀하의 입력이 이 필터와 일치했기 때문에 애플리케이션이 요청을 차단한 것입니다.

단순한 문자열 필터는 네트워크 대상이 여러 가지 동등한 표현을 가질 수 있기 때문에 취약합니다. 방어자는 단순히 문자열만 비교하는 것이 아니라, 네트워크상의 의미를 이해하는 검증 방식을 사용해야 합니다.

애플리케이션이 입력을 필터링하는 방식을 이해하는 것은 SSRF 를 악용하는 데 중요한 단계이며, 어떤 제한을 우회해야 하는지 알려줍니다.

입력 필터 우회

이 단계에서는 이전 단계에서 마주친 기본적인 입력 필터를 우회하는 방법을 배웁니다.

우회 기술이 작동하는 이유는 URL 파싱, 호스트 이름 확인, 입력 필터링이 항상 동일한 해석 규칙을 사용하지 않기 때문입니다.

단순한 문자열 일치 (예: 127.0.0.1 차단) 에 의존하는 입력 필터는 IP 주소를 여러 방식으로 표현할 수 있기 때문에 종종 결함이 있습니다. 운영 체제의 네트워크 스택은 이러한 대체 표현들을 여전히 동일한 대상으로 해석하지만, 애플리케이션의 텍스트 필터는 이를 인식하지 못할 수 있습니다.

잘못 구현된 필터를 우회할 수 있는 localhost IP 주소 (127.0.0.1) 의 일반적인 표현 방식은 다음과 같습니다. 127.1과 같은 단축 IP, 2130706433과 같은 10 진수 IP, 0177.000.000.001과 같은 8 진수 IP, 또는 0x7f000001과 같은 16 진수 IP 를 사용할 수 있습니다.

애플리케이션은 정확히 127.0.0.1과 localhost 문자열만 차단하므로, 단축 IP 표현인 127.1을 사용하여 필터를 우회하고 내부 관리자 패널에 접근할 수 있습니다.

다음 명령을 실행하여 우회 기술을 테스트해 보세요.

curl "http://localhost:8080/check?url=http://127.1:5000/admin"

127.1은 차단된 문자열과 일치하지 않으므로 애플리케이션이 요청을 허용합니다. 서버의 네트워크 스택은 127.1을 127.0.0.1로 해석하고 내부 관리자 페이지를 성공적으로 가져옵니다.

Welcome to the Internal Admin Panel. Secret Key: SSRF_ADMIN_SUCCESS

입력 필터를 성공적으로 우회하고 SSRF 취약점을 악용하여 제한된 내부 서비스에 접근했습니다.

내부 메타데이터 접근

이 단계에서는 SSRF 취약점을 사용하여 민감한 클라우드 메타데이터에 접근합니다.

애플리케이션이 클라우드 환경 (AWS, Google Cloud, Azure 등) 에서 호스팅될 때, 종종 169.254.169.254라는 특별한 비라우팅 (non-routable) IP 주소에 접근할 수 있습니다. 이 주소는 실행 중인 클라우드 인스턴스에 대한 정보를 제공하는 인스턴스 메타데이터 서비스 (IMDS) 를 호스팅하며, 여기에는 매우 민감한 임시 IAM(Identity and Access Management) 자격 증명이 포함될 수 있습니다. "비라우팅"이란 이 주소가 일반적인 공용 인터넷 접근이 아닌 로컬 클라우드 인프라를 위한 것임을 의미합니다.

공격자가 클라우드 호스팅 애플리케이션에서 SSRF 취약점을 발견하면, 이 메타데이터 엔드포인트를 쿼리하는 것이 클라우드 환경 전체를 장악할 수 있는 핵심 목표가 되는 경우가 많습니다.

이 실습 환경에서는 시뮬레이션된 클라우드 메타데이터 서비스가 169.254.169.254:8000에서 실행 중입니다. 실제 클라우드 메타데이터 서비스는 일반적으로 포트 80을 사용하지만, 이 실습에서는 특별한 권한 없이 서비스를 시작하고 다른 소프트웨어와 충돌하지 않도록 의도적으로 포트 8000을 사용합니다. 먼저 SSRF 취약점을 사용하여 사용 가능한 메타데이터 디렉터리를 나열해 보세요.

curl "http://localhost:8080/check?url=http://169.254.169.254:8000/latest/meta-data/"

서버가 메타데이터 디렉터리 목록을 가져와 반환합니다.

iam/security-credentials/admin-role

출력 결과에서 admin-role이라는 IAM 역할을 확인할 수 있습니다. 이제 이 경로를 SSRF 페이로드에 추가하여 이 역할과 관련된 실제 보안 자격 증명을 추출할 수 있습니다.

다음 명령을 실행하여 민감한 자격 증명을 검색하세요.

curl "http://localhost:8080/check?url=http://169.254.169.254:8000/latest/meta-data/iam/security-credentials/admin-role"

시뮬레이션된 메타데이터 서비스가 JSON 형식의 자격 증명을 반환합니다.

{"AccessKeyId":"AKIAIOSFODNN7EXAMPLE","SecretAccessKey":"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"}

환경에서 데이터가 반환되지 않으면 /tmp/meta.log를 확인하여 169.254.169.254:8000에서 서비스가 수신 대기 중인지 확인하세요.

이 자격 증명을 성공적으로 추출함으로써 클라우드 환경에서 SSRF 취약점이 미치는 심각한 영향을 입증했습니다.

요약

이 실습에서는 서버 측 요청 위조 (SSRF) 취약점을 탐색하고 악용하는 방법을 성공적으로 실습했습니다. 서버 측 가져오기 동작을 관찰하여 취약한 URL 매개변수를 식별하는 방법을 배웠습니다. 또한 로컬 접근을 차단하도록 설계된 기본적인 입력 필터를 마주하고, 대체 IP 주소 표현을 사용하여 이를 성공적으로 우회했습니다. 마지막으로 민감한 시뮬레이션 클라우드 메타데이터 자격 증명을 추출함으로써 SSRF 의 치명적인 영향을 입증했습니다. 이러한 기술을 이해하는 것은 보안 평가 중에 취약점을 식별하고 웹 애플리케이션에 강력한 방어 체계를 구현하는 데 필수적입니다.