콘텐츠 대표 이미지 - ⚡ 플래시 론(Flash Loan) 공격과 DeFi 보안 취약점: 담보 없는 순간 대출은 어떻게 해킹 도구가 되었나 🔐

⚡ 플래시 론(Flash Loan) 공격과 DeFi 보안 취약점: 담보 없는 순간 대출은 어떻게 해킹 도구가 되었나 🔐

친구야, 은행에 가서 "담보는 없는데 1조 원만 빌려주세요. 대신 12초 안에 갚을게요"라고 하면 어떻게 될까? 당연히 경비원이 출동하겠지 😅
그런데 블록체인 세계에서는 이게 진짜로 가능해. 이름하여 플래시 론(Flash Loan). 그리고 이 마법 같은 도구가 지난 몇 년간 수천억 원 규모의 DeFi 해킹 사건들에 단골로 등장했어.

오늘은 플래시 론이 정확히 뭔지, 왜 "갚지 않으면 애초에 빌린 적도 없는 일"이 되는지, 해커들은 이걸 어떻게 무기로 바꿨는지, 그리고 프로토콜과 우리 같은 사용자는 어떻게 대비해야 하는지까지 차근차근 뜯어볼게. 커피 한 잔 들고 편하게 따라와 ☕

한 트랜잭션 안의 순간 대출 ① 대출 실행 담보 0원 ② 자금 사용 스왑·차익·청산 ③ 원금+수수료 같은 블록 상환 ④ 못 갚으면? 전부 되돌림 성공하거나, 아무 일도 없었던 것이 되거나

1. 플래시 론, 대체 정체가 뭐야? 🤔

1-1. "담보 없는 대출"이 가능한 이유: 원자성(Atomicity)

전통 금융에서 대출의 핵심은 신용과 담보야. 돈을 빌려준 사람은 "이 사람이 안 갚으면 어떡하지?"라는 위험을 지니까, 신용을 따지거나 집이나 예금을 담보로 잡지. DeFi(탈중앙화 금융)의 일반 대출 프로토콜도 비슷해. Aave나 Compound에서 돈을 빌리려면 빌리는 금액보다 더 많은 가치의 암호화폐를 먼저 맡겨야 하거든. 이걸 과담보(Over-collateralization)라고 불러.

그런데 플래시 론은 담보가 아예 필요 없어. 비결은 이더리움 같은 스마트 컨트랙트 플랫폼의 트랜잭션 원자성에 있어. 원자성이란 쉽게 말해 "전부 성공하거나, 전부 없던 일이 되거나"라는 성질이야. 하나의 트랜잭션 안에서 여러 작업을 순서대로 실행하다가 중간에 하나라도 실패(revert)하면, 그 트랜잭션에서 일어난 모든 상태 변경이 통째로 취소돼.

플래시 론은 이 성질을 영리하게 써먹어. 대출 컨트랙트는 이렇게 동작하거든.

1
대출 컨트랙트가 돈을 먼저 보내준다.
빌리는 사람(정확히는 빌리는 사람의 스마트 컨트랙트) 주소로 요청한 토큰을 전송해.
2
빌린 사람의 코드를 호출한다.
"자, 돈 줬으니 하고 싶은 거 해"라며 미리 약속된 콜백 함수(예: Aave의 executeOperation)를 실행시켜. 이 안에서 스왑, 차익거래, 청산 등 원하는 걸 마음대로 해.
3
콜백이 끝나면 잔고를 확인한다.
원금과 수수료가 돌아왔는지 검사해. 돌아왔다면 트랜잭션 성공 ✅
4
안 돌아왔다면 전체를 되돌린다.
revert가 발생해서 1번의 송금까지 포함한 모든 것이 취소돼. 블록체인 입장에선 대출 자체가 존재하지 않았던 거야 ❌

그러니까 빌려주는 쪽은 떼일 위험이 구조적으로 0이야. 돈이 사라지는 시나리오 자체가 존재하지 않으니 담보를 받을 이유도 없지. 이게 바로 "1조 원도 담보 없이 빌릴 수 있는" 비밀이야. 실제로 대출 가능한 상한은 단 하나, 그 풀에 들어 있는 유동성 크기뿐이야.

💡 비유하자면
무인 편의점에서 "물건을 들고 계산대를 통과하기 전에 결제가 안 되면, 문이 열리지 않고 물건이 자동으로 진열대에 돌아가는 시스템"이라고 생각하면 돼. 손님은 매장 안에서 물건을 자유롭게 써볼 수는 있지만, 결제 없이 나가는 미래는 아예 존재하지 않는 거지.

1-2. 짧은 역사: 아이디어에서 표준까지

플래시 론 개념은 2018년 무렵 Marble 프로토콜 등에서 "스마트 컨트랙트 은행" 아이디어로 소개됐고, 2020년 1월 Aave가 정식 기능으로 출시하면서 대중화됐어. 비슷한 시기 dYdX의 마진 거래 시스템도 여러 동작을 한 트랜잭션에 묶을 수 있어서 사실상 무수수료 플래시 론처럼 쓰였고, Uniswap V2는 토큰을 먼저 받아가고 나중에 지불하는 플래시 스왑(Flash Swap)을 도입했지. 이후 Balancer, MakerDAO(DSS Flash) 같은 곳도 플래시 민트·플래시 론을 지원했어.

개발자 생태계에서는 인터페이스를 통일하기 위해 ERC-3156이라는 플래시 론 표준도 제안됐어. 덕분에 여러 대출원을 같은 방식으로 호출할 수 있게 됐지.

제공처방식수수료 특징
Aave V2flashLoan대출액의 0.09%
Aave V3flashLoan / flashLoanSimple기본 0.05% (거버넌스로 조정 가능)
Uniswap V2·V3플래시 스왑풀의 거래 수수료 수준
BalancerVault 플래시 론무수수료로 운영된 시기가 길었음
dYdX(구 Solo Margin)여러 동작 묶음 실행사실상 무수수료로 널리 활용

※ 수수료율은 프로토콜 버전·거버넌스 결정에 따라 바뀔 수 있으니, 실제 사용 전에는 반드시 최신 공식 문서를 확인해야 해.

