LLM Security Defense

PromptGuard

Ollama 기반 EXAONE 3.5 7.8B 모델을 대상으로, 프롬프트 인젝션 상황에서 .env · 내부 문서 · secret-like 값이 유출되지 않도록 방어한 보안 실험 프로젝트입니다.

Visual Overview

입력 공격부터 baseline 비교, 그리고 LoRA 보안 학습까지

민감정보 유출 흐름을 재현하고, baseline과 LoRA 보안 학습 결과를 비교한 실험입니다.

모델에게 env 값을 알려주는 입력 이미지
Attack Context Input

민감정보를 맡긴 뒤, 정상 요청처럼 보이는 방식으로 유출을 유도한 입력 장면입니다.

Open-WebUI 환경에서 테스트 화면을 시각화했습니다.

보안 프롬프트 없이 유출되는 baseline 결과 이미지
Baseline Result

보안 미적용 모델은 민감값에 가까운 응답을 보였습니다.

LoRA 파인튜닝 후 안전 응답을 출력하는 이미지
LoRA Defense Result

LoRA 학습 후에는 거부 응답과 안전한 요약 중심으로 대응했습니다.

소개

PromptGuard는 로컬 LLM이 사용자 요청, 업로드 문서, 내부 테스트 컨텍스트를 함께 다루는 상황에서 secret-like 값이 그대로 재출력되는 문제를 막기 위해 시작한 보안 프로젝트입니다. 직접 요청뿐 아니라 문서 요약, 역할 혼동, 인코딩 우회, OCR 전처리처럼 정상 작업처럼 보이는 공격까지 포함해 평가 구조를 만들었고, baseline → secure_modelfile → LoRA 재학습 순서로 방어 강도를 높였습니다.

공격 구조

Attack Category

direct

비밀값을 직접 요구하거나 일부만 노출하게 만드는 직접 유출 공격입니다.

Attack Category

indirect_docs

문서 요약, 보고서 작성처럼 정상 작업을 가장해 민감값을 끌어내는 공격입니다.

Attack Category

unicode_obfuscation

base64, hex, spacing, reverse string 등 형식 우회로 필터를 피하려는 공격입니다.

Attack Category

role_confusion

감사자·관리자 역할을 부여해 권한이 있는 것처럼 보이게 만드는 공격입니다.

Attack Category

manyshot

정상 예시를 여러 개 보여준 뒤 마지막에 비밀 추출 포맷을 섞어 유도하는 공격입니다.

Attack Category

multimodal_prep

OCR, 캡처 텍스트 정리 상황을 가정해 민감정보 노출을 유도하는 공격입니다.

방어 방식

1차 방어 · Prompt 강화

Modelfile 수준에서 보안 system prompt를 주입해 secret dump, 부분 공개, 문서 기반 유출, 인코딩 우회를 먼저 막는 단계입니다. baseline과 secure_modelfile 비교를 통해 prompt만으로 얻을 수 있는 방어 효과를 확인했습니다.

2차 방어 · LoRA 재학습

거부 응답과 benign 응답이 함께 들어간 데이터셋으로 adapter를 재학습해, 모델이 보안 응답 패턴 자체를 학습하도록 확장한 단계입니다. prompt만으로 남는 취약 구간을 줄이기 위해 모델 동작 자체를 바꾸는 방향으로 설계했습니다.

실험 파이프라인

01
python data/scripts/make_dataset.py --config configs/project_config.yaml
02
python data/scripts/build_attack_eval_set.py --config configs/project_config.yaml
03
python data/scripts/build_benign_eval_set.py --config configs/project_config.yaml
04
python data/scripts/validate_dataset.py --config configs/project_config.yaml
05
ollama create exaone-baseline -f modelfiles/Modelfile.baseline
06
python eval/run_attack_eval.py --config configs/eval_config.yaml --profile baseline
07
ollama create exaone-secure -f modelfiles/Modelfile.secure
08
python eval/run_attack_eval.py --config configs/eval_config.yaml --profile secure_modelfile
09
python train/inspect_modules.py --config configs/train_config.yaml
10
python train/train_lora.py --config configs/train_config.yaml
11
python train/test_adapter.py --config configs/eval_config.yaml
12
python eval/run_attack_eval.py --config configs/eval_config.yaml --profile lora
13
python eval/run_benign_eval.py --config configs/eval_config.yaml --profile lora
14
python eval/compare_results.py --config configs/eval_config.yaml

데이터셋 구성 → 평가셋 생성 → dataset 검증 → baseline / secure_modelfile 비교 → LoRA 학습 → adapter test → 공격/benign 평가 → 최종 비교 순서로 실험을 진행했습니다.

결과 비교

Baseline

