보안에 오래 종사하다 보면 결국 '기능'이 보이지 않고 잠재적인 공격 경로가 보이기 시작하는 나쁜 습관이 생깁니다. 최근 "사용자 지정 GPT를 사용하여 해킹된 ChatGPT가 SSRF 취약점을 악용하여 기밀을 노출한 사례"는 교과서적인 예시입니다. 사용자 지정 GPT를 위한 편리한 작업 기능처럼 보였던 것이 알고 보니 OpenAI의 클라우드 환경으로 바로 연결되는 터널이었습니다. 아주 오래된 버그인 서버 측 요청 위조가 새로운 플랫폼에서 재발견된 것일 뿐, 이국적인 프롬프트 마법이나 'AI 마법'이 잘못 사용된 것은 아니었습니다.
이것이 바로 이번 사건이 중요한 이유입니다. 이 사건은 AI의 악행에 대한 또 다른 과장된 헤드라인이 아닙니다. 실제 인프라에 LLM을 도입하면 기존의 애플리케이션 및 클라우드 보안 규칙이 복수를 위해 다시 돌아온다는 사실을 상기시켜 줍니다. 모델은 새로운 것일 수 있지만 근본적인 실수는 그렇지 않습니다.
익스플로잇 재구성: '액션 추가'에서 클라우드 토큰까지
무슨 일이 일어났는지 이해하려면 사용자 지정 GPT가 어떻게 작동하는지 살펴봐야 합니다. OpenAI의 인터페이스를 사용하면 OpenAPI 스키마를 기반으로 GPT가 호출할 수 있는 외부 HTTP API인 액션을 정의할 수 있습니다. 사용자 입장에서는 데이터를 가져오고, 워크플로를 트리거하고, 내부 시스템에 연결할 수 있는 등 GPT에 '초능력'을 부여한 것과 같은 느낌입니다. 내부적으로는 OpenAI의 인프라 내부에서 실행되는 백엔드 HTTP 클라이언트가 사용자가 설명한 URL을 호출하고 응답을 모델에 다시 공급한다는 의미입니다.
Open Security의 한 연구원이 바로 그 점을 발견했습니다. 사용자 지정 GPT를 사용하면서 익숙한 패턴, 즉 사용자가 제어하는 URL, 실시간 요청을 전송하는 '테스트' 버튼, 클라우드 환경 내부에서 실행되는 서버를 발견한 것이죠. 클라우드 펜 테스트를 해본 사람이라면 누구나 본능적으로 해당 서버가 사용자를 대신해 내부 주소를 호출하도록 속일 수 있는지 확인해야 한다는 사실을 알아차릴 것입니다. 이것이 바로 SSRF의 본질입니다.
클라우드 환경에서 가장 중요한 내부 대상은 거의 항상 메타데이터 서비스입니다. Azure에서는 다른 클라우드와 마찬가지로 링크-로컬 주소에 위치합니다. 169.254.169.254. VM 또는 컨테이너 내부에서 이 엔드포인트는 인스턴스에 대한 세부 정보를 표시할 수 있으며, 더 중요한 것은 워크로드가 클라우드 관리 API를 호출할 수 있는 단기 토큰을 발행할 수 있다는 점입니다. 클라우드 외부에서는 접근할 수 없습니다. 서버의 유리한 지점을 탈취하여 외부 공격자가 할 수 없는 일을 서버가 하도록 강제하는 것이 바로 SSRF가 중요한 이유입니다.
연구원의 첫 번째 장애물은 사용자 지정 GPT 작업은 HTTPS URL만 허용하는 반면 메타데이터 서비스는 HTTP 전용이라는 점이었습니다. 언뜻 보기에는 이 제한이 방어책처럼 보이지만 실제로는 퍼즐 조각이 하나 더 추가된 것에 불과합니다. 해결 방법은 간단했습니다. 연구자가 제어하는 외부 HTTPS 도메인을 등록하고, 해당 도메인이 302 리디렉션을 통해 http://169.254.169.254 메타데이터 URL을 확인하고 액션 백엔드가 리디렉션을 따랐는지 확인합니다. 그랬죠. 갑자기 사용자 지정 GPT 구성에서 무해해 보이는 HTTPS 호출이 내부 클라우드 메타데이터 엔드포인트에 대한 HTTP 호출을 발생시켰습니다.
하지만 Azure의 메타데이터 서비스는 완전히 순진한 것은 아닙니다. 일반적인 남용을 방지하기 위해 특별한 헤더를 요구합니다, 메타데이터: true를 추가합니다. 헤더가 누락되면 서비스는 실제 데이터 공개를 거부합니다. 이 시점에서는 Actions를 정의하는 데 사용되는 OpenAPI 스키마 인터페이스가 임의의 헤더 구성을 노출하지 않기 때문에 시스템이 다시 안전하다고 보일 수 있습니다. 그러나 대규모 시스템에는 구성 표면이 하나만 있는 경우가 거의 없습니다. 이 경우 Actions 기능은 외부 서비스를 연결할 때 정의할 수 있는 "API 키" 및 기타 인증 헤더에 대한 아이디어도 지원합니다. 그러면 이러한 헤더가 아웃바운드 요청에 자동으로 첨부됩니다.
그것으로 체인을 완성하기에 충분했습니다. 헤더 이름 그대로인 가짜 'API 키'를 정의함으로써 메타데이터 그리고 그 가치는 true를 사용하여 백엔드에 Azure IMDS가 예상하는 정확한 헤더를 포함하도록 설득했습니다. 이를 리디렉션 트릭과 결합하면 이제 사용자 지정 GPT 작업 백엔드에서 메타데이터 서비스로의 SSRF 채널이 유효한 메타데이터: true 헤더.
이 채널이 설정되고 나면 나머지는 거의 기계적으로 진행되었습니다. 연구원은 잘 알려진 IMDS 경로를 사용하여 메타데이터 서비스에 Azure 관리 API를 위한 OAuth2 토큰을 요청했습니다. 응답에는 ChatGPT 인프라가 사용 중인 클라우드 ID에 바인딩된 액세스 토큰이 포함되어 있었습니다. 이 토큰은 최소한 관리 엔드포인트를 쿼리할 수 있으며, ID의 권한에 따라 민감한 리소스에 접근할 수도 있었습니다. 그 시점에서 연구자는 작업을 중단하고 OpenAI의 버그 바운티 프로그램을 통해 발견 사실을 보고했고, OpenAI는 이 결함을 심각도가 높은 것으로 분류하여 패치를 진행했습니다.
이 연쇄 공격이 놀라운 이유는 공격자가 셸 액세스, 소스 코드 또는 HTTP 스택의 고전적인 버그가 전혀 필요하지 않았다는 점입니다. 모든 것이 정상적인 설정 화면 내에서 이루어졌습니다: URL, 인증 설정, 테스트 버튼 등 모든 것이 정상적인 설정 화면 내에서 이루어졌습니다.