1-3. 코드로 보는 플래시 론의 뼈대

개념만으로는 감이 덜 올 수 있으니 Aave V3 스타일의 단순화된 수신 컨트랙트를 볼게. (교육용으로 핵심만 남긴 거라 실제 배포용이 아니야!)

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

interface IPool {
    function flashLoanSimple(
        address receiver, address asset, uint256 amount,
        bytes calldata params, uint16 referralCode
    ) external;
}

interface IERC20 {
    function approve(address spender, uint256 amount) external returns (bool);
}

contract MyFlashReceiver {
    IPool public immutable pool;

    constructor(address _pool) { pool = IPool(_pool); }

    // 1) 대출 요청
    function start(address asset, uint256 amount) external {
        pool.flashLoanSimple(address(this), asset, amount, "", 0);
    }

    // 2) 풀이 돈을 보낸 뒤 호출하는 콜백
    function executeOperation(
        address asset, uint256 amount, uint256 premium,
        address initiator, bytes calldata
    ) external returns (bool) {
        require(msg.sender == address(pool), "only pool");
        require(initiator == address(this), "only self");

        // ---- 여기서 빌린 돈으로 차익거래 등 수행 ----

        // 3) 원금 + 수수료를 가져가도록 승인
        IERC20(asset).approve(address(pool), amount + premium);
        return true;
    }
}

눈여겨볼 건 두 개의 require야. 콜백을 누가 불렀는지, 대출을 누가 시작했는지 검사하지 않으면 다른 사람이 내 컨트랙트를 통해 플래시 론을 걸어 내 컨트랙트에 남은 자금을 수수료로 빼가게 만들 수도 있어. 플래시 론을 "쓰는 쪽"에서도 보안이 필요하다는 첫 번째 교훈이지 🔍


2. 원래는 착한 도구였어 😇 플래시 론의 정상적인 쓰임새

플래시 론이 해킹 뉴스에 자주 나오다 보니 "악마의 도구" 이미지가 생겼는데, 사실 원래 목적은 자본 효율성이야. 돈이 없어도 좋은 기회를 실행할 수 있게 해주는 민주화된 금융 도구라고 할 수 있지.

🔁 차익거래(Arbitrage)
A 거래소에선 ETH가 2,000달러, B 거래소에선 2,010달러라면? 빌려서 A에서 사고 B에서 팔고 갚으면 끝. 이 과정이 거래소 간 가격을 맞춰주는 순기능도 있어.
🧯 청산(Liquidation)
담보 가치가 떨어진 대출을 청산하려면 빚을 대신 갚을 돈이 필요해. 플래시 론으로 갚고, 할인된 담보를 받아 팔아서 상환하면 자본 없이도 청산인이 될 수 있어.
🔄 담보 교체(Collateral Swap)
ETH 담보를 WBTC 담보로 바꾸고 싶을 때, 대출을 다 갚고 다시 빌리는 대신 한 트랜잭션에서 교체할 수 있어.
📉 셀프 청산·부채 정리
내 포지션이 청산 당하기 직전에 스스로 빚을 정리해서 청산 페널티를 피하는 용도로도 써.

이렇게 보면 플래시 론은 망치 같은 존재야. 집을 짓는 데도 쓰이지만, 누군가는 창문을 깨는 데 쓸 수도 있는 거지. 중요한 건 망치를 금지하는 게 아니라 창문을 튼튼하게 만드는 것이고, 이게 오늘 이야기의 핵심 결론이기도 해.


3. 왜 해커들의 최애 도구가 됐을까? 🦹

3-1. "자본 장벽"이 사라졌다

예전에는 시장을 조작하려면 엄청난 돈이 필요했어. 어떤 토큰 가격을 크게 흔들려면 수백억 원어치를 사고팔아야 하는데, 그 정도 자본가는 많지 않고 신원도 드러나기 쉽지. 그런데 플래시 론은 지갑에 가스비와 수수료 정도만 있는 익명의 누군가에게 일시적으로 고래급 자본을 쥐여줘.

즉 플래시 론은 취약점 자체를 만드는 게 아니라, 원래 존재하던 취약점을 "거대 자본이 있어야만 공격 가능한 상태"에서 "누구나 공격 가능한 상태"로 바꿔버리는 증폭기야. 보안 업계에서 "플래시 론 공격"이라는 표현을 쓰긴 하지만, 엄밀히는 "플래시 론으로 자금을 조달한 공격"이라고 보는 게 정확해.

3-2. 실패해도 잃는 게 거의 없다

공격이 실패하면? 트랜잭션이 revert되고 끝이야. 대출금은 원래대로 돌아가고 공격자가 잃는 건 가스비 정도야. 반대로 성공하면 수백억 원을 손에 쥐지. 위험은 작고 보상은 큰 비대칭 구조가 공격 동기를 극대화해.

3-3. 한 블록 안에 끝나서 대응할 시간이 없다

이더리움 블록 간격은 약 12초야. 공격은 단 하나의 트랜잭션, 단 하나의 블록 안에서 시작하고 끝나. 운영팀이 모니터링 알림을 받고 "어, 뭔가 이상한데?" 하는 순간 이미 상황 종료라는 뜻이야. 그래서 사후 대응이 아니라 설계 단계의 방어가 핵심이 돼.

3-4. 머니 레고(Money Lego)의 양면성

DeFi의 자랑은 조합성(Composability)이야. 대출 프로토콜, 거래소, 수익 농사, 파생상품이 레고처럼 서로 끼워 맞춰지지. 문제는 내 프로토콜이 안전해도 내가 의존하는 다른 프로토콜의 가격이나 상태가 조작되면 같이 무너진다는 거야. 플래시 론 공격 대부분은 이런 프로토콜 간 의존 관계의 틈을 파고들어.

⚠️ 핵심 정리
플래시 론 공격 = (거대한 일회성 자본) × (조작 가능한 가격 또는 허술한 로직) × (원자적 실행)
이 셋 중 가운데 항목만 막아도 공격은 성립하지 않아. 그래서 방어의 초점은 언제나 "취약한 설계"에 맞춰져야 해.