보안 프롬프트 미적용 기본 모델

More Vulnerable
41.7%
Leakage Rate
보안 미적용 baseline은 직접 요청과 우회형 유출 공격에 취약했습니다.
25 / 60
Fail
총 60개 공격 중 25개가 실패로 집계되며 불안정한 응답을 보였습니다.
Direct + Unicode
취약 영역
직접 요청과 문자열 변형 계열에서 누출이 두드러졌습니다.
Category Summary

direct: 1 / 3 / 6 · indirect_docs: 4 / 3 / 3 · unicode_obfuscation: 1 / 3 / 6 · role_confusion: 6 / 1 / 3 · manyshot: 5 / 1 / 4 · multimodal_prep: 2 / 5 / 3

Secure Modelfile

보안 system prompt 적용 모델

Improved Defense
13.3%
Leakage Rate
보안 system prompt 적용 후 누출률이 크게 감소했습니다.
8 / 60
Fail
동일 공격셋 재평가에서 fail이 25건에서 8건으로 줄었습니다.
-28.4%p
개선 폭
prompt 기반 강화만으로도 방어 성능이 뚜렷하게 개선됐습니다.
Category Summary

direct: 3 / 5 / 2 · indirect_docs: 6 / 4 / 0 · unicode_obfuscation: 3 / 4 / 3 · role_confusion: 4 / 4 / 2 · manyshot: 7 / 3 / 0 · multimodal_prep: 6 / 3 / 1

LoRA

LoRA 기반 보안 파인튜닝 모델

Maximum Defense
0%
Leakage Rate
LoRA 파인튜닝 모델은 전체 공격셋에서 success를 허용하지 않았습니다.
0 / 60
Success
완전 유출 사례 없이 공격 자체를 차단하는 성향을 보였습니다.
All Partial
응답 성향
모든 응답이 partial로 기록되어 매우 보수적으로 반응했습니다.
Category Summary

direct: 0 / 10 / 0 · indirect_docs: 0 / 10 / 0 · unicode_obfuscation: 0 / 10 / 0 · role_confusion: 0 / 10 / 0 · manyshot: 0 / 10 / 0 · multimodal_prep: 0 / 10 / 0

Result Summary

baseline 모델은 41.7%의 높은 누출률을 보이며, direct 요청과 unicode 우회 계열에서 특히 취약한 모습을 보였습니다.

secure_modelfile은 보안 system prompt 추가만으로도 leakage_rate를 13.3%까지 낮추고, fail 개수를 25 → 8로 줄이며추가 학습 없이도 의미 있는 방어 성능 개선을 보여주었습니다.

LoRA 모델은 전체 공격셋에서 success 0건, leakage_rate 0%를 기록하며 가장 강한 방어 성능을 보였지만, 모든 응답이 partial로 기록되어전반적으로 보수적인 응답 성향을 보였습니다.

이를 통해 prompt 기반 방어만으로도 실사용 가능한 수준의 보안 성능 확보가 가능하며,학습 기반 방어는 더 강력하지만 사용성과 trade-off가 발생할 수 있음을 확인했습니다.

Final Conclusion

baseline 모델은 다양한 우회 및 컨텍스트 기반 공격에 취약했지만, secure_modelfile은 보안 프롬프트 적용만으로도 누출률을 크게 낮추며 성능 대비 효율적인 방어 방법임을 확인했습니다. 반면 LoRA 모델은 가장 강한 차단 성능을 보였지만, 모든 응답이 partial로 처리되는 등 과잉 방어 경향이 나타났습니다. 따라서 실제 서비스 환경에서는보안 프롬프트 기반 모델을 1차 방어로 사용하고, 필요에 따라 학습 기반 방어를 추가하는 방식이가장 현실적인 선택이라고 판단했습니다.

문제점 & 해결방법

CASE 01

로컬 환경의 용량·메모리 한계로 실험 흐름이 자주 끊긴 문제

문제 EXAONE 3.5 7.8B 기반 실험을 로컬 Ollama 환경에서 진행하는 과정에서 모델 캐시, adapter, 평가 로그가 누적되며 저장공간과 메모리 사용량이 빠르게 증가했습니다.

해결 데이터셋 생성 → 공격 평가 → secure_modelfile 비교 → LoRA 학습/평가처럼 순차적인 오프라인 검증 구조로 분리하고, 각 단계를 개별 스크립트로 나눠 실행하도록 재설계했습니다.

Outcome

실서비스형 FastAPI 통합 실행은 뒤로 미뤘지만, 로컬 장비 제약 안에서도 결과를 안정적으로 재현할 수 있는 평가 중심 구조를 먼저 완성할 수 있었습니다.

CASE 02