SSRF 스타일 프로브의 작은 코드 스케치
이를 보다 구체적으로 설명하기 위해 보안 엔지니어가 '액션 스타일' HTTP 클라이언트를 정상적으로 검사하는 데 사용할 수 있는 아주 작은 내부 헬퍼 스크립트를 상상해 보세요. 목표는 프로덕션 환경에서 실제 메타데이터 서비스를 공격하는 것이 아니라 스테이징 또는 실험실 환경에서 예기치 않은 리디렉션과 내부 IP 홉을 조사하는 습관을 코딩하는 것입니다:
요청 가져오기
urllib.parse에서 urljoin 가져오기
def trace_request(base_url: str, path: str = "/"):
url = urljoin(base_url, path)
print(f"[+] {url} 요청 중")
try:
resp = requests.get(url, timeout=3, allow_redirects=True)
예외를 e로 제외합니다:
print(f"[!] Error: {e}")
반환
print(f"[+] 최종 URL: {resp.url}")
print(f"[+] Status: {resp.status_code}")
print("[+] 리디렉션 체인:")
resp.history의 h에 대해
print(f" {h.status_code} -> {h.headers.get('Location')}")
# 매우 대략적인 휴리스틱: 내부 IP에 착륙한 경우 경고
resp.raw._connection 및 hasattr(resp.raw._connection, "sock"):
peer = resp.raw._connection.sock.getpeername()[0]
print(f"[+] Peer IP: {peer}")
peer.startswith("10.") 또는 peer.startswith("192.168.") 또는 peer.startswith("169.254."):
print("[!] 경고: 백엔드가 내부 주소로 리다이렉트되었습니다.")
if __name__ == "__main__":
# 예제: 자체 실험실에서 제어된 테스트 엔드포인트로 교체하기
trace_request("")
이와 같은 스크립트는 "ChatGPT를 악용"하지는 않지만, 안전한 것으로 추정되는 외부 URL에서 시작하여 리디렉션을 따르고, HTTP 클라이언트가 갑자기 내부 또는 링크 로컬 IP 범위와 대화하는 것을 발견하면 큰 소리로 불평하는 등 동일한 조사 형태를 포착할 수 있습니다. 이러한 패턴을 자동화로 전환하고 자체 AI 액션을 구동하는 구성 요소에 대해 실행하는 것은 단순히 인시던트를 읽는 것보다 훨씬 더 유용합니다.
'AI 버그'가 아니라 새로운 단계의 구식 클라우드 악용입니다.
"ChatGPT가 해킹당했다"고 읽고 넘어가고 싶을 수도 있습니다. 하지만 그런 프레임은 더 깊은 교훈을 놓치게 됩니다. 모델 자체가 잘못 작동한 것은 아닙니다. 어떻게든 금지된 기능을 잠금 해제하라는 메시지가 표시되지 않았습니다. LLM은 지시를 받은 대로 작업을 호출하고 결과를 읽고 요약했습니다. 취약점은 전적으로 LLM과 외부 세계 사이의 접착제에 있었습니다.
보안팀이 집중해야 할 부분은 바로 이 부분입니다. LLM에 도구, 작업 또는 플러그인을 호출할 수 있는 기능을 부여하면 인프라에서 효과적으로 프로그래밍 가능한 클라이언트로 전환하는 것입니다. 과거에는 사용자가 수동으로 API를 호출하고 개발자가 그 입력을 검토했습니다. 이제 사용자가 모델에 지시를 내리면 모델이 이를 대신 API 호출로 변환합니다. 이 모델은 적대적인 의도가 백엔드에 도달할 수 있는 또 다른 경로가 됩니다.
이러한 관점에서 보면 이번 사고는 다른 의상을 입은 OWASP SSRF에 불과합니다. 사용자가 영향을 받은 URL, 내부 또는 권한이 있는 엔드포인트에 도달할 수 있는 서버, 누락되거나 불완전한 송신 제어, 일반 워크로드에서 너무 쉽게 접근할 수 있는 클라우드 메타데이터 서비스 등 조건은 모두 익숙합니다. 차이점은 진입점이 더 이상 기존의 웹 양식이나 JSON 필드가 아니라 사용자 지정 GPT를 더욱 강력하게 만들기 위해 설계된 구성 블록이라는 점입니다.
이것이 바로 폭발 반경이 중요한 이유이기도 합니다. 영향을 받은 서버는 임의의 마이크로서비스가 아니라 OpenAI의 Azure 환경 내에 있는 ChatGPT의 멀티테넌트 인프라의 일부였습니다. IMDS를 통해 획득한 모든 토큰은 이미 의미 있는 액세스 권한이 있는 워크로드에 속해 있었습니다. 로컬 방어가 공격자가 할 수 있는 일을 제한하더라도 위험 프로필은 잊혀진 테스트 가상 머신과는 근본적으로 다릅니다.
통합 허브로서의 AI: 공격 표면을 넓히고 신뢰의 경계를 허물다
이 버그 뒤에 숨겨진 더 흥미로운 이야기는 아키텍처입니다. AI 플랫폼은 빠르게 통합 허브로 자리 잡고 있습니다. 영업팀을 위한 맞춤형 GPT는 CRM, 청구 시스템, 문서 저장소와 대화할 수 있습니다. 보안에 중점을 둔 GPT는 스캐너, 티켓팅 시스템, CI/CD와 연결될 수 있습니다. 각각의 경우 LLM이 자산이 아니라 해당 커넥터 뒤에 있는 데이터와 작업이 자산입니다.
이러한 현실을 받아들이면 사고의 위협 모델도 바뀌어야 합니다. 'AI 보안'을 계속 즉각적인 주입, 데이터 유출 또는 유해한 결과물로만 생각해서는 안 됩니다. 또한 네트워크 경계, 클라우드 ID, 테넌트 격리에 대해서도 깊이 있는 질문을 던져야 합니다.
내 작업을 실행하는 인프라가 실제로 네트워크에서 어떤 것과 통신할 수 있나요? 많은 클라우드 환경의 기본값은 "DNS가 확인되는 한 모든 아웃바운드가 허용됩니다."입니다. 이는 서비스가 비교적 단순하고 엔지니어가 유연성을 원할 때 적합했습니다. 하지만 LLM 플랫폼을 중간에 배치하면 모든 테넌트가 코드가 아닌 설정을 통해 새로운 아웃바운드 대상을 제안할 수 있는 방법이 생깁니다. 강력한 이그레스 정책이 없다면 사실상 프로그래밍 가능한 SSRF 런처를 만든 것이나 마찬가지입니다.
이러한 워크로드에서 사용하는 ID는 실제로 얼마나 많은 권한을 가지고 있나요? ChatGPT 사례에서 연구원들은 Azure 관리 API에 대한 토큰을 요청할 수 있었습니다. 이 토큰은 역할 할당에 의해 제한되었지만 여전히 높은 가치의 비밀을 나타냅니다. 많은 조직에서 '플랫폼 인프라'에 광범위한 권한을 부여하려는 유혹이 강한데, 이는 배포를 간소화하기 때문입니다. 사용자 입력에 의해 간접적으로 구동될 수 있는 모든 것, 특히 AI를 통해 구동될 수 있는 모든 것의 경우 이러한 유혹은 위험합니다.
테넌트 간, 컨트롤 플레인과 데이터 플레인 간, AI 런타임과 나머지 클라우드 간의 신뢰 경계는 정확히 어디에 있을까요? 잘 설계된 시스템은 하나의 테넌트 구성이 적대적일 수 있고, 해당 테넌트를 대신하여 발신하는 모든 호출이 적대적일 수 있으며, 액션에서 메타데이터, 관리 API로의 모든 승격이 현실적인 공격자의 목표가 될 수 있다고 가정해야 합니다. 이러한 관점에서는 엄격한 네트워크 세분화, 정책을 시행하는 컴패니언 사이드카, 전용 서비스 ID와 같은 패턴은 "있으면 좋은" 것이 아니라 협상할 수 없는 것이 됩니다.
하나의 인시던트에서 반복 가능한 테스트 방법론까지
방어자와 빌더에게 이 사례의 진정한 가치는 특정 버그가 아니라 테스트 사고방식에 있습니다. 연구자는 기본적으로 사용자 정의 GPT 액션을 낯설고 새로운 종류의 HTTP 클라이언트로 취급한 다음 익숙한 체크리스트를 통해 URL을 제어할 수 있는지, 내부 호스트에 도달할 수 있는지, 리디렉션을 악용할 수 있는지, 헤더를 삽입할 수 있는지, 메타데이터를 칠 수 있는지, 클라우드 토큰으로 전환할 수 있는지 등을 살펴봤습니다.
이러한 정신적 체크리스트가 바로 최신 AI 플랫폼용 모의 침투 테스트 워크플로우에서 자동화되어야 하는 부분입니다. 팀들은 헤드라인과 포상금 보고서를 기다리는 대신 자체적인 맞춤형 GPT 인프라, 플러그인 에코시스템, 도구 체인을 일상적으로 타깃으로 삼아야 합니다.
이를 좀 더 명확하게 설명하기 위해 'AI 액션 SSRF 검토'를 다음과 같이 간단하고 반복 가능한 시퀀스로 생각할 수 있습니다:
| 단계 | 주요 질문 | ChatGPT 사례의 예 |
|---|---|---|
| URL 영향력 | 테넌트가 URL을 의미 있게 제어할 수 있나요? | 사용자 정의 GPT 작업을 통해 사용자 정의 외부 엔드포인트를 허용합니다. |
| 행동 리디렉션 | 알 수 없는 위치로 리디렉션되는 리디렉션을 따르나요? | HTTPS 엔드포인트가 다음 주소로 리디렉션됩니다. 169.254.169.254. |
| 헤더 조작 | 테넌트가 민감한 헤더를 간접적으로 설정할 수 있나요? | 인젝션에 사용되는 API 키 구성 메타데이터: true. |
| 권한 및 토큰 | 획득한 토큰으로 실제로 무엇을 할 수 있나요? | IMDS는 워크로드에 대한 관리 API 토큰을 발급했습니다. |
환경에 맞는 이런 종류의 표를 작성해두면 테스트를 자동화하고 설명하기가 훨씬 쉬워집니다. 내부 플레이북에 연결하고, 공급업체와 공유하고, 향후 AI 기능이 동일한 표준을 따르도록 할 수 있습니다.
바로 이 지점에서 AI를 인식하는 전문화된 보안 툴링이 중요해지기 시작합니다. 일반 웹 스캐너는 액션 뒤에 네트워크 호출을 숨기는 UI를 탐색하는 방법이나 GPT 정의 내에서 사용되는 OpenAPI 스키마를 추론하는 방법을 모를 수 있습니다. 이와는 대조적으로, 펜리전트와 같은 AI 기반 펜테스트 플랫폼은 이러한 스키마와 구성을 일급 입력으로 취급할 수 있습니다. 사용자 지정 GPT 또는 기타 AI 도구 세트에 대한 작업 구성을 내보내고 이를 에이전트 테스트 파이프라인에 공급하여 SSRF 조건, 안전하지 않은 리디렉션, 무제한 네트워크 액세스 및 메타데이터 노출을 체계적으로 조사하도록 하는 워크플로우를 상상해 볼 수 있습니다.
자동화와 휴먼 인 더 루프 제어를 결합하는 펜리젠트의 철학은 이러한 패턴에 잘 맞습니다. 에이전트는 모든 툴 정의를 열거하고, URL 또는 호스트 이름을 허용하는 엔드포인트에 대한 후보 페이로드를 생성하고, 호기심 많은 공격자가 시도할 수 있는 것을 시뮬레이션하는 스크립트 트래픽을 유도할 수 있습니다. 시스템이 유망한 행동(예: 외부 HTTPS 엔드포인트가 내부 IP 범위로 리디렉션하는 경우)을 발견하면 요청 로그, 응답 스니펫, 추론된 내부 토폴로지 등의 증거를 통해 이를 드러낼 수 있습니다. 그러면 운영자는 시스템에 클라우드 메타데이터 경로로 특별히 피벗하도록 요청하거나 반환된 토큰이 관리 API에 대해 유효한지 확인하는 등 다음 단계를 진행할 수 있습니다.
이러한 워크플로는 두 가지를 달성합니다. 웹 애플리케이션과 API가 이미 사용하고 있는 것과 동일한 증거 기반 보안 루프에 AI 플랫폼을 도입하고, 공격자가 필연적으로 사용할 수밖에 없는 LLM 기능을 방어자를 위해 활용합니다. 그러면 ChatGPT를 강타한 버그는 더 이상 일회성으로 끝나는 것이 아니라 새로운 통합을 도입하거나 액션 인프라를 변경할 때마다 실행할 수 있는 회귀 스위트에서 테스트 케이스가 됩니다.
AI 플랫폼을 기반으로 구축하는 팀을 위한 실용적인 교훈
AI 서비스를 구축하는 것이 아니라 소비하는 보안 엔지니어나 아키텍트라면 이 사건은 여전히 관련성이 높습니다. 내부적으로 사용자 지정 GPT를 건드리지 않더라도 내부 API, 대시보드 또는 문서 저장소를 AI 에이전트나 공동 파일럿에게 노출하고 있을 가능성이 높습니다. 아이디어는 이전할 수 있습니다.
첫 번째 단계는 LLM을 보안 검토가 필요한 유일한 것으로 취급하는 것을 중단하는 것입니다. 명시적인 도구, 액션, 간접적인 웹후크를 통해 모델이 사용자 환경을 다시 호출할 수 있는 모든 기능을 잠재적인 공격 그래프로 간주해야 합니다. AI 컴포넌트가 어떤 내부 서비스와 대화할 수 있는지, 어떤 ID를 사용하는지, 적대적인 사용자가 의도적으로 이러한 기능을 확장하려고 시도하면 어떤 일이 발생하는지에 대해 자신 있게 대답할 수 있어야 합니다.
두 번째 단계는 AI 글루 코드를 포함하도록 테스트 프로그램을 확장하는 것입니다. 모의 침투 테스트를 의뢰하거나 내부 레드팀 연습을 실행할 때는 도구의 구성 표면, URL 및 헤더 구성 방식, AI 런타임과 민감한 서비스 간의 네트워크 경로, 메타데이터 엔드포인트 주변의 보호 등 AI 통합을 명시적으로 포함해야 합니다. 누군가, 어딘가에서 실제 공격자처럼 이러한 기능을 악용하려 했다는 증거를 요청하세요.
세 번째 단계는 이 공격 표면이 줄어들지 않을 것이라는 사실을 받아들이는 것입니다. 더 많은 비즈니스 프로세스가 LLM에 연결됨에 따라 더 많은 액션, 더 많은 플러그인, 프롬프트를 대신하여 작업을 수행하는 백그라운드 서비스가 늘어날 것입니다. 일련의 인시던트 중심 패치로 보안을 강화하거나 명확한 위협 모델, 기본 아키텍처 패턴, 자동화된 테스트 흐름, 환경이 진화함에 따라 계속 프로빙하는 도구(잠재적으로 Penligent 같은 시스템으로 구동됨)와 같은 반복 가능한 프로그램을 구축할 수 있습니다.
헤드라인 너머
사용자 지정 GPT SSRF 해킹은 단일 공급업체의 일회성 당혹감으로 잘못 읽히기 쉽습니다. 미리 보기로 읽는 것이 더 생산적입니다. AI 플랫폼은 사용자, 모델, API, 클라우드 인프라를 연결하는 오케스트레이션 계층으로 빠르게 성장하고 있습니다. 이러한 역할에는 권한이 수반되며, 권한은 문제가 발생했을 때 항상 더 큰 폭발 반경을 동반합니다.
이 이야기의 고무적인 부분은 앞으로 나아갈 길을 보여준다는 점입니다. 이 취약점은 새로운 맥락에서 오래된 본능을 따르던 한 연구원이 발견했습니다. 이 취약점은 표준 버그 바운티 채널을 통해 신고되었습니다. 수정되었습니다. 이제 나머지 사용자들도 보안과 AI를 모두 이해하는 도구의 도움을 받아 동일한 플레이북을 자체 시스템에 선제적으로 적용할 수 있습니다.
그렇게 한다면, 이 사건의 유산은 단순히 "ChatGPT에 한때 SSRF가 있었다"는 것에 그치지 않습니다. 모델을 더 큰 시스템의 한 구성 요소로 취급하고, 통합을 심각한 공격 표면으로 취급하며, 자동화와 사람의 인사이트(Penligent와 같은 플랫폼이든 자체 내부 파이프라인이든)를 사용하여 막연한 우려를 지속적으로 구체적이고 테스트 가능하며 증거에 기반한 확신으로 전환하는 AI 보안에 대한 사례 연구가 될 수 있습니다. 이러한 이야기는 Medium에서 공유할 가치가 있으며, 엔지니어링 조직 내부에서 공유할 가치가 훨씬 더 높습니다.