4. 공격 유형 ①: 가격 오라클 조작 📊 (가장 흔한 패턴)

4-1. 오라클이 뭐길래?

블록체인은 바깥세상을 직접 볼 수 없어. 그래서 "지금 ETH가 얼마야?" 같은 정보를 알려주는 오라클(Oracle)이 필요해. 대출 프로토콜은 이 가격으로 "담보 가치가 얼마니까 얼마까지 빌려줄게"를 계산하지.

문제는 일부 프로토콜이 가격을 탈중앙화 거래소(DEX) 풀의 현재 비율에서 바로 읽어왔다는 거야. 이걸 현물 가격(Spot Price) 오라클이라고 해. 계산이 쉽고 실시간이라 편하지만, 그 풀의 비율은 누군가 큰 거래를 하면 즉시 바뀌어. 그리고 플래시 론은 그 "큰 거래"를 누구나 할 수 있게 만들어주지.

4-2. AMM의 수학: x × y = k

Uniswap V2 같은 자동화 마켓 메이커(AMM)는 두 토큰의 수량 곱이 일정하게 유지되는 상수곱 공식을 써. 풀에 토큰 A가 x개, 토큰 B가 y개 있으면 x × y = k가 항상 유지되고(수수료 제외), A의 가격은 대략 y ÷ x로 결정돼.

숫자로 해볼게. 풀에 1,000 ETH와 2,000,000 USDC가 있다고 하자.

📌 조작 전
k = 1,000 × 2,000,000 = 2,000,000,000
ETH 가격 ≈ 2,000,000 ÷ 1,000 = 2,000 USDC

📌 공격자가 플래시 론으로 빌린 1,000 ETH를 풀에 던지면
새 ETH 수량 x = 2,000
새 USDC 수량 y = 2,000,000,000 ÷ 2,000 = 1,000,000
공격자가 받는 USDC = 2,000,000 − 1,000,000 = 1,000,000
풀 기준 ETH 가격 ≈ 1,000,000 ÷ 2,000 = 500 USDC 😱

단 한 번의 거래로 이 풀이 말하는 ETH 가격이 75% 폭락했어. 실제 시장의 ETH 가치는 그대로인데 말이야.

상수곱 곡선 위의 가격 조작 A: 정상 가격 2,000 USDC B: 조작된 가격 500 USDC 풀 안의 ETH 수량 (오른쪽일수록 많음) USDC 수량 ETH를 대량 투입하면 곡선을 따라 B로 미끄러진다

4-3. 오라클 조작 공격의 전형적인 시나리오

이제 이 조작된 가격을 그대로 믿는 대출 프로토콜이 있다고 해볼게. 공격자는 이렇게 움직여.

1
플래시 론으로 거액 조달 — Aave, Balancer, Uniswap 등에서 수천만~수억 달러를 빌려.
2
오라클이 참조하는 풀을 비틀기 — 담보로 쓸 토큰 가격은 올리거나, 빌릴 토큰 가격은 내리도록 대량 스왑을 해.
3
부풀려진 가격으로 이득 취하기 — 비싸 보이는 담보로 실제 가치보다 훨씬 많이 빌리거나, 싸 보이는 자산을 대량 확보해.
4
풀 되돌리기 — 반대 방향 스왑으로 풀 가격을 원상태 근처로 돌려 손실을 최소화해.
5
플래시 론 상환 + 차익 챙기기 — 원금과 수수료를 갚고, 남은 돈을 들고 사라져. 대출 프로토콜에는 상환되지 않을 부실 채권만 남지.

여기서 포인트는, 공격자가 쓰는 비용이 스왑 수수료 + 슬리피지 손실 + 플래시 론 수수료 + 가스비라는 거야. 피해 프로토콜에서 빼낸 금액이 이 비용보다 크면 공격은 "수익성 있는 사업"이 돼. 유동성이 얕은 풀을 오라클로 쓸수록 조작 비용이 싸지니, 공격자 입장에선 얕은 풀 + 현물 가격 오라클 조합이 최고의 먹잇감이야.

4-4. 변형: LP 토큰·볼트 지분 가격 조작

조작 대상이 꼭 일반 토큰 가격일 필요는 없어. 수익 농사(Yield) 볼트의 지분 1개당 가치(pricePerShare)나 유동성 공급자(LP) 토큰 가격을 계산하는 공식이 풀의 순간 잔고에 의존하면, 그것도 조작돼. 예를 들어 볼트가 "내가 가진 자산 ÷ 발행한 지분 수"로 지분 가치를 계산하는데 누군가 볼트에 토큰을 대량으로 기부(donate)해서 분자를 갑자기 키우면, 지분 가치가 순간적으로 튀어 오르는 거지. 이른바 도네이션 공격이나 지분 인플레이션 공격이 여기서 나와.

LP 토큰은 더 까다로워. LP 토큰 가치를 "풀 안의 각 토큰 수량 × 각 현물 가격"으로 단순 합산하면, 풀 비율을 비트는 순간 계산이 틀어져. 그래서 업계에서는 상수곱 불변량과 외부 오라클 가격을 결합해 LP 가치를 계산하는 이른바 공정 LP 가격(Fair LP Pricing) 방식이 권장돼 왔어.


5. 공격 유형 ②: 거버넌스 탈취 🗳️

5-1. 투표권을 "빌릴" 수 있다면?

많은 DeFi 프로토콜은 토큰 보유자들이 투표로 운영 방향을 결정하는 DAO 거버넌스를 써. 토큰을 많이 가질수록 투표권도 커지지. 그런데 만약 투표권을 계산할 때 "지금 이 순간 들고 있는 토큰"을 기준으로 하고, 투표 통과와 실행이 같은 트랜잭션 안에서 가능하다면? 그렇다, 플래시 론으로 투표권을 잠깐 빌려서 원하는 안건을 통과시킬 수 있어.

5-2. 대표 사례: Beanstalk (2022년 4월)

스테이블코인 프로토콜 Beanstalk는 2022년 4월 17일 이 방식으로 털렸어. 당시 Beanstalk에는 안건이 일정 기간 이후 3분의 2 이상의 찬성을 얻으면 즉시 실행할 수 있는 emergencyCommit 기능이 있었어. 공격자의 흐름을 정리하면 이래.