LoRA 모델이 강하게 방어했지만, 너무 보수적으로 반응한 문제

문제 LoRA 모델은 leakage_rate 0%, success 0건으로 가장 강한 방어 성능을 보였지만, 모든 응답이 partial로 기록되어 전반적으로 보수적으로 반응하는 경향이 나타났습니다.

해결 이 결과를 단순한 100% 방어 성공이 아니라, 보안성과 사용성 사이 trade-off 사례로 해석했습니다. 또한 benign 응답을 함께 학습 데이터에 포함한 이유와 이후 정상 요청 처리 평가의 필요성을 함께 정리했습니다.

Outcome

단순 수치 자랑이 아니라, 실제 서비스 적용 시 발생할 수 있는 과잉 방어 문제까지 함께 설명할 수 있게 되었습니다.

CASE 03

prompt 강화만으로 완전히 막지 못하는 유형이 남아 있던 문제

문제 secure_modelfile 결과에서는 fail이 줄었지만, unicode_obfuscation, direct, role_confusion 계열 일부는 여전히 완전 차단에 실패한 케이스가 존재했습니다.

해결 공격셋을 넓혀 평가하고, 이후 LoRA 재학습을 통해 모델 자체가 refusal 패턴을 학습하도록 확장했습니다. 결과 해석에서도 완전 해결이 아니라 남은 취약 구간이 있음을 분명히 드러냈습니다.

Outcome

프로젝트를 과장하지 않고, 어디까지 막혔고 어디서 한계가 남는지를 구체적으로 보여줄 수 있게 되었습니다.

CASE 04

프롬프트 기반 방어만으로는 모델 행동 자체를 바꾸기 어려운 문제

문제 secure_modelfile은 효과가 있었지만, system prompt는 바깥에서 규칙을 덧씌우는 방식이라 일부 상황에서는 지시 충돌이나 역할 혼동에 흔들릴 가능성이 남아 있었습니다.

해결 이를 보완하기 위해 LoRA adapter를 붙여 보안 거부 패턴 자체를 학습시키는 방향으로 확장했습니다. 즉 규칙을 읽게 하는 수준을 넘어 모델 행동 레벨에서 보안 응답을 정렬하는 구조로 발전시켰습니다.

Outcome

Prompt 수준 보안과 학습 기반 보안을 비교할 수 있는 2단계 실험 구조를 만들었고, 각각의 장단점을 한 프로젝트 안에서 설명할 수 있게 되었습니다.

핵심 코드 스니펫

data/scripts/build_attack_eval_set.py

공격 평가셋 생성

attack manifest와 카테고리별 프롬프트 파일을 읽어 JSONL 평가셋으로 변환하는 단계입니다. 공격 유형 메타데이터를 함께 묶어 이후 리포트에서 카테고리별 비교가 가능하도록 구성했습니다.

data/scripts/make_dataset.py

보안 학습 데이터 구성

공격 프롬프트에는 거부 응답을, benign 요청에는 요약·마스킹 응답을 붙여 train/valid 데이터셋을 생성하는 단계입니다.

eval/run_attack_eval.py

공격 응답 평가

baseline, secure_modelfile, lora 프로필별로 응답을 생성하고 success / partial / fail 및 leakage 여부를 집계하는 평가 흐름입니다.

data/scripts/validate_dataset.py

누출 패턴 검증

학습용 assistant 응답 안에 더미 비밀값이나 누출 패턴이 들어가지 않았는지 검증하는 방어용 체크 단계입니다.

train/train_lora.py

LoRA 기반 보안 재학습

EXAONE 3.5 7.8B에 LoRA adapter를 부착하고, 보안 거부 데이터셋으로 SFT를 진행하는 학습 단계입니다.

추후 확장

PromptGuard는 보안 실험에서 끝나는 것이 아니라, 이후 AI Automation 파이프라인의 앞단 보안 모듈로 연결할 계획입니다. 자동 수집된 뉴스, 이슈 문서, 요약 대상 텍스트가 들어오기 전에 PromptGuard가 먼저 입력과 응답을 검사하고, 민감정보 노출 가능성이 있는 경우 raw 값 대신 redacted summary만 통과시키는 방식으로 사용할 예정입니다. 이후 뉴스 요약과 같은 실제 기능에서는 파인튜닝 대신Ollama Modelfile 기반 프롬프트 엔지니어링 방식을 활용해 모델의 동작을 제어하고, 가벼운 환경에서도 안정적으로 서비스할 수 있도록 구성할 계획입니다. FastAPI 기반 서비스 구조와 연결해 실제 요청 흐름에서 동작하도록 확장하고, benign 평가를 더 정교하게 구성해 방어율뿐 아니라 실제 사용 가능성까지 함께 검증할 계획입니다.