우리는 최근 분기별 Elastic OnWeek 이벤트 중 하나를 마쳤는데, 이 이벤트는 일상적인 일과를 벗어난 특별한 한 주 동안 기회를 탐색할 수 있는 기회를 제공합니다. OWASP와 NSA AISC의 최근 발표에 따라, 우리는 Elastic에서 기본적으로 LLM에 대한 OWASP 상위 10가지 취약점에 대해 시간을 보내기로 결정했습니다. 이 글에서는 ES|QL로 악의적인 LLM 활동을 탐지할 수 있는 몇 가지 기회에 대해 설명합니다:
- LLM01: 프롬프트 주입
- LLM02: 안전하지 않은 출력 처리
- LLM04: 모델 서비스 거부
- LLM06: 민감한 정보 공개
Elastic은 악의적인 동작에 대해 LLM 애플리케이션을 감사할 수 있는 기능을 제공합니다. 단 4단계로 구성된 한 가지 접근 방식을 보여드리겠습니다:
- LLM 요청 및 응답 가로채기 및 분석
- LLM별 분석 결과로 데이터 보강하기
- Elastic Security로 데이터 보내기
- 나중에 응답에 사용할 수 있는 ES|QL 탐지 규칙 작성하기
이러한 접근 방식은 새롭게 등장하는 생성 AI 기술 및 보안 과제에 발맞추면서 LLM에 특화된 탐지 규칙을 개발하는 등 고급 탐지 전략을 모색하고 구현하기 위한 지속적인 노력을 반영합니다. 이러한 기반을 바탕으로 작년에는 이러한 선제적인 행보를 지속하기 위해 툴킷과 전반적인 역량을 크게 향상시켰습니다.
Elastic은 보안을 위한 AI Assistant를 출시하면서 고급 검색 애플리케이션 개발을 위한 관련 도구 모음인 Search AI Platform을 통해 이 개방형 생성 AI 조수가 어떻게 구동되는지 소개했습니다. 머신 러닝(ML)과 인공지능(AI)을 기반으로 하는 이 AI 어시스턴트는 알림 요약, 워크플로 제안, 쿼리 전환, 상담원 통합 조언과 같은 강력한 사전 구축 워크플로우를 제공합니다. 이 기능이 통합 가시성과 보안에 걸쳐 어떻게 원활하게 적용되는지 Elastic의 AI Assistant에서 자세히 읽어보시기를 적극 권장합니다.
AI 어시스턴트의 기능을 타사 LLM 애플리케이션으로 사용하여 요청과 응답을 캡처, 감사, 분석하여 편의를 도모하고 실험을 실행할 수 있습니다. 데이터가 인덱스에 저장되면 그 위에 행동 탐지를 작성하는 것은 평소와 같은 업무가 되며, 전체 보안 탐지 엔진을 활용할 수도 있습니다. 이 실험에서 Elastic AI Assistant LLM 활동을 프록시하고 있지만, 이는 단지 LLM 기반 애플리케이션 감사를 시연하기 위한 수단으로 사용될 뿐입니다. 또한, 이 프록시 접근 방식은 타사 애플리케이션이 Elastic Security로 데이터를 전송하기 위한 것입니다.
LLM 활동을 가로채거나 관찰 가능한 LLM 지표를 활용하여 애플리케이션의 라이프사이클에 보안 메커니즘을 도입할 수 있습니다. 다양한 안전 전술을 구현하여 프롬프트 기반 위협에 대처하는 것이 일반적인 관행입니다:
- 입력 정리: 사용자 입력을 모델에 공급하기 전에 살균하고 유효성을 검사합니다.
- 콘텐츠 중재: OpenAI 도구를 사용하여 유해한 프롬프트 및 출력 필터링하기
- 요금 제한 및 모니터링: 사용 패턴을 추적하여 의심스러운 활동 감지
- 허용/차단 목록: 특정 애플리케이션에 대해 허용되거나 금지된 입력을 정의합니다.
- 안전한 프롬프트 엔지니어링: 모델을 의도한 결과로 안내하는 미리 빌드된 프롬프트 설계
- 사용자 역할 관리: 사용자 액세스를 제어하여 무단 작업 방지
- 최종 사용자를 교육하세요: 위험 완화를 위한 책임감 있는 모델 사용을 장려합니다.
- 레드팀 & 모니터링: 취약점 테스트 및 예기치 않은 출력에 대한 지속적인 모니터링
- 모델 학습을 위한 HITL 피드백: 휴먼 인 더 루프, 플래그가 지정된 문제에서 학습하여 시간이 지남에 따라 모델을 개선하세요.
- API 액세스 제한: 특정 요구 사항 및 사용자 인증에 따라 모델 액세스를 제한합니다.
OpenAI와 다른 많은 LLM 구현업체가 제공하는 두 가지 강력한 기능은 최종 사용자 ID를 제출하고 모더레이션 API를 통해 콘텐츠를 확인하는 기능으로, LLM 안전의 기준을 설정하는 기능입니다. 원본 요청과 함께 해시된 ID를 전송하면 남용 탐지에 도움이 되며, 개인 정보를 전송하지 않고도 고유한 사용자 식별이 가능하므로 대상에 맞는 피드백을 제공합니다. 또는 OpenAI의 모더레이션 엔드포인트는 개발자가 혐오 표현, 자해 조장, 폭력 등 잠재적으로 유해할 수 있는 콘텐츠를 식별하여 이러한 콘텐츠를 필터링할 수 있도록 도와줍니다. 한 걸음 더 나아가 위협과 자해 의도까지 감지할 수 있습니다.
악성 프롬프트를 방지하기 위한 모든 권장 사항과 모범 사례에도 불구하고 완벽한 해결책은 없다는 것을 잘 알고 있습니다. OpenAI의 API와 같은 기능을 사용할 때 이러한 위협 중 일부는 콘텐츠 필터에 의해 감지될 수 있으며, 콘텐츠 필터는 사용 정책 위반 알림으로 대응합니다:
이러한 콘텐츠 필터링은 많은 문제를 해결하는 데 유용하지만 환경, 애플리케이션 에코시스템 또는 기타 경고의 광범위한 맥락에서 추가 위협을 식별할 수는 없습니다. 기존의 보호 기능에 생성형 AI 사용 사례를 더 많이 통합할수록 잠재적인 위협에 대응할 수 있는 통제력과 가능성이 높아집니다. 또한, 기본적인 공격을 막기 위해 LLM 안전장치가 마련되어 있더라도 탐지 엔진을 사용하여 자동으로 차단하거나 남용을 허용하는 대신 경고하고 향후 개선 조치를 취할 수 있습니다.
LLM 요청 프록시 및 설정
최적의 보안 솔루션은 LLM 애플리케이션의 에코시스템에 직접 추가 보호 장치를 통합합니다. 이를 통해 요청과 응답을 둘러싼 전체 컨텍스트를 통해 더욱 풍부한 알림을 제공할 수 있습니다. 요청이 LLM으로 전송되면 잠재적인 악의적 활동을 차단하고 분석할 수 있습니다. 필요한 경우 응답 작업을 트리거하여 후속 HTTP 호출을 연기할 수 있습니다. 마찬가지로 LLM의 응답을 검사하면 악의적인 행동의 추가 징후를 발견할 수 있습니다.
프록시를 사용하여 이러한 상호작용을 처리하면 몇 가지 이점이 있습니다:
- 통합 및 관리의 용이성: 전용 프록시 애플리케이션 내에서 새 보안 코드를 관리하면 복잡한 보안 로직을 메인 애플리케이션에 직접 포함하지 않아도 됩니다. 이 접근 방식은 기존 애플리케이션 구조에 필요한 변경을 최소화하여 유지 관리가 용이하고 보안과 비즈니스 로직을 보다 명확하게 분리할 수 있습니다. 메인 애플리케이션은 프록시를 통해 LLM 요청을 라우팅하도록만 재구성해야 합니다.
- 성능 및 확장성: 프록시를 별도의 서버에 배치하면 보안 메커니즘을 격리하고 계산 부하를 분산하는 데 도움이 됩니다. 이는 운영을 확장하거나 성능 집약적인 작업을 관리할 때 매우 중요할 수 있으며, 추가 보안 처리로 인해 주 애플리케이션의 성능이 영향을 받지 않도록 보장합니다.
빠른 시작 옵션: 플라스크가 있는 프록시
수신 및 발신 LLM 연결을 프록시하여 초기 설정을 빠르게 진행할 수 있습니다. 이 접근 방식은 간단한 Python 기반 Flask 애플리케이션을 생성하여 다른 LLM 애플리케이션에 일반화할 수 있습니다. 이 애플리케이션은 통신을 가로채서 보안 위험을 분석하고 응답을 전달하기 전에 관련 정보를 기록합니다.
Elasticsearch에 연결하고 OpenAI LLM 요청을 처리하기 위한 여러 SDK가 존재합니다. 제공된 llm-detection-proxy 리포지토리는 사용 가능한 Elastic 및 OpenAI 클라이언트를 보여줍니다. 이 스니펫은 단일 플라스크 경로에서 실험적인 프록시의 대부분을 강조합니다.
@app.route("/proxy/openai", methods=["POST"])
def azure_openai_proxy():
"""Proxy endpoint for Azure OpenAI requests."""
data = request.get_json()
messages = data.get("messages", [])
response_content = ""
error_response = None
try:
# Forward the request to Azure OpenAI
response = client.chat.completions.create(model=deployment_name, messages=messages)
response_content = response.choices[0].message.content # Assuming one choice for simplicity
choices = response.choices[0].model_dump()
except openai.BadRequestError as e:
# If BadRequestError is raised, capture the error details
error_response = e.response.json().get("error", {}).get("innererror", {})
response_content = e.response.json().get("error", {}).get("message")
# Structure the response with the error details
choices = {**error_response.get("content_filter_result", {}),
"error": response_content, "message": {"content": response_content}}
# Perform additional analysis and create the Elastic document
additional_analysis = analyze_and_enrich_request(prompt=messages[-1],
response_text=response_content,
error_response=error_response)
log_data = {"request": {"messages": messages[-1]},
"response": {"choices": response_content},
**additional_analysis}
# Log the last message and response
log_to_elasticsearch(log_data)
# Calculate token usage
prompt_tokens = sum(len(message["content"]) for message in messages)
completion_tokens = len(response_content)
total_tokens = prompt_tokens + completion_tokens
# Structure and return the response
return jsonify({
"choices": [choices],
"usage": {
"prompt_tokens": prompt_tokens,
"completion_tokens": completion_tokens,
"total_tokens": total_tokens,
}
})
Flask 서버를 사용하면 프록시를 사용하도록 OpenAI Kibana 커넥터를 구성할 수 있습니다.
LLM에 대한 이 프록시는 로컬에서 실행되므로 자격 증명과 연결 정보는 Elastic 외부에서 관리되며, API 키 섹션에 빈 문자열을 제공할 수 있습니다. 계속 진행하기 전에 일반적으로 연결을 테스트하는 것이 좋습니다. 간결성을 위해 이 프로토타입에서 고려하지 않은 실제 환경에서 프록시 솔루션을 구현하려는 경우 다른 보안 영향을 고려하는 것이 중요합니다.
이제 LLM 요청과 응답을 색인하고 이 실험에서 생성한 azure-openai-logs
색인에서 사용 가능한 데이터에 대한 탐지를 시작할 수 있습니다. 선택적으로 Elastic 수집 파이프라인을 사용해 데이터를 전처리할 수도 있지만, 이 고안된 예제에서는 ES|QL의 강력한 기능을 사용해 효과적으로 탐색을 작성할 수 있습니다.
샘플 AzureOpenAI LLM 요청/응답 데이터
랭스미스 프록시
참고: 랭스미스 프록시 프로젝트는 LLM API를 위한 도커화된 프록시를 제공합니다. 최소화된 솔루션을 제공하지만, 이 글을 쓰는 현재로서는 사용자 정의 보안 분석 도구를 통합하거나 Elastic Security와 직접 통합할 수 있는 기본 기능이 부족합니다.
LangSmith 프록시는 LLM API 상호 작용을 간소화하도록 설계되었습니다. 최소한의 구성만 필요한 사이드카 애플리케이션입니다(예: LLM API URL). 트래픽이 많은 시나리오의 성능(캐싱, 스트리밍)을 향상시킵니다. 효율성을 위해 NGINX를 사용하며 자세한 LLM 상호작용 추적을 위한 옵션 추적을 지원합니다. 현재 OpenAI 및 AzureOpenAI와 함께 작동하며, 향후 다른 LLM에 대한 지원도 계획되어 있습니다.
LLM 잠재적 공격 및 탐지 규칙 기회
일부 LLM에는 문서화된 보호 목록이 첨부되어 있지 않더라도 이러한 프롬프트 중 일부를 시도하는 것만으로도 즉시 거부되거나 프롬프트를 제출하는 데 사용된 플랫폼에서 금지될 수 있다는 점을 이해하는 것이 중요합니다. 악성 프롬프트를 보내기 전에 신중하게 실험하고 SLA를 이해하는 것이 좋습니다. 이 탐색은 OpenAI의 리소스를 활용하므로, 버그크라우드의 안내에 따라 @bugcrowdninja.com 이메일 주소를 사용하여 추가 테스트 계정에 가입하는 것이 좋습니다.
다음은 탐지 기회를 설명하기 위한 몇 가지 그럴듯한 예시 목록입니다. 각 LLM 주제에는 OWASP 설명, 예시 프롬프트, 샘플 문서, 탐지 기회, 사용자가 워크플로에 추가 보안 메커니즘을 통합하는 경우 취할 수 있는 잠재적 조치가 포함되어 있습니다.
현재 이 목록은 광범위하지는 않지만, Elastic Security Labs는 향후 개발을 위해 여러 가지 이니셔티브를 진행하고 있으며 규칙의 공식화는 계속될 것입니다.
LLM01 - 프롬프트 주입
OWASP 설명: 조작된 입력을 통해 LLM을 조작하면 무단 액세스, 데이터 유출, 잘못된 의사 결정으로 이어질 수 있습니다. 여기를 참조하세요.
예시: 공격자는 LLM을 속여 의도하지 않은 작업을 실행하거나 민감한 정보를 노출하도록 유도하는 프롬프트를 만들려고 할 수 있습니다. 참고: 프롬프트맵과 같은 도구를 사용하여 창의적인 프롬프트 삽입 아이디어를 생성하고 테스트 프로세스를 자동화할 수 있습니다.
Prompt:
샘플 응답:
탐지 규칙 기회: 이 예에서 LLM은 보안 위험으로 인해 데이터베이스 연결 문자열 처리를 거부하는 방식으로 대응했습니다. 자격 증명을 비공개로 유지할 것을 강조하고 환경 변수나 볼트 같은 안전한 방법을 사용하여 자격 증명을 보호할 것을 제안합니다.
매우 취약하지만 기본적인 지표 매칭 쿼리는 다음과 같습니다:
FROM azure-openai-logs |
WHERE request.messages.content LIKE "*generate*connection*string*"
OR request.messages.content LIKE "*credentials*password*username*"
OR response.choices LIKE "*I'm sorry, but I can't assist*"
조금 더 고급 쿼리는 지난 하루 동안 두 번 이상의 유사한 시도를 감지합니다.
FROM azure-openai-logs
| WHERE @timestamp > NOW() - 1 DAY
| WHERE request.messages.content LIKE "*credentials*password*username*"
OR response.choices LIKE "*I'm*sorry,*but*I*can't*assist*"
OR response.choices LIKE "*I*can’t*process*actual*sensitive*"
| stats total_attempts = count(*) by connectorId
| WHERE total_attempts >= 2
악성 프롬프트를 탐지하고 LLM 응답을 보호하는 방법에는 여러 가지가 있습니다. 이러한 지표에만 의존하는 것은 최선의 방법은 아니지만, 추가적인 보강 또는 다양한 대응 시도를 통해 점차적으로 탐지 기능을 개선할 수 있습니다. 또한 문서에 ID를 도입하면 특정 사용자와 연관된 필드를 기준으로 시도를 집계하여 쿼리를 더욱 향상시킬 수 있습니다.
예 2: 크레센도 효과는 공격자가 보안 시스템의 무단 액세스 및 조작과 관련된 가상 시나리오를 설명하도록 모델에 요청하는 것으로 전환하는 일련의 무해해 보이는 문의를 통해 언어 모델을 서서히 조작하는 현실적인 탈옥 공격입니다. 이를 통해 잠재적으로 LLM의 보안 제약을 우회할 수 있는 방법을 추출하는 것이 목표입니다.
Prompt:
샘플 응답:
OpenAI의 필터링을 통한 추가 분석으로 어뷰징의 첫 번째 발생을 즉시 감지할 수 있습니다.
탐지 규칙 기회:
FROM azure-openai-logs
| WHERE @timestamp > NOW() - 1 DAY
AND (
request.messages.content LIKE "*credentials*password*username*"
OR response.choices LIKE "*I'm sorry, but I can't assist*"
OR analysis.openai.code == "ResponsibleAIPolicyViolation"
OR malicious
)
| STATS total_attempts = COUNT(*) BY connectorId
| WHERE total_attempts > 1
| SORT total_attempts DESC
그러나 크레센도 효과를 계속 사용하면 OpenAI의 초기 콘텐츠 필터 이후 대화 피벗이 차단 해제되는 것을 확인할 수 있습니다. 이와 같은 수법을 예방하기 어렵더라도 탐지할 수 있는 기회는 여전히 존재한다는 점을 이해하는 것이 중요합니다.
LLM-Guard와 같은 추가 분석 도구는 대화가 민감한 내용인지 여부를 감지합니다(이 경우 부정확한 경우). 그러나 여러 프롬프트에 걸쳐 악의적인 행동을 추적할 수 있는 잠재적 기회를 암시합니다. 참고: 여러 이벤트에 걸친 행동을 추적하는 데 도움이 되도록 이 ES|QL 쿼리의 대안으로 EQL 시퀀스를 활용할 수도 있습니다.
FROM azure-openai-logs
| WHERE @timestamp > NOW() - 1 DAY
AND (
request.messages.content LIKE "*Molotov*"
OR analysis.openai.code == "ResponsibleAIPolicyViolation"
OR malicious
)
| STATS attempts = count(*), max_sensitivity = max(analysis.llm_guard_response_scores.Sensitive) BY connectorId
| WHERE attempts >= 1 AND max_sensitivity > 0.5
| SORT attempts DESC
이 쿼리는 단일 사용자/세션과 관련된 로그 항목의 시퀀스를 분석하여 여러 이벤트에서 화염병과 관련된 의심스러운 행동을 탐지합니다(커넥터Id로 식별됨). 쿼리 코어는 다음을 기준으로 이벤트를 필터링합니다:
- 콘텐츠 매칭: 대화 콘텐츠(
request.messages.content LIKE "*Molotov*"
)에서 "화염병" 에 대한 언급을 검색합니다. - **정책 위반: OpenAI의 안전 필터(
analysis.openai.code == "ResponsibleAIPolicyViolation"
)에 의해 차단된 시도를 식별하여 잠재적으로 의심스러운 행동의 시작을 나타냅니다. - 악성 플래그 고려 사항: 여기에는 시스템이 콘텐츠를 악성으로 플래그(
malicious == true
)를 지정하여 잠재적으로 미묘하거나 다양한 언급을 캡처한 로그가 포함됩니다. - 세션 수준 분석: 커넥터Id별로 이벤트를 그룹화하여 세션 내의 전체 시도 시퀀스를 분석합니다. 그런 다음 해당 세션의 모든 시도에 대한 총 시도 횟수(
attempts = count(*)
)와 가장 높은 민감도 점수(max_sensitivity = max(analysis.llm_guard_response_scores.Sensitive)
)를 계산합니다. - 고위험 세션 플래그 지정: 시도 횟수가 1회 이상(
attempts >= 1
)이고 최대 민감도 점수가 0.5를 초과하는 세션(max_sensitivity > 0.5
)을 필터링합니다. 이 임계값은 사용자가 잠재적으로 위험한 콘텐츠를 지속적으로 논의하거나 공개하는 세션에 집중하는 데 도움이 됩니다.
세션 내의 여러 이벤트에서 이러한 요소를 분석함으로써 개별 이벤트가 단독으로 플래그가 지정되지 않더라도 토론이 확대되는 패턴을 감지하는 접근 방식을 구축할 수 있습니다.
LLM02 - 안전하지 않은 출력 처리
OWASP 설명: LLM 출력의 유효성을 검사하지 않으면 시스템을 손상시키고 데이터를 노출시키는 코드 실행을 포함한 다운스트림 보안 익스플로잇이 발생할 수 있습니다. 여기를 참조하세요.
예시: 공격자는 LLM을 악용하여 크로스 사이트 스크립팅(XSS) 또는 기타 인젝션 공격에 사용할 수 있는 출력을 생성하려고 시도할 수 있습니다.
Prompt:
샘플 응답:
탐지 규칙 기회:
FROM azure-openai-logs
| WHERE @timestamp > NOW() - 1 DAY
| WHERE (
response.choices LIKE "*<script>*"
OR response.choices LIKE "*document.cookie*"
OR response.choices LIKE "*<img src=x onerror=*"
OR response.choices LIKE "*<svg/onload=*"
OR response.choices LIKE "*javascript:alert*"
OR response.choices LIKE "*<iframe src=# onmouseover=*"
OR response.choices LIKE "*<img ''><script>*"
OR response.choices LIKE "*<IMG SRC=javascript:alert(String.fromCharCode(88,83,83))>*"
OR response.choices LIKE "*<IMG SRC=# onmouseover=alert('xxs')>*"
OR response.choices LIKE "*<IMG onmouseover=alert('xxs')>*"
OR response.choices LIKE "*<IMG SRC=/ onerror=alert(String.fromCharCode(88,83,83))>*"
OR response.choices LIKE "*javascript:alert('XSS')>*"
OR response.choices LIKE "*<IMG SRC=javascript:alert('XSS')>*"
OR response.choices LIKE "*<IMG SRC=\"jav
ascript:alert('XSS');\">*"
)
| stats total_attempts = COUNT(*), users = COUNT_DISTINCT(connectorId)
| WHERE total_attempts >= 2
이 의사 쿼리는 크로스 사이트 스크립팅(XSS) 공격에서 흔히 발생하는 스크립팅 요소 또는 쿠키 액세스 시도가 포함된 LLM 응답을 식별하여 잠재적으로 안전하지 않은 출력 처리를 탐지합니다. 잘 알려진 키워드에 대한 허용 또는 차단 목록으로 확장할 수 있는 셸입니다.
LLM04 - 모델 DoS
OWASP 설명: 리소스를 많이 사용하는 작업으로 LLM에 과부하가 걸리면 서비스 중단과 비용 증가가 발생할 수 있습니다. 여기를 참조하세요.
예시: 공격자가 과도한 컴퓨팅 리소스를 소모하는 복잡한 프롬프트를 보낼 수 있습니다.
Prompt:
샘플 응답:
탐지 규칙 기회:
FROM azure-openai-logs
| WHERE @timestamp > NOW() - 1 DAY
| WHERE response.choices LIKE "*requires*significant*computational*resources*"
| stats total_attempts = COUNT(*), users = COUNT_DISTINCT(connectorId)
| WHERE total_attempts >= 2
이 탐지 사례는 잠재적으로 악의적인 행동을 식별하는 데 LLM 응답이 어떻게 사용되는지 보여주는 또 다른 간단한 예입니다. 이 예시는 전통적인 보안 위협은 아니지만, 공격자가 리소스나 토큰을 소모하여 피해자에게 비용을 부과하는 방법을 모방할 수 있습니다.
예 2: 공격자가 과도한 컴퓨팅 리소스를 소모하는 복잡한 프롬프트를 보낼 수 있습니다.
Prompt:
샘플 응답:
언뜻 보기에 이 프롬프트는 정상적으로 보입니다. 그러나 단시간에 과도한 요청과 장황한 답변은 비용을 크게 증가시킬 수 있습니다.
탐지 규칙 기회:
FROM azure-openai-logs
| WHERE @timestamp > NOW() - 1 HOUR
| STATS request_count = COUNT(*), distinct_prompts = COUNT_DISTINCT(request.messages.content) BY connectorId
| WHERE request_count > 50 AND distinct_prompts > 10
| SORT request_count DESC
예제 2의 맥락에서 이 작업 쿼리는 지난 1시간 동안 azure-openai-logs
에서 각 connectorId
에 대한 모든 요청과 고유한 프롬프트 콘텐츠를 계산하여 사용 패턴을 효율적으로 추적하고 분석합니다. connectorId
이 기간 내에 10회 이상의 고유 프롬프트가 포함된 50 요청을 제출하는 경우, 이는 공격자가 암호화 알고리즘 세부 정보를 조사하기 위해 쿼리를 수정하여 과도한 부하를 유발하거나 탐지 시스템을 회피할 수 있는 설명과 같은 잠재적인 오용 패턴을 나타냅니다. 그런 다음 요청 횟수가 가장 많은 connectorIds
에 우선순위를 지정하여 가장 활동적이거나 의심스러운 소스를 빠르게 식별할 수 있도록 합니다.
LLM06 - 민감한 정보 공개
OWASP 설명: LLM 결과물에서 민감한 정보가 공개되지 않도록 보호하지 않으면 법적 처벌을 받거나 경쟁 우위를 잃을 수 있습니다. 여기를 참조하세요.
예시: 공격자는 학습 데이터에 포함된 민감한 정보를 추출하기 위해 프롬프트를 조작할 수 있습니다.
Prompt:
샘플 응답:
탐지 규칙 기회:
FROM azure-openai-logs
| WHERE @timestamp > NOW() - 1 DAY
| WHERE request.messages.content LIKE "*common*passwords*used*in*the*dataset*" AND malicious
| stats total_attempts = COUNT(*), users = COUNT_DISTINCT(connectorId)
BY identified_threats.keyword, analysis.langkit_score
| WHERE total_attempts >= 2
이 쿼리는 데이터 세트" 에서 모델 학습에 사용된 "일반 비밀번호에 대해 구체적으로 묻는 요청이 포함된 마지막 날의 로그와 이러한 요청이 악성으로 플래그가 지정된 로그를 검색합니다. 이러한 로그를 집계하여 이러한 시도의 횟수를 계산하고 식별된 위협과 언어 키트 점수에 따라 그룹화하여 관련 사용자를 식별합니다. AND malicious = true
을 포함하면 이미 잠재적으로 유해한 것으로 표시된 요청에 집중하여 조사 및 대응 조치의 우선순위를 정할 수 있습니다.
보안 인사이트로 탐지 규칙 강화하기
프록시를 통해 LLM 요청을 라우팅하면 특수 보안 도구를 활용하여 각 요청에 악의적인 의도가 있는지 분석할 수 있습니다. 탐지되면 원본 요청에 악성 콘텐츠의 가능성과 특정 유형의 위협을 나타내는 추가 메타데이터를 추가하여 보강할 수 있습니다. 이렇게 강화된 데이터는 Elasticsearch에서 색인되어 강력한 모니터링, 알림, 회고 분석 데이터 세트를 생성합니다. 이러한 보강을 통해 지난 섹션의 LLM 탐지 기회가 가능해졌습니다.
사용 가능한 모든 도구에 대해 자세히 설명할 수는 없지만, 여러 오픈 소스 도구가 등장하여 LLM 상호 작용을 분석하고 보호하는 다양한 접근 방식을 제공하고 있습니다. 이러한 도구 중 일부는 악성 프롬프트를 탐지하도록 학습된 머신 러닝 모델의 지원을 받습니다:
- Rebuff(깃허브): 머신러닝을 활용하여 LLM 상호작용을 통한 소셜 엔지니어링, 피싱 및 기타 악성 활동 시도를 식별하고 완화합니다. 사용 예시로는 요청 콘텐츠를 Rebuff의 분석 엔진에 전달하고 그 결과에 따라 "악성" 부울 필드로 요청에 태그를 지정하는 방법이 있습니다.
- LLM-Guard(GitHub): LLM 요청에서 유해한 패턴을 탐지하기 위한 규칙 기반 엔진을 제공합니다. LLM-Guard는 사전 정의된 카테고리를 기반으로 탐지된 위협을 분류하여 자세한 위협 분류를 통해 요청을 강화할 수 있습니다.
- LangKit(GitHub): LLM 모니터링 및 보안을 위해 설계된 툴킷인 LangKit은 요청 콘텐츠를 분석하여 적대적인 입력 또는 의도하지 않은 모델 동작의 징후를 확인할 수 있습니다. 사용자 지정 분석 기능을 통합하기 위한 후크를 제공합니다.
- Vigil-LLM(깃허브): 의심스러운 LLM 요청에 대한 실시간 모니터링 및 경고에 중점을 둡니다. 프록시 계층에 통합하면 잠재적인 보안 문제를 즉시 플래그 지정하여 요청 데이터를 경계 점수로 보강할 수 있습니다.
- 오픈 프롬프트 인젝션(GitHub): 프롬프트 인젝션 공격을 탐지하는 방법론과 도구를 제공하여 프롬프트 인젝션 기법과 관련된 특정 침해 지표로 요청 데이터를 보강할 수 있습니다.
참고: 이러한 도구의 대부분은 외부 LLM에 대한 추가 호출/비용이 필요하며, 위협 헌팅을 효과적으로 수행하려면 추가 인프라가 필요합니다.
LLM-guard와 LangKit을 사용하는 간단한 구현의 예는 다음과 같습니다:
def analyze_and_enrich_request(
prompt: str, response_text: str, error_response: Optional[dict] = None
) -> dict:
"""Analyze the prompt and response text for malicious content and enrich the document."""
# LLM Guard analysis
sanitized_prompt, results_valid_prompt, results_score_prompt = scan_prompt(
input_scanners, prompt["content"]
)
(
sanitized_response_text,
results_valid_response,
results_score_response,
) = scan_output(output_scanners, sanitized_prompt, response_text)
# LangKit for additional analysis
schema = injections.init()
langkit_result = extract({"prompt": prompt["content"]}, schema=schema)
# Initialize identified threats and malicious flag
identified_threats = []
# Check LLM Guard results for prompt
if not any(results_valid_prompt.values()):
identified_threats.append("LLM Guard Prompt Invalid")
# Check LLM Guard results for response
if not any(results_valid_response.values()):
identified_threats.append("LLM Guard Response Invalid")
# Check LangKit result for prompt injection
prompt_injection_score = langkit_result.get("prompt.injection", 0)
if prompt_injection_score > 0.4: # Adjust threshold as needed
identified_threats.append("LangKit Injection")
# Identify threats based on LLM Guard scores
for category, score in results_score_response.items():
if score > 0.5:
identified_threats.append(category)
# Combine results and enrich document
# llm_guard scores map scanner names to float values of risk scores,
# where 0 is no risk, and 1 is high risk.
# langkit_score is a float value of the risk score for prompt injection
# based on known threats.
enriched_document = {
"analysis": {
"llm_guard_prompt_scores": results_score_prompt,
"llm_guard_response_scores": results_score_response,
"langkit_score": prompt_injection_score,
},
"malicious": any(identified_threats),
"identified_threats": identified_threats,
}
# Check if there was an error from OpenAI and enrich the analysis
if error_response:
code = error_response.get("code")
filtered_categories = {
category: info["filtered"]
for category, info in error_response.get(
"content_filter_result", {}
).items()
}
enriched_document["analysis"]["openai"] = {
"code": code,
"filtered_categories": filtered_categories,
}
if code == "ResponsibleAIPolicyViolation":
enriched_document["malicious"] = True
return enriched_document
이 함수는 프록시를 통과하는 각 요청에 대해 호출될 수 있으며, 반환된 데이터는 Elasticsearch로 전송되기 전에 요청 문서에 추가됩니다. 그 결과 LLM과의 원시 상호 작용을 캡처하고 요청 및 응답을 기반으로 탐지 규칙에 포함할 수 있는 즉각적인 보안 인사이트를 제공하는 상세하고 실행 가능한 데이터 세트가 생성됩니다. 프롬프트 주입 LLM01 예제로 돌아가서 쿼리를 다음과 같이 업데이트할 수 있습니다:
FROM azure-openai-logs
| WHERE @timestamp > NOW() - 1 DAY
| WHERE identified_threats.keyword == "LangKit Injection" OR analysis.langkit_score > 0.4
| stats total_attempts = count(*), users = count_distinct(connectorId) by identified_threats.keyword, analysis.langkit_score
| WHERE users == 1 and total_attempts >= 2
보시다시피 두 채점 메커니즘 모두 오픈 소스 프롬프트 분석 도구에서 반환된 결과를 기반으로 하는 주관적인 방식입니다. 이 쿼리는 식별된 위협이 "LangKit Injection" 또는 LangKit 점수가 0.4
이상인 지난 날의 로그를 필터링합니다. 그런 다음 총 시도를 계산하고 식별된 각 위협 카테고리 및 LangKit 점수와 연관된 고유 사용자(에이전트) 수를 계산하여 사용자가 한 명이고(users == 1
) 총 시도가 두 번 이상인 경우만 포함하도록 필터링합니다(total_attempts >= 2
).
이러한 추가 도구를 사용하면 다양한 분석 결과 필드를 통해 탐지 규칙을 개선할 수 있습니다. 이 예제에서는 단순화를 위해 대부분의 데이터를 그대로 제공했습니다. 그러나 프로덕션 환경에서는 모든 도구와 LLM 응답에서 이러한 필드를 Elastic Common Schema (ECS)와 같은 스키마로 정규화하는 것이 중요합니다. ECS로 데이터를 정규화하면 서로 다른 데이터 소스 간의 상호 운용성이 향상되고 분석이 간소화되며 보다 효과적이고 일관된 보안 규칙 생성이 간소화됩니다.
이 시리즈의 2부에서는 ECS 필드 매핑 및 통합에 대해 보다 공식적인 접근 방식을 취한 방법에 대해 설명합니다.
LLM 신청서 심사를 위한 대체 옵션
프록시를 사용하는 것이 간단할 수도 있지만, 프로덕션 설정에 따라 다른 접근 방식이 더 적합할 수도 있습니다:
- 애플리케이션 성능 모니터링 (APM) 활용
- OpenTelemetry 통합 사용
- Kibana에서 직접 변경 사항을 수정하여 LLM 활동 감사 및 추적하기
당연히 이러한 접근 방식에는 타사 도구를 지원하기 위한 사용자 지정 로직을 개발하지 않고 생성된 모든 LLM 보안 분석 도구 데이터를 기본적으로 수집하지 못하는 등의 잠재적인 한계가 있습니다.
심층적인 애플리케이션 인사이트를 위해 Elastic APM 활용하기
Elastic APM은 성능 병목 현상을 감지하고 문제가 있는 요청이나 쿼리를 식별하는 데 필수적인 애플리케이션 실시간 모니터링을 위한 대안 솔루션을 제공합니다. Elastic APM을 통합함으로써 사용자는 트랜잭션 시간, 데이터베이스 쿼리 성능, 외부 API 호출 효율성 등에 대한 상세한 인사이트를 얻을 수 있습니다. 이러한 포괄적인 가시성을 통해 성능 문제나 오류를 더 쉽게 해결하고 신속하게 해결할 수 있습니다. 프록시 접근 방식과 달리, APM은 애플리케이션에 대한 로그를 Elastic으로 자동 수집하여 데이터 내에서 보이는 동작을 기반으로 보안 탐지 규칙을 생성할 수 있는 기회를 제공합니다.
통합 가시성 향상을 위한 OpenTelemetry 활용
이미 OpenTelemetry를 사용하고 있는 애플리케이션의 경우, Elastic APM과의 통합을 활용하면 광범위한 계측 변경 없이 통합 가시성을 향상시킬 수 있습니다. 이 통합은 추적 및 메트릭을 포함한 광범위한 원격 분석 데이터 캡처를 지원하며, 이를 Elastic Stack으로 원활하게 전송할 수 있습니다. 이 접근 방식을 통해 개발자는 익숙한 라이브러리를 계속 사용하면서 Elastic의 강력한 모니터링 기능의 이점을 누릴 수 있습니다. 여러 프로그래밍 언어에 걸친 OpenTelemetry의 호환성과 Elastic의 기본 프로토콜 (OTLP)을 통한 지원은 간단한 데이터 전송을 용이하게 하여 분산 시스템 모니터링을 위한 강력한 기반을 제공합니다. 프록시 예제와 비교할 때, 이 접근 방식은 독립적인 인덱스와 로깅 메커니즘을 Elastic에 유지하는 것보다 더 기본적으로 데이터를 수집합니다.
Kibana를 사용한 LLM 감사
데이터를 감사하고 전송하기 위해 LLM 애플리케이션을 위한 사용자 정의 로직을 작성하는 것처럼, Elastic의 AI Assistant로 접근 방식을 테스트할 수 있습니다. TypeScript에 익숙한 경우, Kibana 시작 가이드를 사용해 로컬 Elastic 인스턴스를 배포하는 것을 고려해 보세요. 설정이 완료되면 Elastic AI Assistant로 이동하여 감사 및 분석을 위해 LLM 요청과 응답을 가로채도록 구성하세요. 참고: 이 접근 방식은 주로 APM 및 기타 통합 또는 프록시를 사용하여 타사 애플리케이션을 추적하는 것과 비교하여 Elastic 고유의 LLM 통합을 추적합니다. 실험 및 탐색적 테스트 목적으로만 고려해야 합니다.
다행히도 Kibana는 이미 APM으로 계측되어 있으므로 APM 서버를 구성하면 이 소스에서 자동으로 로그 수집이 시작됩니다( elastic.apm.active: true
설정). 자세한 내용은 README를 참조하세요.
마무리 생각
Elastic에서 대규모 언어 모델의 수명 주기 내에 보안 관행을 통합하기 위한 이러한 탐색을 계속 진행하면서, LLM 워크플로우에 보안을 포함시키는 것이 보다 안전하고 신뢰할 수 있는 애플리케이션을 만들기 위한 길을 제공할 수 있다는 것이 분명해졌습니다. 분석가들이 가장 직관적이고 효과적이라고 생각하는 보안 솔루션을 활용하여 악성 활동을 선제적으로 탐지, 경고 및 분류하는 방법을 설명하는 이 인위적인 사례는 OnWeek 동안의 작업에서 도출된 것입니다.
프록시 접근 방식의 예시를 통해 요청을 적극적으로 감지하고 방지하는 모델을 통합할 수 있다는 점도 주목할 필요가 있습니다. 또한 악의적인 위협을 식별한 경우 사용자에게 다시 보내기 전에 LLM 응답을 분류할 수 있습니다. 현재로서는 다양한 방어 접근 방식을 포괄할 수 있도록 보안 보호 기능을 유연하게 확장할 수 있습니다. 이 경우 추가 검사를 수행할 때마다 시간이 소모되고 사용자가 기대하는 자연스러운 대화 흐름이 방해되므로 보안과 성능 사이에 미세한 경계가 존재합니다.
llm-detection-proxy에서 개념 증명 프록시를 확인하여 필요에 맞게 조정해 보세요!
저희는 항상 이와 같은 사용 사례와 워크플로우에 관심이 있으므로 언제나처럼 GitHub 이슈를 통해 저희에게 연락하거나 커뮤니티 Slack에서 채팅하고 토론 포럼에서 질문해 주세요.
이 게시물에서 설명된 기능이나 성능의 출시와 일정은 Elastic의 단독 재량에 따라 결정됩니다. 현재 제공되지 않는 기능이나 성능은 예정된 시간에 출시되지 않을 수도 있으며 아예 제공되지 않을 수도 있습니다.