1
하루쯤 전에 악성 안건(BIP)을 미리 제출해둬. 내용은 프로토콜 자금을 특정 주소로 보내는 코드였고, 겉으로는 우크라이나 기부처럼 보이게 꾸몄어.
2
대기 기간이 지난 뒤, Aave 등에서 약 10억 달러 규모의 플래시 론을 끌어와.
3
빌린 자산으로 Curve의 BEAN 관련 LP 토큰을 만들어 Beanstalk에 예치, 막대한 투표권을 순간적으로 확보해.
4
3분의 2 기준을 넘긴 상태에서 emergencyCommit으로 안건을 즉시 실행, 프로토콜 자산을 빼내.
5
플래시 론을 갚고, 남은 자금(대략 8천만 달러 안팎으로 보도됨)을 챙겨 Tornado Cash 등으로 이동시켜.

프로토콜 전체 손실은 약 1억 8천만 달러 수준으로 보도됐어. 흥미로운 건 공격자가 실제로 우크라이나 기부 주소에 약 25만 달러를 보냈다는 점이야. 냉소적인 유머랄까… 🫠

빌린 표로 넘긴 3분의 2 문턱 2/3 기준 일반 투표 플래시 론 투표권 즉시 실행된 악성 안건 투표·실행이 한 트랜잭션이면 표도 빌릴 수 있다

5-3. 거버넌스 공격의 근본 원인

⏱️ 시차 부재
투표권 획득 → 투표 → 실행이 한 블록 안에 끝날 수 있었어. 타임락이 있었다면 커뮤니티가 대응할 시간이 생겼겠지.
📸 현재 잔고 기준
과거 특정 블록의 잔고(스냅샷)가 아니라 현재 잔고로 투표권을 셌어. 빌린 토큰도 똑같이 한 표가 된 거야.
🚨 비상 우회로
"비상 실행" 같은 빠른 경로는 편리하지만, 공격자에게도 똑같이 빠른 경로가 돼.

이후 DeFi 업계에서는 투표권 스냅샷(예: OpenZeppelin의 ERC20Votes처럼 과거 블록 기준 투표권 조회), 투표 지연과 실행 타임락, 위임 기간 요구 등이 사실상 기본 설계로 자리 잡았어.


6. 공격 유형 ③: 비즈니스 로직 결함 🧩

6-1. 가격은 멀쩡한데 계산이 틀렸다면

오라클이 완벽해도 프로토콜 내부 회계 로직에 구멍이 있으면 플래시 론이 그 구멍을 "대규모로" 벌려. 이 유형은 코드마다 모양이 제각각이라 패턴화가 어렵고, 그래서 더 무서워.

6-2. 대표 사례: Euler Finance (2023년 3월)

2023년 3월 13일, 대출 프로토콜 Euler Finance에서 약 1억 9,700만 달러가 빠져나갔어. 핵심 원인은 donateToReserves라는 함수였어. 이 함수는 사용자가 자기 예치금(eToken)을 프로토콜 준비금으로 기부할 수 있게 해줬는데, 기부 후 그 계정의 건전성(health) 검사를 하지 않았어.

공격자는 대략 이렇게 움직였어.

① Aave에서 DAI를 플래시 론으로 빌림
② Euler에 예치하고 레버리지 기능(mint)으로 예치·부채를 동시에 부풀림
③ donateToReserves로 예치금 일부를 기부 → 계정이 일부러 부실 상태가 됨
④ 다른 공격자 계정이 이 부실 계정을 청산하면서 큰 할인율로 담보를 넘겨받음
⑤ 받은 담보를 인출해 플래시 론 상환, 차익 확보

즉 "스스로를 부실하게 만들고, 스스로를 할인 청산해서 이득을 보는" 구조였지. 각 함수는 따로 보면 그럴듯했지만, 조합했을 때의 불변 조건(invariant)이 깨진 거야. 이 사건은 이후 공격자가 협상 끝에 대부분의 자금을 반환한 이례적인 결말로도 유명해.

6-3. 자주 보이는 로직 결함 패턴

패턴설명플래시 론의 역할
상태 검증 누락자산 이동 후 담보 비율·건전성 재검사를 빼먹음검사 안 하는 틈에 거대한 포지션을 만들어 이득 극대화
지분 계산 반올림 오류지분 발행·소각 시 나눗셈 반올림 방향이 공격자에게 유리미세한 오차를 큰 금액·반복 호출로 증폭
첫 예치자 인플레이션빈 볼트에 소량 예치 후 대량 기부로 지분 가치 왜곡기부할 거액을 순간 조달
보상 분배 스냅샷 오류보상을 "현재 예치량" 기준으로 계산보상 계산 직전 거액 예치, 직후 인출
잘못된 회계 순서잔고 갱신 전에 외부 호출이나 가격 계산중간 상태를 이용한 대규모 거래

7. 공격 유형 ④: 재진입(Reentrancy)과의 콤보 🔄

7-1. 재진입이 뭐더라?

재진입은 스마트 컨트랙트 보안의 고전이야. 컨트랙트 A가 외부로 돈을 보내거나 외부 컨트랙트를 호출할 때, 받는 쪽이 그 틈에 다시 A를 호출해서 아직 갱신되지 않은 상태를 이용하는 공격이지. 2016년 The DAO 해킹이 대표 사례고, 그 여파로 이더리움 하드포크까지 일어났어.

플래시 론과 결합하면 재진입으로 반복 인출할 수 있는 금액의 규모가 훨씬 커져. 재진입 자체는 "몇 번이나 빼먹을 수 있나"의 문제고, 플래시 론은 "한 번에 얼마나 크게 할 수 있나"를 키워주는 셈이야.

7-2. 읽기 전용 재진입(Read-only Reentrancy)

