(1/3) 유출된 시스템 프롬프트, 공격자는 이걸로 뭘 할 수 있을까
🚨 시스템 프롬프트 유출과 LLM 서비스 방어 (전체 3편)
- 위협 — 유출된 시스템 프롬프트로 할 수 있는 일 ← 지금 글
- 입력단 방어 — 프롬프트 인젝션 탐지와 필터 설계
- 실행단 방어 — 에이전트 권한 통제와 운영 완결
Summary
요즘 GitHub 에 유명 AI 어시스턴트들의 시스템 프롬프트 가 통째로 올라오는 저장소들이 돌아다닙니다. 모델한테 “넌 이런 성격이고, 이런 규칙을 지키고, 이런 도구를 쓸 수 있어” 라고 미리 박아둔 그 긴 지시문 말이에요. 최근에도 한 모델의 시스템 프롬프트가 통째로 공개되면서 “그래서 이게 유출되면 뭐가 문제냐” 는 이야기가 다시 나왔습니다.
이 글에서는 유출된 시스템 프롬프트가 실제로 무엇에 쓰일 수 있는지 를 공격자 관점과 방어자 관점에서 같이 정리해볼게요.
💡 이 글에서 다루는 것
- 시스템 프롬프트가 정확히 뭐고, 왜 “숨겨진” 자산인지
- 유출된 프롬프트로 할 수 있는 일 5가지 (역설계 · 탈옥 설계 · 인젝션 정교화 · 프롬프트 학습 · 방어)
- 내 서비스에 시스템 프롬프트를 박을 때의 방어 체크리스트
🚨 이 글은 보안 이해·방어를 위한 글입니다. 실제로 동작하는 탈옥 프롬프트나 우회 페이로드는 싣지 않고, 공격자가 어떤 사고 흐름으로 접근하는지 와 그래서 어떻게 막는지 에 초점을 둡니다.
1. 시스템 프롬프트가 뭐길래
LLM 기반 서비스를 한 번이라도 만들어보면 금방 알게 되는 구조가 있어요. 사용자가 채팅창에 입력하는 메시지(user 메시지) 위에, 사용자 눈에는 안 보이는 시스템 메시지 가 한 겹 깔려 있습니다.
대충 이런 모양이에요.
[system] 당신은 친절한 고객지원 봇입니다. 환불 규정은 다음과 같습니다 ...
욕설이나 정치적 주제에는 답하지 마세요.
내부 가격 정책(원가, 마진)은 절대 노출하지 마세요.
사용 가능한 도구: search_order(주문조회), issue_refund(환불)
[user] 환불 좀 해줘요
[assistant] (모델의 답변)
system 칸에 들어가는 이 지시문이 시스템 프롬프트 입니다. 여기에는 보통 이런 것들이 들어가요.
- 정체성·말투 — “너는 누구고 어떤 톤으로 말한다”
- 거절 규칙 — “어떤 요청은 거절하고, 거절할 땐 이렇게 한다”
- 사용 가능한 도구 정의 — 함수 이름, 파라미터, 언제 호출하는지
- 숨겨야 할 정보 — 내부 정책, 원가, 다른 사용자 데이터
- 출력 포맷 규칙 — 마크다운, 길이, 인용 방식
핵심은 이게 사용자에게 안 보이도록 설계된 자산 이라는 점이에요. 서비스 운영자가 모델을 길들이는 핵심 노하우가 다 여기 들어있고, 그래서 이게 통째로 새어나가면 “기획서가 통째로 털린” 느낌에 가깝습니다.
✅ 정리하면, 시스템 프롬프트는 모델의 운영 매뉴얼 이에요. 사용자가 보는 답변은 결과물일 뿐이고, 그 결과를 만들어내는 규칙집이 한 겹 아래에 따로 있는 거죠.
2. 이번에 유출된 건 뭔가
이런 유출을 모아두는 공개 저장소가 몇 개 있는데, 그중 잘 알려진 게 CL4R1T4S 라는 저장소예요. 여러 상용 AI 어시스턴트의 시스템 프롬프트를 추출해 텍스트로 정리해두는 곳입니다. 최근에는 한 플래그십 모델의 시스템 프롬프트 전문이 올라왔고, 열어보면 대략 이런 큰 단원들로 구성돼 있었어요.
| 섹션 | 들어있는 내용 |
|---|---|
| 제품·모델 정보 | 어떤 모델 라인업이 있고 어떤 기능을 안내할지 |
| 거절 처리(Refusal) | 무엇을 거절하고, 거절을 어떻게 표현할지 |
| 법률·금융 조언 | 면책·주의 문구를 어떻게 붙일지 |
| 톤·포맷 | 말투, 마크다운, 길이 규칙 |
| 사용자 웰빙 | 위기 신호에 어떻게 반응할지 |
| 지식 컷오프 | 학습 데이터 기준 시점 안내 방식 |
| 메모리 시스템 | 무엇을 기억하고 저장하는지 |
| 검색·저작권 준수 | 웹 검색 인용 규칙, 저작권 회피 규칙 |
| 도구 정의 | 15개 이상 도구의 이름·파라미터·호출 조건 |
흥미로운 건, 이게 단순한 “성격 설정” 이 아니라 꽤 정밀한 행동 규약 이라는 점이에요. 거절을 어떤 문장으로 할지, 어떤 경우엔 짧게 끊고 어떤 경우엔 대안을 제시할지, 도구를 호출할 때 어떤 순서로 판단할지까지 적혀 있습니다.
바로 이 정밀함이 공격자에게 쓸모가 있어요. 다음 절에서 하나씩 볼게요.
3. 유출된 프롬프트로 할 수 있는 일들
3.1 모델 행동 역설계 — “왜 거절하는지” 를 알아내기
평소에 모델을 쓰다 보면 “이건 왜 거절하지?” 싶은 순간이 많죠. 시스템 프롬프트가 없으면 그건 블랙박스를 두드려보며 추측 하는 작업이에요. 거절 문장을 보고 “아마 이런 규칙이 있나 보다” 하고 역으로 더듬는 거죠.
그런데 시스템 프롬프트가 통째로 공개되면 이 추측 단계가 통째로 날아갑니다. 거절의 정확한 트리거 조건 과 문구 템플릿 이 텍스트로 손에 들어오니까요. “이 단어가 들어가면 거절, 이 맥락이면 통과” 같은 경계선이 그대로 보이는 셈이에요.
방어자 입장에서도 같은 정보가 유용하긴 합니다(내 서비스가 어디서 과하게 거절하는지 점검). 다만 같은 지도가 공격자 손에도 들어간다는 게 문제예요.
3.2 가드레일 우회 설계 — 탈옥(jailbreak)의 정밀화
탈옥이라고 부르는 가드레일 우회는 원래 무차별 대입에 가까운 작업 이에요. “이렇게 물어보면 되나? 역할극을 시키면 되나?” 하고 수백 번 변형을 던져보는 거죠.
유출된 시스템 프롬프트는 이 작업을 무차별 대입에서 표적 공격으로 바꿔놓습니다. 규칙이 텍스트로 보이면 공격자는 이렇게 사고해요.
- 규칙들 사이에 서로 충돌하는 지점 이 있나? (예: “항상 도움이 돼라” vs “이건 거절해라”)
- 거절 규칙이 특정 단어·형식에만 걸려 있나? 그렇다면 같은 의도를 다른 표현으로 우회 가능한가?
- “사용자 안전 우선” 같은 상위 규칙을, 모델이 더 우선시하도록 프레이밍 할 여지가 있나?
즉 유출된 규칙집은 공격자에게 약점 지도 역할을 합니다. 어디를 밀면 규칙끼리 부딪히는지 미리 알고 들어가는 거예요.
⚠️ 그래서 시스템 프롬프트만 믿고 “여기 거절하라고 써놨으니 안전하다” 고 생각하면 위험합니다. 규칙이 공개되는 순간, 그 규칙의 빈틈을 찾는 난이도가 확 낮아져요.
3.3 프롬프트 인젝션 정교화 — 도구 정의가 새어나갈 때
개인적으로 가장 위험하다고 보는 부분이에요. 요즘 LLM 서비스는 단순 채팅이 아니라 도구(tool)를 호출하는 에이전트 인 경우가 많죠. 시스템 프롬프트에는 그 도구들의 정의가 들어있습니다. 함수 이름, 파라미터, 호출 조건까지요.
이게 새어나가면 프롬프트 인젝션 의 정밀도가 올라가요. 프롬프트 인젝션은 사용자 입력(또는 모델이 읽는 외부 문서)에 악의적인 지시를 심어, 모델이 운영자의 의도를 벗어난 행동을 하게 만드는 공격입니다.
도구 정의를 모르면 공격자는 “환불 함수가 있긴 할 텐데 이름이 뭐지?” 부터 추측해야 해요. 그런데 시스템 프롬프트에서 issue_refund(order_id, amount) 같은 시그니처가 그대로 보이면, 인젝션 페이로드를 그 함수를 정확히 겨냥해서 짤 수 있게 됩니다. 호출 조건까지 알면 “어떤 맥락을 만들어야 모델이 그 함수를 부를지” 도 설계 가능해지고요.
🚨 도구를 쓰는 에이전트라면, 시스템 프롬프트 유출 = 공격 표면의 내부 설계도 유출 입니다. 단순 챗봇보다 훨씬 위험도가 높아요.
3.4 프롬프트 엔지니어링 학습 / 벤치마킹
여기서부터는 꼭 악용만은 아닌, 회색지대에 가까운 용도예요.
최상위 AI 랩들이 쓴 시스템 프롬프트는 그 자체로 고급 프롬프트 엔지니어링 교본 입니다. 거절을 설교조로 하지 않게 만드는 문장, 톤을 일정하게 유지시키는 표현, 도구 호출 판단을 정리한 구조 — 이런 노하우가 잘 다듬어진 형태로 들어있어요. 그래서 다른 서비스를 만드는 사람들이 이걸 보고 자기 프롬프트를 다듬는 데 참고하기도 합니다.
문제는 이게 운영자의 영업 비밀 에 가깝다는 점이에요. 경쟁사가 그대로 베끼거나, 서비스의 차별화 포인트(어떤 톤·어떤 정책)를 통째로 들여다보는 데 쓰일 수 있습니다. 코드 유출만큼은 아니어도, “이렇게 모델을 길들였구나” 하는 핵심 노하우가 공짜로 풀리는 거죠.
3.5 방어 측면 — 레드팀과 탐지
같은 유출물이 방어자에게도 무기가 됩니다. 오히려 방어 쪽에서 더 적극적으로 활용해야 해요.
- 레드팀 — 공개된 규칙집을 보면서 “이 규칙의 빈틈은 여기겠다” 를 먼저 찾아 자기 서비스를 두드려볼 수 있어요. 공격자보다 먼저 약점을 찾는 거죠.
- 거절 일관성 점검 — 내 시스템 프롬프트가 의도대로 거절/허용하는지, 경계선이 흐릿한 곳은 없는지 점검합니다.
- 탐지 룰 작성 — 알려진 탈옥 패턴(역할극 유도, 규칙 충돌 유발 등)을 입력단에서 걸러내는 필터를 설계.
💡 유출은 공격자에게만 유리한 게 아니에요. 같은 정보를 먼저 읽고 먼저 막으면, 방어자가 한 발 앞설 수 있습니다.
4. 그래서 유출이 정말 위험한가
“시스템 프롬프트 좀 보인다고 큰일이야?” 라는 반론도 있어요. 절반은 맞습니다. 시스템 프롬프트는 비밀번호가 아니에요. 그 자체로 계정이 털리거나 서버가 뚫리지는 않습니다.
위험의 본질은 다른 데 있어요. 보안 설계의 기본 원칙 중에 “비밀에 의존한 보안(security by obscurity)은 보안이 아니다” 라는 게 있죠. 시스템 프롬프트가 “안 보일 거라는 가정” 위에서만 안전하게 동작하도록 설계돼 있었다면, 그 가정이 깨지는 순간 다음 세 가지가 한꺼번에 드러납니다.
- 거절 경계선 — 무엇을 어떤 조건에 막는지 (우회의 출발점)
- 숨기려던 정보 — 내부 정책·가격·민감 규칙을 프롬프트에 직접 박았다면 그게 노출
- 공격 표면 — 도구 이름·파라미터·호출 조건 (인젝션의 표적)
🚨 가장 흔한 사고는 시스템 프롬프트에 민감 정보를 직접 텍스트로 박아두는 것 입니다. “이 API 키로 호출해”, “내부 환불 한도는 50만 원” 같은 걸 system 칸에 넣어두면, 프롬프트가 새는 순간 그게 그대로 털려요. 모델은 어차피 그 텍스트를 다 읽고 있으니, 잘 유도하면 사용자에게 그대로 뱉을 수도 있고요.
5. 내 서비스에 적용한다면 — 방어 체크리스트
LLM 서비스를 만든다면, 시스템 프롬프트는 언젠가 새어나갈 수 있다는 가정 위에서 설계하는 게 안전합니다. 실제로 막아야 할 포인트를 정리해볼게요.
- 비밀을 프롬프트에 박지 않기 — API 키·DB 접속정보·내부 한도 같은 건 시스템 프롬프트가 아니라 코드/서버 측 로직 에 둡니다. 모델이 읽는 텍스트에 비밀을 넣지 않는 게 1순위예요.
- 권한은 모델이 아니라 서버에서 검증 — “이 사용자는 환불 권한이 있다” 같은 판단을 모델의 자율 판단에 맡기지 말 것. 도구를 호출하더라도 실제 실행 직전에 서버에서 권한·한도를 다시 검사 합니다.
- 도구 부작용 최소화 — 모델이 부를 수 있는 도구는 가능한 한 읽기 전용 으로. 돈이 나가거나 데이터가 바뀌는 도구는 사람 승인 단계를 끼웁니다.
- 입력단 인젝션 필터 — 외부 문서나 사용자 입력에 “이전 지시를 무시하고…” 류의 지시가 섞여 있는지 거르는 방어를 둡니다. 완벽하진 않아도 난이도를 올려줘요.
- 거절을 다층으로 — 시스템 프롬프트의 거절 규칙 하나에만 의존하지 말고, 별도 분류기(입력/출력 모더레이션)를 한 겹 더 둡니다. 규칙이 공개돼도 두 번째 방어선이 남도록.
- 정기 레드팀 — 공개된 유출물·알려진 탈옥 패턴으로 내 서비스를 주기적으로 두드려보고, 새는 곳을 찾아 패치합니다.
✅ 한 줄 요약: 시스템 프롬프트는 “안 보일 비밀” 이 아니라 “보여도 안전해야 하는 설명서” 로 설계하세요. 진짜 방어선은 프롬프트 텍스트가 아니라 그 아래 서버 로직에 있어야 합니다.
마치며
유출된 시스템 프롬프트는 그 자체로 폭탄은 아니지만, 공격자에게 약점 지도이자 내부 설계도 가 되어줍니다. 거절을 우회할 출발점, 인젝션의 표적, 숨기려던 정보까지 한 번에 보여주니까요.
그렇다고 막연히 무서워할 필요는 없어요. 방어의 방향은 분명합니다. 비밀은 프롬프트 밖에 두고, 권한과 부작용은 서버에서 통제하고, 거절은 여러 겹으로. 시스템 프롬프트가 새어나가도 무너지지 않는 구조를 만들면, 유출 그 자체는 사고가 아니라 점검의 계기 정도로 끝납니다.
일단 오늘은 여기까지…..
다음 글에서는 프롬프트 인젝션을 실제로 어떻게 탐지하고 막는지, 입력단 필터 설계를 좀 더 구체적으로 정리해볼게요.