Solana Upgrade Authority 보안: 대부분의 프로토콜이 배우지 못한 $40M 교훈
Source: Dev.to
죄송합니다만, 번역하려는 전체 텍스트를 제공해 주시면 해당 내용을 한국어로 번역해 드리겠습니다. 현재는 위의 소스 링크만 포함되어 있어 번역할 본문이 없습니다. 텍스트를 복사해서 알려 주시면 바로 번역해 드리겠습니다.
문제
solana program deploy 로 배포된 모든 Solana 프로그램은 기본적으로 업그레이드 가능합니다.
업그레이드 권한 – 단일 키페어 – 은 프로토콜에 갓모드 접근 권한을 가집니다: 프로그램 전체 바이너리를 교체할 수 있습니다. 타임락 없음. 멀티시그 없음. 경고도 없습니다.
2026년 1월 Step Finance 붕괴($40 M 유출)는 스마트‑컨트랙트 버그가 아니었습니다.
이는 업그레이드 권한 키를 보관하고 있던 임원용 디바이스가 탈취된 것이었습니다. 공격자는 코드 취약점이 필요 없었고, 프로그램을 교체할 키만 있으면 되었습니다.
만약 Solana 프로그램의 업그레이드 권한이 단일 핫 월렛이라면, 같은 운명을 맞이할 피싱 이메일 한 통만 남은 것입니다.
업그레이드 권한 작동 방식
Solana 프로그램을 배포하면 BPF Loader가 다음을 생성합니다:
- 실행 가능한 바이트를 포함하는 데이터 계정을 가리키는 프로그램 계정.
- 프로그램 계정 메타데이터에 저장된 업그레이드‑권한(pubkey).
해당 키를 제어하는 사람은 BPFLoaderUpgradeable::Upgrade를 호출해 전체 프로그램 바이너리를 교체할 수 있습니다.
예시: 프로그램을 누가 제어하고 있는지 확인하기
solana program show 출력
Program Id: YourProgram111111111111111111111111
Owner: BPFLoaderUpgradeab1e11111111111111111111111
ProgramData Address: ProgramData111111111111111111111
Authority: HotWa11et1111111111111111111111111 ← 단일 실패 지점
Last Deployed In: Slot 250000000
Data Length: 832456 bytesAuthority 필드가 바로 공격 대상입니다. 공격자가 이 키를 입수하면 다음을 할 수 있습니다:
- 모든 PDA를 탈취하는 악성 바이너리를 배포한다.
- 접근 제어를 우회하도록 프로그램 로직을 교체한다.
- 시간이 지남에 따라 자금을 빼돌리는 백도어를 삽입한다.
- 프로그램을 완전히 사용할 수 없게 만든다.
기본 권한 = 개발자의 로컬 키페어 (
~/.config/solana/id.json).
이는 60 % 이상의 Solana 프로그램이 메인넷에 배포되는 방식이며, 여러분 프로그램의 보안은 노트북 보안과 동일합니다.
위험 요소: 악성코드, 피싱, 기기 도난, 내부자 위협.
Source: …
업그레이드 권한 보안
1. 권한을 Ledger(하드웨어 지갑)로 이전
solana program set-upgrade-authority \
--new-upgrade-authority \
--keypair usb://ledger장점: 키가 핫 머신에 절대 노출되지 않음.
단점: 여전히 단일 키가 한 사람에게만 존재 → 버스 팩터 = 1.
위험: 물리적 도난, 강제, 단일 인물에 의한 타협.
2. 멀티시그 사용 (Squads Protocol – 표준 Solana 멀티시그)
import { Squads } from "@sqds/sdk";
// Create a multisig vault for upgrade authority
const multisigAccount = await squads.createMultisig(
2, // threshold: 2‑of‑3 required
createKey,
[
member1.publicKey, // CTO – hardware wallet
member2.publicKey, // Lead Dev – hardware wallet
member3.publicKey, // Security Lead – hardware wallet
]
);
// Transfer program upgrade authority to multisig
await squads.createProposalForProgramUpgrade(
multisigAccount,
programId,
bufferAddress,
spillAddress,
"v2.1.0 – Fix oracle validation"
);결과: 2‑of‑3 키 보유자가 업그레이드를 승인해야 함. 공격자는 서로 다른 보안 경계에 있는 여러 당사자를 동시에 타협해야 함.
위험: 여러 구성원을 대상으로 한 사회공학, 거버넌스 공격, 비상 대응 지연.
3. 제안과 실행 사이에 필수 지연(타임락) 추가
예시: 48시간 타임락이 적용된 커스텀 업그레이드 프로그램 (Anchor)
// ── Propose Upgrade ───────────────────────────────────────────────────────
pub fn propose_upgrade(ctx: Context, buffer: Pubkey) -> Result {
let proposal = &mut ctx.accounts.proposal;
proposal.buffer = buffer;
proposal.proposed_at = Clock::get()?.unix_timestamp;
proposal.execution_time = proposal.proposed_at + TIMELOCK_DURATION; // 48 h
proposal.approvals = 0;
proposal.executed = false;
emit!(UpgradeProposed {
program: ctx.accounts.program.key(),
buffer,
execution_time: proposal.execution_time,
});
Ok(())
}
// ── Execute Upgrade ───────────────────────────────────────────────────────
pub fn execute_upgrade(ctx: Context) -> Result {
let proposal = &ctx.accounts.proposal;
let now = Clock::get()?.unix_timestamp;
require!(proposal.approvals >= THRESHOLD, ErrorCode::InsufficientApprovals);
require!(now >= proposal.execution_time, ErrorCode::TimelockNotExpired);
require!(!proposal.executed, ErrorCode::AlreadyExecuted);
// Execute the BPFLoaderUpgradeable::Upgrade instruction via CPI
// ...
Ok(())
}
// ── Cancel Upgrade ───────────────────────────────────────────────────────
pub fn cancel_upgrade(ctx: Context) -> Result {
// Any single guardian can cancel during the timelock window
let proposal = &mut ctx.accounts.proposal;
require!(!proposal.executed, ErrorCode::AlreadyExecuted);
proposal.cancelled = true;
emit!(UpgradeCancelled {
program: ctx.accounts.program.key(),
cancelled_by: ctx.accounts.guardian.key(),
});
Ok(())
}효과: 공격자가 멀티시그를 탈취하더라도 커뮤니티는 48 시간 동안 다음을 수행할 수 있음:
- 무단 업그레이드 제안을 탐지한다.
- 단일 가디언이 이를 취소한다.
- 사용자에게 자금을 인출하도록 경고한다.
위험: 긴급 버그를 패치하는 데 시간이 더 걸림 (긴급 패스를 높은 임계값으로 두어 완화 가능).
4. 핵 옵션: 업그레이드 권한을 영구적으로 폐기
solana program set-upgrade-authority --final프로그램은 다시는 변경될 수 없음. 이는 보안상의 최상위 수준이지만 다음을 의미함:
- 버그 수정이 불가능.
- 기능 추가가 불가능.
- 코드가 완벽히 올바른지 확신해야 함.
최적 활용 사례: 핵심 AMM 로직, 토큰 계약, 브리지(광범위한 감사를 마친 후).
모두 합쳐 보기 – 성숙도 패턴
| 경로 | 거버넌스 | 타임락 | 실행 속도 |
|---|---|---|---|
| 일반 업그레이드 | 2‑of‑3 멀티시그 | 48 h | 표준 |
| 긴급 | 4‑of‑5 멀티시그 (확장된 위원회) | 4 h | 빠름 |
| 중대한 (활성 악용) | 5‑of‑5 멀티시그 | 0 h (즉시) | 즉시 + 자동 일시정지 |
핵심 인사이트: 긴급도가 높을수록 합의가 더 많이 필요하며, 낮아지는 것이 아닙니다. 정말 즉시 배포가 필요하다면, 모든 5명의 서명자가 참여할 수 있어야 합니다. 이는 위험이 가장 클 때입니다.
Source: …
TL;DR 체크리스트
- 기본 핫월렛 권한을 메인넷에 남겨두지 마세요.
- 권한을 하드웨어 월렛으로 이동하세요 (가능하면 멀티시그).
- 업그레이드 경로에 타임락을 추가하세요.
- 프로그램이 충분히 검증되면 최종화를 고려하세요.
- 업그레이드 프로세스를 문서화하고 팀에게 피싱/물리 보안 모범 사례를 교육하세요.
오늘 바로 업그레이드 권한을 보호하세요 – 이는 Solana 프로토콜을 보호하는 가장 중요한 키입니다.
업그레이드 권한 모니터링 및 보안 체크리스트
탐지는 예방만큼 중요합니다. 프로그램의 업그레이드 권한과 관련된 모든 상호작용에 대한 알림을 설정하세요:
import asyncio
from datetime import datetime
from solders.pubkey import Pubkey
from solana.rpc.websocket_api import connect
PROGRAM_ID = Pubkey.from_string("YourProgram111111111111111111111111")
BPF_LOADER = Pubkey.from_string("BPFLoaderUpgradeab1e11111111111111111111111")
async def monitor_upgrades():
async with connect("wss://api.mainnet-beta.solana.com") as ws:
# Subscribe to any transaction mentioning the BPF Loader + your program
await ws.logs_subscribe(
filter_={"mentions": [str(BPF_LOADER)]},
commitment="confirmed"
)
async for msg in ws:
logs = msg[0].result.value.logs
signature = msg[0].result.value.signature
# Check if this upgrade targets our program
if any("Upgrade" in log for log in logs):
if any(str(PROGRAM_ID) in log for log in logs):
await send_alert(
f"🚨 PROGRAM UPGRADE DETECTED!\n"
f"Program: {PROGRAM_ID}\n"
f"Tx: {signature}\n"
f"Time: {datetime.utcnow()}\n"
f"ACTION REQUIRED: Verify this was authorized"
)
async def send_alert(message: str):
# Send to Telegram, Discord, PagerDuty, etc.
print(message)
asyncio.run(monitor_upgrades())또한 SetAuthority 명령어를 모니터링하세요
공격자는 먼저 업그레이드 권한을 자신의 키로 이전하려 할 수 있습니다:
# Quick check: has your authority changed?
solana program show | grep AuthorityAudit Checklist (based on 2026 incidents such as Step Finance)
- Upgrade authority is NOT a single hot wallet → 업그레이드 권한은 단일 핫 월렛이 아님
- Multisig with ≥2‑of‑3 threshold → ≥2‑of‑3 임계값을 가진 멀티시그
- Each signer uses a hardware wallet → 각 서명자는 하드웨어 월렛을 사용함
- Signers are geographically distributed → 서명자들이 지리적으로 분산되어 있음
- No single person has access to the threshold number of keys → 단일 인물이 임계값에 해당하는 키에 접근할 수 없음
- Backup/recovery procedure documented and tested → 백업/복구 절차가 문서화되고 테스트됨
- Timelock of ≥24 hours for normal upgrades → 일반 업그레이드에 ≥24시간 타임락 적용
- Emergency path with higher threshold (not lower timelock) → 더 높은 임계값을 가진 비상 경로 (타임락을 낮추는 것이 아님)
- Program binary verified on‑chain before execution → 실행 전 체인 상에서 프로그램 바이너리 검증
- Buffer account contents independently verified by ≥2 parties → 버퍼 계정 내용이 ≥2 당사자에 의해 독립적으로 검증됨
- Upgrade proposals publicly announced before execution → 업그레이드 제안이 실행 전에 공개적으로 발표됨
- Real‑time alerts for
UpgradeandSetAuthorityinstructions →Upgrade및SetAuthority명령에 대한 실시간 알림 - Authority pubkey checked on every deployment → 매 배포 시 권한 공개키 확인
- On‑chain program hash verified against source code → 온체인 프로그램 해시를 소스 코드와 대조 검증
- Solana Explorer / Anchor Verifiable Builds used → Solana Explorer / Anchor 검증 가능한 빌드 사용
- Program pause mechanism exists (separate from upgrade authority) → 프로그램 일시정지 메커니즘 존재 (업그레이드 권한과 별도)
- Emergency contact list for all multisig signers → 모든 멀티시그 서명자를 위한 비상 연락처 목록
- Written runbook for “upgrade authority compromised” scenario → “업그레이드 권한이 손상된” 시나리오에 대한 서면 런북
- Regular drills (quarterly) to test emergency upgrade flow → 비상 업그레이드 흐름을 테스트하기 위한 정기 훈련 (분기별)
불변성으로 가는 단계적 경로
| 단계 | 기간 | 요구 사항 |
|---|---|---|
| 단계 1 (출시) | 즉시 | 2‑of‑3 멀티시그, 24 h 타임락 |
| 단계 2 | 6 개월 | 3‑of‑5 멀티시그, 48 h 타임락, ≥2개의 감사 완료 |
| 단계 3 | 1 년 | 핵심 로직 동결; 주변 모듈만 업그레이드 가능 |
| 단계 4 | 2년 이상 | 광범위한 실전 테스트 후 완전 불변성 달성 |
각 단계는 사용자에게 공개하는 약속입니다. 현재 단계와 다음 단계로 진행하기 위한 기준을 문서화하십시오.
Key Takeaways
- The $40 M loss at Step Finance shows that a program is only as secure as its upgrade authority.
- A perfectly audited contract is worthless if the key to replace it sits on an executive’s laptop.
- The fix isn’t exotic cryptography; it’s operational discipline:
- Move to multisig today.
- Add a timelock this quarter.
- Plan your path to immutability.
- Monitor everything.
Your users trust you with their funds. The least you can do is ensure a single compromised laptop can’t betray that trust.
DreamWork Security publishes weekly research on DeFi security patterns. Follow us for more Solana and EVM security analysis.