최근에 주목받은 변형이 읽기 전용 재진입이야. 공격자가 상태를 바꾸는 게 아니라, 어떤 풀이 업데이트를 반쯤 끝낸 어정쩡한 순간에 다른 프로토콜이 그 풀의 가격 조회 함수(view 함수)를 부르도록 유도하는 거지. 예를 들어 Curve의 일부 풀은 유동성 제거 과정에서 네이티브 ETH를 보내는 시점에 내부 값이 일시적으로 불일치하는 구간이 있었고, 이 순간의 get_virtual_price 같은 값을 그대로 믿은 외부 프로토콜들이 피해를 입은 사례들이 보고됐어(2023년 dForce 사건 등).

여기서 교훈은 "view 함수는 안전하다"는 통념이 깨졌다는 거야. 값을 읽어오는 쪽에서도 "이 값이 지금 일관된 상태인가?"를 의심해야 해.


8. 사건 파일 📁: 연대기로 보는 주요 플래시 론 공격

이제 실제 역사를 따라가 볼게. 피해 규모는 사건 당시 보도·사후 분석 보고서 기준의 대략적인 값이고, 코인 가격 변동 때문에 자료마다 차이가 있을 수 있어.

시기프로토콜대략적 피해핵심 원인
2020.02bZx (1차·2차)약 35만 달러 / 약 64만 달러얕은 DEX 유동성 가격 조작, 외부 가격 의존
2020.10Harvest Finance약 2,400만~3,400만 달러Curve 스테이블 풀 가격 비틀기로 볼트 지분가 왜곡
2021.05PancakeBunny (BSC)약 4,500만 달러 수준LP·보상 계산이 조작 가능한 풀 가격에 의존
2021.10Cream Finance약 1억 3천만 달러yUSD 볼트 지분 가격 조작(기부 방식)
2022.04Beanstalk약 1억 8천만 달러플래시 론 거버넌스 탈취, 즉시 실행
2023.03Euler Finance약 1억 9,700만 달러donateToReserves 건전성 검사 누락

8-1. bZx: 플래시 론 공격의 시작

2020년 2월, 플래시 론 공격이 처음으로 크게 이슈가 된 사건이야. 1차 공격에서 공격자는 dYdX에서 1만 ETH를 빌려 일부는 Compound에 담보로 넣어 WBTC를 빌리고, 일부로는 bZx(Fulcrum)에서 레버리지 숏 포지션을 열었어. 이 숏 포지션 주문이 유동성이 얕은 Uniswap의 WBTC 풀을 거치도록 되어 있어서 WBTC 가격이 크게 튀었고, 공격자는 빌려둔 WBTC를 그 비싼 가격에 처분해 이득을 봤지. 며칠 뒤 2차 공격에선 sUSD 가격을 Uniswap·Kyber에서 끌어올린 뒤 부풀려진 sUSD를 담보로 ETH를 과다 대출받았어.

이 사건이 남긴 건 "DEX 하나의 현물 가격을 신뢰하면 안 된다"는 교훈이었고, 이후 업계가 Chainlink 같은 탈중앙 오라클과 TWAP로 이동하는 계기가 됐어.

8-2. Harvest Finance: 스테이블코인도 흔들린다

2020년 10월 26일, 수익 농사 애그리게이터 Harvest Finance가 당했어. 공격자는 Curve의 Y 풀에서 USDC·USDT 비율을 크게 비틀어, 볼트가 계산하는 자산 가치를 일시적으로 낮췄어. 싸게 계산될 때 볼트에 예치하고, 가격을 되돌린 뒤 비싸게 계산될 때 인출하는 걸 여러 번 반복했지. 스테이블코인끼리의 미세한 가격 차이였지만 금액이 워낙 커서 피해가 막대했어. 공격자가 나중에 일부(약 250만 달러)를 돌려보낸 것도 화제가 됐어.

교훈: "1달러짜리끼리 교환하는 풀이니 안전하겠지"는 착각이야. 어떤 풀이든 거대 자본 앞에서는 비율이 흔들려.

8-3. PancakeBunny: 보상 계산의 함정

2021년 5월, BNB 체인의 수익 최적화 프로토콜 PancakeBunny에서 공격자는 플래시 론으로 PancakeSwap 풀의 가격을 대거 비튼 뒤, 보상으로 지급되는 BUNNY 토큰이 왜곡된 가격 기준으로 계산되도록 만들었어. 결과적으로 BUNNY가 대량 발행됐고 시장에 쏟아지면서 토큰 가격이 폭락했지. 보상 발행 로직이 조작 가능한 가격에 묶여 있으면 무한 프린터가 될 수 있다는 걸 보여준 사례야.

8-4. Cream Finance: 볼트 지분 가격의 비극

2021년 10월 Cream Finance 사건은 앞서 말한 지분 가격 조작의 교과서야. Cream은 Yearn의 yUSD 볼트 지분을 담보로 받으면서 그 가치를 볼트의 pricePerShare로 계산했는데, 공격자는 볼트에 기초 자산을 대량으로 보내(기부) pricePerShare를 단번에 두 배 수준으로 끌어올렸어. 담보 가치가 뻥튀기되자 Cream의 다른 자산들을 대규모로 빌려 나간 거지. 피해액은 약 1억 3천만 달러로 알려졌어.

8-5. Beanstalk & Euler: 진화한 공격

앞에서 자세히 본 두 사건은 "가격 조작"을 넘어서 거버넌스와 함수 조합 로직을 노렸다는 점에서 공격이 한 단계 진화했음을 보여줘. 공격자들은 이제 단순 가격 비틀기를 넘어, 프로토콜의 의사결정 체계와 회계 불변 조건 전체를 분석하고 있어.

🧠 참고: 플래시 론 없이도 일어난 조작
2022년 10월 Solana 기반 Mango Markets 사건은 플래시 론이 아니라 공격자가 직접 보유한 자금으로 MNGO 선물 가격을 끌어올려 담보 가치를 부풀린 사례야. 수단은 달라도 본질은 같아. 얕은 유동성 + 조작 가능한 가격 = 위험. 플래시 론은 이 공식에 "누구나"라는 단어를 더해줄 뿐이지.


9. 공격 한 번을 해부해보자 🔬 (트랜잭션 레벨)

보안 분석가들은 사건이 터지면 Etherscan이나 Phalcon, Tenderly 같은 트랜잭션 분석 도구로 호출 흐름(call trace)을 뜯어봐. 일반적인 오라클 조작 공격 트랜잭션은 이런 계층 구조를 가져.

