서명만으로는 충분하지 않다: 권한 검증에 '서명'과 '신선도'가 모두 필요한 이유 — CLAIM-25
요약
AI 에이전트의 권한 검증 시 서명뿐만 아니라 데이터의 신선도(freshness)가 필수적임을 설명합니다. 서명만 확인하는 게이트는 재전송 공격에 취약하므로, 소스 주소 고정 및 시퀀스 검증 등 네 가지 필수 속성을 갖춘 복합 게이트가 필요합니다.
핵심 포인트
- 서명만으로는 권한 취소 후의 재전송 공격을 막을 수 없음
- 권한 검증에는 서명(Signed)과 신선도(Fresh)가 모두 필요함
- 고정된 소스 주소, 서명 검증, 시퀀스 하한선, 하이 워터 마크가 필수 속성임
- 각 보안 속성은 특정 공격을 방어하는 독립적인 역할을 수행해야 함
AI 에이전트가 유효 기간(time-to-live) 내에 있는 권한(grant)을 보유하고 있더라도, 해당 권한을 정당화했던 소스(source)의 조건이 변경되었을 수 있습니다. 시계는 유효하다고 말하지만, 소스는 그렇지 않다고 말합니다. 타임스탬프(timestamp)만 확인하는 게이트(gate)는 이를 놓칩니다. 재유도(re-derivation) 게이트는 실행 시점에 소스를 다시 확인함으로써 이를 잡아냅니다.
그것이 CLAIM-24 레이어였습니다.
그 후 ANP2가 댓글을 통해 다음의 공백을 지적했습니다:
"발행자(issuer)에 의해 암호학적으로 서명된, 취소 전의 진정한 응답이 있습니다. 서명은 유효합니다. 하지만 시퀀스 번호(sequence number)가 취소 이벤트 이전의 것입니다. 당신의 게이트가 이를 잡아낼 수 있습니까?"
아니요.
서명만으로는 불가능합니다.
이것이 바로 CLAIM-25입니다: 권한 검증(authority verification)은 반드시 **서명(signed)**되어 있으면서 동시에 **신선(fresh)**해야 합니다. 이를 가능하게 하는 네 가지 속성은 단순히 장식적인 것이 아닙니다. 그중 하나라도 제거하면 특정 공격이 성공하게 됩니다.
서명 전용 게이트가 놓치는 공격
어떤 에이전트가 과거에 다음과 같은 읽기 권한을 가졌다고 가정해 봅시다:
read:credentials:dev
이후 발행자는 해당 권한을 취소하고 에이전트의 권한을 다음과 같이 하향 조정합니다:
read:logs:dev
권한 취소 전, 발행자는 이전 권한을 확인하는 응답에 서명했습니다. 그 응답은 실제이며, 서명도 유효합니다. 해당 응답의 시퀀스(sequence)는 8입니다.
권한 취소는 시퀀스 10에서 발생합니다.
서명 전용 게이트는 유효한 발행자 서명을 확인하고 ALLOW(허용)를 반환합니다.
하지만 이 응답은 권한 취소 이전에 생성된 것입니다. 인증되었지만 오래된(stale) 정보입니다.
이것이 바로 재전송 공격(replay window)의 구간입니다.
요구되는 네 가지 속성
CLAIM-25는 네 가지 필수 속성을 가진 복합 게이트를 테스트합니다:
- 고정된 소스 주소 (Pinned source address)
- 서명 검증 (Signature verification)
- 권한에 포함된 시퀀스 하한선 (Grant-carried sequence floor)
- 변조 방지 하이 워터 마크 (Tamper-evident high-water mark)
이 네 가지는 반드시 동시에 유지되어야 합니다.
중요한 점은 단순히 전체 게이트가 작동하는 것만이 아닙니다. 핵심은 각 속성마다 개별적인 제거 실험(ablation)이 필요하다는 것입니다. 특정 속성을 제거했을 때, 해당 속성이 방어하던 공격이 반드시 성공해야 합니다. 만약 공격이 성공하지 않는다면, 제어 로직이 혼동되어 해당 속성이 실제로 하중을 견디는(load-bearing) 역할을 하는지 알 수 없게 됩니다.
속성 1: 고정된 소스 주소 (Pinned Source Address)
게이트(gate)는 요청하는 에이전트(agent)가 런타임(runtime)에 어떤 소스(source)를 조회할지 선택하도록 허용해서는 안 됩니다.
만약 에이전트가 "이 소스를 확인해라"라고 말할 수 있다면, 공격자는 이전의 조건들을 반환하는 친숙한 소스로 대체할 수 있습니다. 그 응답은 신선할(fresh) 수도 있습니다. 심지어 친숙한 소스에 의해 서명(signed)되었을 수도 있습니다. 하지만 소스 자체가 잘못되었다면 그 어떤 것도 의미가 없습니다.
권한 부여(grant)에는 소스 주소가 포함됩니다:
{
"source_address": "policy://issuer/main"
}
실행 시점에, 게이트는 런타임 소스 주소를 권한 부여에 고정된(pinned) 소스와 비교합니다. 두 값이 일치하지 않으면 요청은 거부됩니다.
Ablation A3: 소스 고정(source pinning) 제거. 게이트는 런타임에 제공된 친숙한 소스를 수락합니다. 결과: ALLOW.
이는 소스 고정이 이 패킷에서 실제로 제 역할을 하고 있음을 확인시켜 줍니다.
속성 2: 서명 검증 (Signature Verification)
소스 응답은 발행자(issuer)에 의해 서명되어야 하며, 해당 서명은 반드시 검증되어야 합니다.
신선도(Freshness)만으로는 충분하지 않습니다. 위조된 응답은 어떠한 역할(role), 어떠한 범위(scope), 어떠한 시퀀스 번호(sequence number)라도 주장할 수 있기 때문입니다.
Ablation 패킷에서 공격자는 시퀀스(sequence) 50과 이전의 범위(scope)를 가진 위조된 응답을 제시합니다. 시퀀스 50은 권한 부여의 하한선(floor)보다 높습니다. 만약 서명 검증이 비활성화되어 있다면, 위조된 응답은 통과됩니다.
Ablation A4: 서명 검증 비활성화. 결과: ALLOW.
서명만으로는 충분하지 않습니다. 하지만 서명이 없다면 신선도 또한 위조될 수 있습니다.
속성 3: 권한 부여에 포함된 시퀀스 하한선 (Grant-Carried Sequence Floor)
이것은 재전송 공격(replay attack)의 창(window)을 닫는 속성입니다.
권한 부여에는 다음 내용이 포함됩니다:
{
"sequence_at_issue": 10
}
게이트는 시퀀스가 관련 하한선보다 낮은 모든 소스 응답을 거부합니다.
재전송 공격 시:
응답 시퀀스(response sequence) = 8
권한 부여 하한선(grant floor) = 10
저장된 마크(stored mark) = 12
게이트는 사용 가능한 가장 강력한 하한선을 사용합니다:
floor = max(grant.sequence_at_issue, stored_mark)
따라서 일반적인 재전송 사례에서는 다음과 같습니다:
floor = max(10, 12) = 12
sequence 8 < 12
REFUSED_STALE
콜드 스타트 (Cold-start) 사례는 더 까다롭습니다. 만약 게이트 (gate)가 재시작되어 저장된 마크 (stored mark)가 없다면, 로컬의 하이워터 스테이트 (high-water state)에 의존할 수 없습니다. 따라서 플로어 (floor)는 권한 부여 (grant)와 함께 전달되어야 합니다.
stored mark = none
grant floor = 10
sequence 8 < 10
...
Ablation A1: 권한 부여에 포함된 플로어 (grant-carried floor)를 제거하고, 저장된 마크를 삭제하여 콜드 스타트를 시뮬레이션합니다. 어떤 소스로부터의 플로어도 존재하지 않습니다. 결과: ALLOW.
이는 이 패킷에서 권한 부여에 포함된 플로어가 선택 사항이 아님을 확인시켜 줍니다.
속성 4: 변조 탐지 마크 (Tamper-Evident Mark)
저장된 하이워터 마크 (high-water mark)는 또 다른 재귀적 문제를 발생시킵니다.
만약 저장된 마크를 다시 쓸 수 있다면, 공격자는 이를 재전송된 응답 (replayed response)보다 낮은 값으로 낮출 수 있습니다:
original mark = 12
rewound mark = 5
response seq = 8
이제 시퀀스 (sequence) 8은 되돌려진 마크 (rewound mark)보다 높습니다. 만약 게이트가 재작성된 마크를 신뢰한다면, 재전송 공격 (replay)이 다시 성공하게 됩니다.
따라서 마크는 변조 탐지 (tamper-evident)가 가능해야 합니다. 만약 게이트가 저장된 마크가 낮아진 것을 감지하면, 시퀀스 신선도 (sequence freshness)를 확인하기 전에 거부합니다.
Ablation A2: 변조 탐지를 비활성화하고 마크 경로를 격리합니다. 마크가 5로 되돌려집니다. 재전송된 시퀀스는 8입니다. 결과: ALLOW.
이는 변조 탐지 또한 핵심적인 역할을 수행함을 확인시켜 줍니다.
절제 프로토콜 (The Ablation Protocol)
각 절제 (ablation)는 정확히 하나의 보호 경로를 제거하고, 그에 대응하는 공격이 성공하는지 확인합니다.
이것이 중요한 이유는 부실한 절제가 거짓 정보를 줄 수 있기 때문입니다. 만약 서명 검증 (signature verification)을 제거했는데 게이트가 다른 이유로 거부한다면, 당신은 서명 검증이 필요했다는 것을 증명한 것이 아닙니다. 단지 다른 무언가가 먼저 차단했다는 것만을 보여준 것입니다.
따라서 평가자는 최종 결정뿐만 아니라 구조적 증거 (structural witnesses)를 확인합니다.
| 절제 (Ablation) | 제거된 속성 (Removed property) | 예상되는 실패 (Expected failure) | 구조적 증거 (Structural witness) |
|---|---|---|---|
| A1 | Grant-carried floor | Cold-start replay passes | sequence_at_issue is None and stored_mark is None |
| ... |
네 가지 절제 모두 예상된 실패 모드를 생성했습니다.
그것이 주요 결과입니다. 복합 게이트(compound gate)는 이 패킷에서 정상 작동하며, 부정 대조군(negative controls)은 이 구현에서 각 부분이 왜 필요한지를 보여줍니다.
결과 (Results)
SignedFreshGate — 핵심 시나리오
E clean grant ALLOW PASS
...
베이스라인 (Baseline):
SignatureOnlyGate — 신선도(freshness) 없음
E clean grant ALLOW PASS
...
절제 실험 (Ablations):
SignedFreshGate — 절제 대조군
A1 no grant-carried floor ALLOW PASS
...
이 연구의 주장 (What This Claims)
내부적으로 작성된 9가지 시나리오 패킷을 대상으로 한 결과는 다음과 같습니다:
- 서명 전용 게이트(signature-only gate)는 재전송 공격(replay)의 창을 열어둡니다.
- 서명 및 신선도 결합(Signed-AND-fresh)은 패킷 내의 재전송 케이스를 차단합니다.
- 콜드 스타트(cold-start) 재전송을 방지하기 위해서는 권한(grant)에 포함된 시퀀스 하한선(sequence floor)이 필요합니다.
- 마크 롤백 재귀(mark rollback recursion)를 방지하기 위해서는 변조 방지 마크(tamper-evident mark)가 필요합니다.
- 런타임 소스 교체(runtime source substitution)를 방지하기 위해서는 소스 고정(source pinning)이 필요합니다.
- 신선도(freshness)만으로는 위조될 수 있기 때문에 서명 검증(signature verification)이 필요합니다.
- 절제 실험(ablation controls)을 통해 네 가지 속성 모두가 이 구현에서 핵심적인 역할을 수행함을 확인했습니다.
이것이 본 연구의 주장입니다.
이 연구의 주장이 아닌 것 (What This Does Not Claim)
이것은 완전한 운영 환경용 신뢰 모델(production trust model)이 아닙니다.
패킷은 내부적으로 작성되었습니다. 발행자(issuer), 소스 응답(source responses), 서명(signatures), 시퀀스 번호(sequence numbers), 그리고 마크 상태(mark states)는 시뮬레이션된 것입니다. 이 결과는 게이트 로직과 절제 실험 구조를 테스트합니다. 이 구현이 실제 배포를 위해 완전하다는 것을 증명하는 것은 아닙니다.
다음과 같은 미결 과제들이 남아 있습니다:
- 발행 시 권한(grant) 자체의 위조를 무엇이 방지하는가?
- 고정된 소스 엔드포인트(pinned source endpoint)가 침해되었으나 여전히 유효한 응답에 서명한다면 어떤 일이 발생하는가?
- 운영 환경에서 하이 워터 마크(high-water mark)를 어떤 저장 매체(storage substrate)에 보관해야 하는가?
- 권한, 소스 응답, 마크 업데이트, 그리고 최종 동작을 연결하는 감사 추적(audit trail)은 무엇이어야 하는가?
이것들은 숨겨진 가정이 아니라, 다음 단계의 레이어들입니다.
CLAIM-24와의 연결 (Connection to CLAIM-24)
CLAIM-24는 소스 드리프트 (source drift)로 인해 발생하는 오래된 권한 (stale authority)을 테스트했습니다. 이는 게이트 (gate)가 에이전트가 쓸 수 없는 소스로부터 현재 상태를 다시 도출 (re-derive)해야 함을 보여주었습니다.
CLAIM-25는 다음 공격 표면 (attack surface)을 테스트합니다: 응답이 인증되었더라도 (authentic), 해당 동작을 승인하기에는 너무 오래되었을 수 있습니다.
따라서 두 가지 클레임 (claims)은 다음과 같이 쌓입니다:
CLAIM-24: 오래된 캐시된 권한 (stale cached grants)을 신뢰하지 마라
CLAIM-25: 신선도 (fresh)가 보장되지 않는 한 서명된 응답 (signed responses)을 신뢰하지 마라
재도출 (Re-derivation)이 필요합니다.
서명된 신선도 (Signed freshness)가 필요합니다.
어느 한 레이어 (layer)만으로는 충분하지 않습니다.
코드 (The Code)
평가기 (evaluator), 게이트 구현체 (gate implementations), 시나리오 (scenarios), 그리고 결과 파일은 공개 리포지토리 (public repository)에 있습니다:
cd claim_25
python3 evaluator.py full
만약 이 게이트가 거부해야 할 동작을 허용하는 시나리오를 발견한다면, 이슈 (issue)를 생성해 주세요. 그것이 하네스 (harness)를 공개하는 목적입니다.
CLAIM-25는 2026년 6월 6일에 사전 등록되었습니다. 하네스 실행은 같은 날 확인되었습니다. 결과는 리포지토리에서 재현 가능합니다.
이것은 진행 중인 시리즈의 일부입니다: AI 에이전트의 메모리 (memory)와 권한 (authority)에 관한 반증 가능한 클레임 (falsifiable claims)이며, 공개적으로 테스트되며, 한계점은 사전에 명시됩니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기