📜 가상의 공격 트랜잭션 호출 흐름
AttackContract.attack()
 └ LendingPool.flashLoan(USDC, 50,000,000)
   └ AttackContract.executeOperation()
     ├ DEX.swap(USDC → TOKEN) ← 풀 가격 급등
     ├ VictimLending.deposit(TOKEN)
     ├ VictimLending.borrow(ETH, 과다) ← 조작된 가격으로 계산
     ├ DEX.swap(TOKEN → USDC) ← 가격 원복
     ├ DEX.swap(ETH 일부 → USDC)
     └ USDC.approve(LendingPool, 원금+수수료)
 └ 잔여 ETH → 공격자 지갑

여기서 분석가들이 보는 체크포인트는 세 가지야.

① 자금 출처
어떤 플래시 론 제공처에서 얼마를 빌렸나? 여러 곳에서 동시에 빌린 경우도 많아.
② 상태가 비틀린 지점
어느 호출에서 가격·잔고·지분이 비정상으로 변했나? 이게 근본 원인을 가리켜.
③ 가치 유출 지점
피해 프로토콜에서 실제로 돈이 빠져나간 함수는 무엇인가? 패치 대상이 여기서 결정돼.

9-1. 공격 직후에 벌어지는 일들

공격 트랜잭션이 블록에 들어가면 보통 이런 일이 연쇄적으로 일어나.

1
온체인 모니터링 알림 — 보안 업체·봇들이 비정상 자금 흐름을 감지하고 SNS에 경보를 올려.
2
프로토콜 일시 정지 — pause 기능이 있다면 남은 자금 보호를 위해 컨트랙트를 멈춰.
3
자금 추적 — 공격자 주소를 블랙리스트화하고, 스테이블코인 발행사가 해당 주소의 토큰을 동결하기도 해(USDC·USDT는 동결 기능이 있어).
4
협상 메시지 — 온체인 메시지로 "일부를 바운티로 줄 테니 나머지를 돌려 달라"고 제안하는 경우가 흔해.
5
사후 분석 보고서(Post-mortem) 공개 — 원인, 피해 규모, 보상 계획을 공개해.

9-2. 화이트햇과 MEV 봇의 끼어들기

재미있는 현상도 있어. 블록에 들어가기 전 트랜잭션은 공개 대기열(mempool)에 보이기 때문에, MEV 봇이 수익성 있는 트랜잭션을 복사해서 더 높은 수수료로 먼저 실행해버리는 일이 있어(프런트러닝). 그래서 공격자들은 Flashbots 같은 비공개 경로로 트랜잭션을 보내기도 하고, 반대로 화이트햇 해커들이 공격을 감지해 같은 기법으로 먼저 자금을 "구출"해서 돌려준 사례도 있지. 블록체인 보안이 그야말로 초 단위의 체스 게임이 된 거야 ♟️


10. 방어 전략 🛡️: 프로토콜은 어떻게 지켜야 할까

10-1. 오라클을 단단하게

방식장점한계·주의점
탈중앙 오라클 네트워크
(예: Chainlink)
여러 거래소·데이터 제공자의 가격을 집계, 한 풀을 비틀어선 거의 안 움직임업데이트 간격·편차 임계값이 있어 급변장에선 지연 가능, 마지막 갱신 시각(stale) 검사 필수
TWAP
(시간가중평균가격)
일정 기간 평균이라 한 블록 조작으로는 크게 못 바꿈기간이 짧거나 풀이 얕으면 여러 블록 조작으로 뚫릴 수 있음, 급변 시 반응 느림
복수 오라클 교차 검증둘 이상의 출처가 크게 어긋나면 거래 중단설계 복잡도 증가, 둘 다 실패하는 시나리오 대비 필요
가격 변동 상한(서킷 브레이커)짧은 시간에 비정상 급등락 시 자동 차단정상적인 급변장에서도 서비스가 멈출 수 있음

Uniswap V2와 V3는 각각 누적 가격(cumulative price) 값을 기록해두어 TWAP를 계산할 수 있게 해줘. V3는 observe 함수로 과거 시점들의 누적 틱(tick)값을 조회할 수 있지. 핵심은 "현재 블록의 현물 잔고로 가격을 계산하지 않는다"는 원칙이야.

Chainlink를 쓸 때 흔히 저지르는 실수도 짚고 갈게.

(, int256 answer, , uint256 updatedAt, ) = priceFeed.latestRoundData();
require(answer > 0, "invalid price");
require(block.timestamp - updatedAt < MAX_DELAY, "stale price");
// L2라면 시퀀서 가동 여부(Sequencer Uptime Feed)도 함께 확인

가격이 0 이하인지, 너무 오래된 값은 아닌지 확인하지 않으면 오라클이 멈췄을 때 엉뚱한 가격으로 대출이 실행될 수 있어.

10-2. 거버넌스에 시간을 넣어라

📸 과거 블록 스냅샷
투표권을 제안 생성 시점 이전 블록 기준으로 계산하면, 투표 당일 빌린 토큰은 무용지물이야.
⏳ 타임락
통과 후 실행까지 수일의 대기 기간을 두면 악성 안건을 발견하고 대응할 수 있어.
🧑‍⚖️ 가디언·거부권
명백한 악성 안건을 막는 보안 위원회를 두되, 권한 남용을 막을 장치도 함께 설계해야 해.

10-3. 코드 레벨 방어

✅ Checks-Effects-Interactions 패턴 — 검증 → 상태 변경 → 외부 호출 순서를 지켜 재진입 여지를 없애.
✅ ReentrancyGuard — OpenZeppelin의 nonReentrant 같은 잠금 장치를 상태 변경 함수에 적용해.
✅ 모든 상태 변경 후 불변 조건 재검사 — 담보 비율, 총 공급량, 지분 가치 등 "절대 깨지면 안 되는 조건"을 함수 끝에서 확인해. Euler 사건이 바로 이걸 놓쳤지.
✅ 내부 회계 사용 — balanceOf(address(this))로 잔고를 직접 읽는 대신 내부 변수로 자산을 추적하면 기부 공격을 막기 쉬워.
✅ 가상 지분·초기 지분 소각 — ERC-4626 볼트의 첫 예치자 공격을 막기 위해 가상 자산/지분 오프셋이나 최초 지분 일부 소각을 써.
✅ 반올림 방향 통일 — 항상 프로토콜에 유리한 방향(지분 발행 시 내림, 상환 요구 시 올림)으로 계산해.

10-4. "같은 블록 금지"는 해답일까?

"예치와 인출을 같은 블록에서 못 하게 하면 되잖아?"라는 아이디어도 있어. 실제로 일부 프로토콜은 이런 제한이나 tx.origin == msg.sender 검사(컨트랙트 호출 차단)를 썼어. 하지만 이건 부분적 처방이야.

⚠️ 왜 완벽하지 않을까?
· 다중 블록 조작이 가능한 공격자(검증자 결탁, 자기 자본 보유자)에겐 소용없어.
· 컨트랙트 지갑(스마트 계정) 사용자나 정상적인 다른 프로토콜과의 조합성을 해쳐.
· 계정 추상화 등 지갑 구조 변화로 tx.origin 검사의 의미가 약해지고 있어.
결국 근본 원인(조작 가능한 가격, 깨진 불변 조건)을 고치는 게 정답이야.

10-5. 검증과 모니터링의 겹겹 방어

1
복수 감사(Audit) — 서로 다른 보안 업체 여러 곳의 감사를 받아. 단, 감사는 "버그가 없다는 보증"이 아니라 "찾을 수 있었던 버그를 찾았다는 기록"이야.
2
퍼징·불변 조건 테스트 — Foundry의 invariant 테스트, Echidna 같은 도구로 무작위 호출 조합을 수백만 번 돌려 불변 조건이 깨지는지 찾아.
3
포크 환경 공격 시뮬레이션 — 메인넷 상태를 포크해서 실제 플래시 론 유동성으로 공격 시나리오를 재현해 봐.
4
정형 검증(Formal Verification) — 핵심 수학 로직을 수학적으로 증명해. 비용이 크지만 대형 프로토콜에선 점점 표준이 되고 있어.
5
버그 바운티 — Immunefi 같은 플랫폼에서 화이트햇에게 큰 포상금을 걸어. 해커에게 "훔치는 것보다 신고하는 게 이득"인 구조를 만드는 거지.
6
실시간 모니터링·자동 정지 — 비정상 자금 흐름 탐지 시 자동으로 일시 정지하는 시스템을 갖춰.

스마트 컨트랙트 감사나 보안 리뷰는 고도의 전문성이 필요한 분야라, 프로젝트 초기 팀이라면 재능넷 같은 재능 공유 플랫폼에서 블록체인 개발·보안 전문가의 도움을 받아 코드 리뷰나 테스트 환경 구축을 맡기는 것도 현실적인 방법이야. 물론 메인넷 대규모 자금이 걸린 프로토콜이라면 공인된 감사 기관의 정식 감사를 함께 받아야 하고.


11. 그럼 우리 같은 사용자는? 🙋 DeFi 이용자 체크리스트

코드를 직접 짜지 않는 일반 사용자도 위험을 줄일 수 있어. 투자 조언이 아니라 리스크를 판단하는 관점으로 봐줘.

🔍 감사 보고서 확인
어떤 업체가 언제 감사했는지, 지적 사항이 해결됐는지 공개돼 있나? 감사 후 코드가 바뀌진 않았나?
📡 오라클 출처 확인
문서에 가격 출처가 명시돼 있나? 특정 DEX 한 곳의 현물 가격만 쓰는 구조라면 경계해.
⏳ 운영 기간(Lindy)
오래, 큰 자금을 안전하게 지켜온 프로토콜일수록 검증 시간이 길었다는 뜻이야. 다만 오래됐다고 절대 안전한 건 아니야.
🗳️ 거버넌스 구조
타임락이 있나? 관리자 키는 멀티시그인가? 한 사람이 자금을 옮길 수 있는 구조는 아닌가?
💧 담보 자산 유동성
유동성이 얕은 신생 토큰을 담보로 받는 대출 시장은 조작 공격에 취약해.
🧺 분산
한 프로토콜에 자산을 몰지 말고, 감당 가능한 범위에서만 이용해. 수익률이 비정상적으로 높다면 이유를 먼저 의심해.

🧭 "고수익 = 고위험"의 DeFi 버전
신생 프로토콜이 수백~수천 %의 연이율을 내건다면, 그 수익은 보통 토큰 인센티브에서 나와. 이런 곳일수록 코드 검증이 덜 됐을 가능성이 크고, 토큰 가격이 조작 가능한 오라클과 엮여 있으면 플래시 론 공격 한 번에 토큰 가치와 예치 자산이 함께 증발할 수 있어.


12. 흔한 오해 바로잡기 🙅

❓ 오해 1. "플래시 론을 금지하면 해킹이 사라진다"

아니야. 플래시 론은 공격 자금을 조달하는 수단일 뿐이야. 고래나 자금력 있는 공격자는 자기 돈으로도 같은 공격을 할 수 있어(Mango Markets 사례처럼). 게다가 플래시 론은 누구나 배포할 수 있는 코드라서 특정 프로토콜이 기능을 끈다고 생태계에서 사라지지도 않아. 플래시 론을 막는 대신 취약한 설계를 고치는 게 정답이야.

❓ 오해 2. "플래시 론 공격은 블록체인 자체의 결함이다"

이더리움 같은 기반 체인은 정해진 규칙대로 정확히 실행했을 뿐이야. 문제는 그 위에 올라간 애플리케이션의 설계 결함이지. 그래서 이런 사건들은 "합법적인 코드 실행이냐, 범죄냐"라는 법적 논쟁을 낳기도 했어. 다만 여러 나라 수사 당국은 시장 조작이나 사기 혐의로 수사·기소한 사례들이 있어서 "코드가 허용하면 합법"이라는 주장이 통한다고 보긴 어려워.

❓ 오해 3. "감사받은 프로토콜은 안전하다"

위 사건 목록의 상당수가 감사를 받은 프로토콜이었어. 감사는 위험을 줄여주지만 0으로 만들지는 못해. 특히 다른 프로토콜과의 조합 위험은 감사 범위 밖에 있는 경우가 많아.

❓ 오해 4. "스테이블코인 풀은 가격 조작이 안 된다"

Harvest Finance 사례에서 봤듯, 비율이 1:1에 가깝도록 설계된 풀도 충분히 큰 자본이면 흔들려. 금액이 크면 0.5%의 왜곡도 수백만 달러가 돼.

❓ 오해 5. "TWAP만 쓰면 끝"

TWAP는 한 블록 조작엔 강하지만, 기간이 짧거나 유동성이 얕으면 여러 블록에 걸쳐 가격을 유지하는 공격에 뚫릴 수 있어. 2022년 Inverse Finance 사건처럼 짧은 시간 창의 평균가가 조작된 사례도 있었어. 오라클 기간, 유동성 깊이, 외부 오라클과의 교차 검증을 함께 따져야 해.


13. 자주 묻는 질문 💬

Q. 플래시 론을 쓰려면 코딩을 꼭 할 줄 알아야 해?

원래는 직접 스마트 컨트랙트를 배포해야 해. 콜백 함수 안에 모든 로직을 넣어야 하니까. 다만 일부 서비스는 담보 교체·부채 정리 같은 기능을 플래시 론 기반으로 버튼 하나에 제공하기도 해. 사용자는 모르는 사이에 플래시 론을 쓰고 있는 셈이지.

Q. 플래시 론으로 빌린 돈을 다음 블록까지 들고 있을 순 없어?

불가능해. 그게 플래시 론의 정의야. 같은 트랜잭션 안에서 갚지 않으면 전부 되돌려지니까 "들고 튀는" 미래는 존재하지 않아. 그래서 공격자는 빌린 돈 자체가 아니라, 빌린 돈으로 다른 곳에서 만들어낸 차익을 가져가는 거야.

Q. 이더리움 말고 다른 체인에도 있어?

응. EVM 호환 체인(BNB 체인, Polygon, Arbitrum, Optimism, Avalanche 등)에는 Aave 같은 프로토콜이 배포돼 있어서 플래시 론이 흔해. 실제로 BNB 체인에서 2021년에 플래시 론 공격이 연달아 터지기도 했어. 원자적 트랜잭션을 지원하는 다른 계열 체인에도 비슷한 기능들이 존재해.

Q. 공격자는 잡혀?

블록체인은 모든 거래가 공개돼서 자금 흐름 추적은 가능해. 공격자가 믹서나 크로스체인 브리지로 세탁을 시도하지만, 거래소 입금 단계에서 신원이 드러나거나 실수로 추적되는 사례도 있어. 다만 모든 사건이 해결되는 건 아니고, 상당수는 협상을 통한 일부 반환으로 마무리돼.

Q. 플래시 론 수수료가 0.05%면, 공격 비용은 얼마나 들어?

예를 들어 Aave V3에서 1,000만 USDC를 0.05% 수수료로 빌리면 수수료는 5,000 USDC야. 여기에 스왑 수수료, 가격 충격(슬리피지)으로 인한 손실, 가스비가 더해지지. 수천만 달러 규모 공격에서 이 비용은 수익에 비해 매우 작아서, 비용으로 공격을 억제하기는 어려워.


14. 앞으로의 흐름 🔭

DeFi 보안은 계속 진화 중이야. 몇 가지 흐름을 정리해볼게.

🧮 불변 조건 중심 개발
"이 함수가 맞게 동작하나?"보다 "어떤 순서로 호출해도 이 조건은 절대 안 깨지나?"를 먼저 정의하고 개발하는 문화가 확산되고 있어.
🛰️ 실시간 방어 인프라
공격 트랜잭션이 mempool에 보이는 순간 감지해 프로토콜을 먼저 멈추는 자동화 시스템이 발전하고 있어.
🔗 오라클 고도화
여러 데이터 소스 집계, 저지연 피드, 이상치 필터링 등 오라클 설계가 점점 정교해지고 있어.
🧩 격리된 시장 구조
위험한 자산을 별도의 격리 시장에 두어 한 자산 사고가 전체로 번지지 않게 하는 설계가 늘고 있어.

그리고 하나 기억할 건, 플래시 론이 보안 연구의 도구이기도 하다는 점이야. 화이트햇들은 포크 환경에서 플래시 론으로 대규모 자본 시나리오를 재현해 취약점을 미리 찾아내. 공격자가 가진 무기를 방어자도 똑같이 쥐고 있는 셈이지 ⚔️🛡️


15. 마무리: 순간의 자본, 영원한 교훈 🌱

정리해볼게. 플래시 론은 원자성이라는 블록체인의 성질을 이용해 담보 없이 거대한 자본을 순간적으로 빌려주는 혁신적인 도구야. 차익거래, 청산, 담보 교체처럼 시장을 효율적으로 만드는 착한 역할을 하지만, 동시에 조작 가능한 오라클, 시차 없는 거버넌스, 깨진 회계 불변 조건을 가진 프로토콜에겐 치명적인 증폭기가 돼.

bZx에서 Euler까지 이어진 사건들이 말해주는 건 결국 하나야. "내 프로토콜은 세상 모든 사람이 무한한 자본을 한 블록 동안 가질 수 있다는 가정에서도 안전한가?" 이 질문에 "예"라고 답할 수 있어야 DeFi에서 살아남을 수 있어.

블록체인 개발에 관심 있는 친구라면 이 사건들의 사후 분석 보고서를 하나씩 읽어보는 걸 강추해. 어떤 교과서보다 생생한 보안 교재거든. 그리고 혼자 공부하다 막히면 재능넷에서 같은 관심사를 가진 전문가를 찾아보는 것도 좋은 방법이야. 오늘도 긴 글 따라와줘서 고마워, 안전한 DeFi 생활 하자! 🙌

#플래시론#DeFi보안#오라클조작#거버넌스공격#스마트컨트랙트#재진입공격

댓글 작성

이 글에 대한 여러분의 생각을 들려주세요

댓글 0
댓글을 불러오는 중입니다.

아직 댓글이 없습니다.