
Cobo DeFi 보안 강의(하): DeFi에서 흔히 발생하는 보안 취약점 및 예방
저자: 맥스 코보(Max Cobo), 보안 책임자
이 글은 Cobo Global의 24번째 기사입니다.
Moledao의 초청을 받아 최근 Cobo의 보안 책임자 맥스가 온라인으로 커뮤니티 구성원들을 대상으로 DeFi 보안 수업을 진행했습니다. 맥스는 지난 1년 이상 동안 Web3 산업에서 발생한 주요 보안 사건들을 되돌아보고, 이러한 사건들이 왜 발생했는지와 이를 어떻게 방지할 수 있는지를 집중적으로 논의하였으며, 일반적인 스마트 계약의 보안 취약점과 예방 조치를 정리하고, 프로젝트 팀과 일반 사용자에게 보안 관련 제언을 제공했습니다. 이에 따라 맥스의 강연 내용을 두 편으로 나누어 발표하며, DeFi 애호가들이 참고하여 저장할 수 있도록 합니다.
상편: 《Cobo DeFi 보안 수업(상): 2022년 DeFi 보안 대형 사건 리뷰》
일반적인 DeFi 취약점 유형에는 플래시론, 가격 조작, 함수 권한 문제, 임의 외부 호출, fallback 함수 문제, 비즈니스 로직 결함, 개인키 유출, 재진입 공격 등이 있습니다.

2022년 11-12월 보안 사건 통계
여기서는 플래시론, 가격 조작, 재진입 공격 세 가지 유형을 중심으로 설명하겠습니다.
플래시론
-
일반적인 공격은 종종 플래시론과 함께 이루어지며, 공격자는 플래시론을 통해 거액의 자금을 빌려 가격 조작이나 비즈니스 로직 공격 등을 수행하는 것을 좋아합니다.
-
개발자는 계약 기능이 거액의 자금으로 인해 기능 오류를 일으키거나, 한 번의 트랜잭션 내에서 여러 함수와 상호작용하여 보상을 획득하는 시나리오가 발생하지 않는지 고려해야 합니다.
-
계약 내에서 일부 토큰 수량 값이 보상 계산에 사용되거나 DEX 거래쌍의 토큰 수량이 다양한 계산에 활용되는 경우를 자주 볼 수 있는데, 개발자가 이러한 기능 설계 시 공격자가 플래시론을 이용해 변수를 조작할 수 있다는 점을 고려하지 않으면 계약 자금이 도난당할 수 있습니다.
플래시론 자체는 DeFi의 혁신 중 하나이지만, 해커들이 악용할 경우 소액의 가스비만 지불하면 아무 비용 없이 자금을 빌릴 수 있으며, 전체 차익거래 과정을 수행한 후 자금을 반납하고 그 외의 이익을 가져갈 수 있습니다.
지난 2년간 플래시론을 이용한 문제가 많이 발생했습니다. 많은 DeFi 프로젝트는 수익률이 매우 높아 보이지만, 실제로는 프로젝트팀의 수준이 천차만별입니다. 코드가 구매된 것이거나, 코드 자체에는 취약점이 없더라도 로직상 문제가 있을 수 있습니다. 예를 들어 특정 시간에 보유자의 토큰 보유량에 따라 보상을 지급하는 프로젝트가 있었는데, 공격자가 플래시론으로 대량의 토큰을 매수한 후 보상 지급 시 대부분의 보상을 탈취한 사례가 있습니다. 또한 토큰을 기반으로 가격을 산정하는 일부 프로젝트는 플래시론을 통해 가격을 조작할 수 있으므로, 프로젝트팀은 이러한 문제에 경계해야 합니다.
가격 조작
가격 조작 문제는 플래시론과 밀접한 관련이 있으며, 주로 가격 계산 시 일부 파라미터가 사용자에 의해 조작될 수 있기 때문에 발생합니다. 자주 나타나는 유형은 두 가지입니다.
-
하나는 제3자 데이터를 가격 계산에 사용하나, 부적절한 사용 방법이나 검증 누락으로 인해 악의적으로 가격이 조작되는 것입니다.
-
다른 하나는 특정 주소의 토큰 수량을 계산 변수로 사용하나, 해당 주소의 토큰 잔고가 일시적으로 증가하거나 감소될 수 있다는 점입니다.
재진입 공격
외부 계약을 호출할 때의 주요 위험 중 하나는 외부 계약이 제어 흐름을 장악하고, 호출 함수의 의도와는 다르게 데이터를 변경할 수 있다는 점입니다.
```
mapping (address => uint) private userBalances; function withdrawBalance() public {
uint amountToWithdraw = userBalances[msg.sender];
(bool success, ) = msg.sender.call.value(amountToWithdraw)(""); // 만약 msg.sender가 계약이라면, fallback 코드가 실행되며 withdrawBalance를 다시 호출하여 재진입 공격이 가능
require(success);
userBalances[msg.sender] = 0;
}
```
사용자의 잔고가 함수의 마지막 단계에서야 0으로 설정되기 때문에, 두 번째(그 이후) 호출도 성공하게 되며 잔고를 반복적으로 인출할 수 있습니다.
다양한 계약에 따라 재진입 방식은 다양하며, 단일 계약 내 여러 함수 또는 서로 다른 계약의 함수를 조합해 재진입 공격을 수행할 수 있으므로, 재진입 문제 해결 시 다음 사항을 유의해야 합니다:
1. 단일 함수의 재진입 방지뿐 아니라 전반적인 재진입 방지를 고려해야 합니다.
2. Checks-Effects-Interactions 패턴을 따르는 코딩 방식을 준수해야 합니다.
3. 검증된 재진입 방지 modifier를 사용해야 합니다.
가장 우려되는 것은 무작정 '바퀴를 다시 발명'하는 것입니다. 이미 검증된 최고의 보안 실천 방안을 활용하면 되는데 굳이 모든 것을 새로 만들 필요는 없습니다. 자신이 새로 만든 '바퀴'는 충분히 검증되지 않았기 때문에 문제가 발생할 확률이 이미 오랫동안 검증된 솔루션보다 훨씬 높습니다.
Omni Protocol은 재진입 문제로 인해 해킹을 당했는데, 여기에는 또 다른 이야기가 있습니다.
Omni Protocol 취약점 뒤의 이야기 — 네 명의 해커들의 대결
이더리움의 mempool은 수많은 해커들에 의해 끊임없이 모니터링되고 있으며, 이들은 거래를 분석해 수익성이 있는 거래를 선제적으로 실행함으로써 이익을 얻습니다. Omni Protocol 취약점을 발견한 공격자가 제출한 거래는 두 명의 해커에게 포착되었고, 이들은 flashbot을 통해 선제 거래를 제출하여 Omni Protocol 프로토콜로부터 1,200 ETH를 탈취했습니다. 반면 취약점을 발견한 공격자는 단지 480 ETH만을 얻었습니다. 이 과정에서 또 다른 해커가 flashbot에 제출된 공격 거래를 감지하고, 공격 거래가 Doodle ERC20 토큰을 구매해야 한다는 점을 이용해 샌드위치 공격을 수행해 151 ETH를 획득하기도 했습니다.
취약점을 발견한 사람이 가장 큰 이득을 본 것은 아닙니다. 오히려 다크 포레스트 속의 다른 사냥꾼들이 더 많은 이익을 얻습니다. 이 생태계에서는 사냥꾼들로 가득 차 있으며, 사냥꾼들끼리 서로의 먹잇감이 될 수 있습니다. 심지어 공격의 시작자라도 신인이면 대부분의 자금을 가져가기 어렵고, 한 번에 모두 가져가지 못하면 다른 사람들이 더 높은 가스비로 먼저 거래를 실행하여 선점합니다. DEX에서 토큰 거래가 포함된다면 샌드위치 공격에 노출되어 매우 혼란스러운 상황이 벌어질 수 있습니다.
보안 제언
마지막으로 프로젝트팀과 일반 참여자들에게 드리는 보안 제언입니다.
프로젝트팀 보안 팁
첫째, 계약 개발 시 최고의 보안 실천 방침을 준수하세요.
둘째, 계약의 업그레이드 및 일시 중단 기능을 마련하세요. 많은 공격은 자금을 한 번에 모두 옮기는 것이 아니라 여러 번의 거래로 나누어 수행됩니다. 비교적 체계적인 모니터링 메커니즘이 있다면 이러한 공격을 감지할 수 있고, 계약이 일시 중단 가능한 상태라면 피해를 효과적으로 줄일 수 있습니다.
셋째, 타임락(time lock)을 도입하세요. Ankr의 사례처럼 타임락이 있었다면, 예를 들어 48시간 내에만 작업이 완료되도록 하는 경우, 타임락 기간 동안 많은 사람들이 프로젝트 창시자가 누구나 사용 가능한 새로운 mint 메서드를 업데이트했다는 사실을 발견할 수 있었고, 모니터링 담당자는 프로젝트가 해킹당했음을 인지하고 프로젝트팀에 알릴 수 있었습니다. 알림을 받았음에도 아무도 대응하지 않더라도, 최소한 자신의 자금은 먼저 인출하여 손실을 방지할 수 있었을 것입니다. 따라서 타임락이 없는 프로젝트는 이론적으로 문제가 발생할 가능성을 높이는 것입니다.
넷째, 보안 투자를 늘리고 체계적인 보안 시스템을 구축하세요. 보안은 점도 아니고 선도 아닌, 체계로 이루어져야 합니다. 프로젝트팀 입장에서 다수의 회사로부터 계약 감사를 받았다고 문제가 없다고 생각해서는 안 됩니다. 북한 해커가 개인키를 탈취하거나, 멀티시그의 모든 개인키를 도난당하는 경우도 있고, 경제 모델이나 비즈니스 모델 자체에 문제가 있어 자금 손실이 발생할 수 있습니다. 돈이 유출되는 방식은 수천 가지이며, 중요한 것은 사전에 이러한 보안 위험을 얼마나 피할 수 있는지입니다. 리스크 모델링을 수행하고, 대부분의 위험을 점진적으로 제거하며, 나머지 위험은 수용 가능한 수준 내에서 관리해야 합니다. 보안과 효율성은 동시에 얻을 수 없으므로 어느 정도의 선택과 집중이 필요합니다. 하지만 보안에 전혀 신경 쓰지 않고 투자하지 않으면 공격을 당하는 것은 당연한 결과입니다.
다섯째, 모든 직원의 보안 의식을 높이세요. 보안 의식을 높이기 위해 특별한 기술이 필요한 것은 아닙니다. 트위터에서 자주 볼 수 있듯이, 많은 사람들이 피싱으로 NFT를 잃어버립니다. 피싱은 인간의 약점을 이용하는 것이며, 조금만 주의를 기울이면 피해를 피할 수 있습니다. Web3 환경에서는 단순히 '왜 그런가?'라는 질문을 조금 더 하고, 조금 더 생각하는 것만으로도 많은 문제를 회피할 수 있습니다.
여섯째, 내부 악용을 방지하고 효율성 유지하면서 리스크 관리를 강화하세요. 다시 Ankr 사례를 들어보겠습니다. 첫째, 계약의 Owner가 멀티시그가 아닌 싱글시그였고, 개인키 유실로 인해 전체 프로젝트가 통제당했습니다. 둘째, 타임락이 없어 중요한 운영 업데이트가 즉시 반영되었고, 아무도 이를 몰랐기 때문에 프로토콜 참여자들에게 매우 불공평했습니다. 셋째, 내부 보안 메커니즘이 전혀 작동하지 않았습니다.
체인 상의 프로토콜은 효율성을 유지하면서 보안을 어떻게 향상시킬 수 있을까요? 광고 하나 하겠습니다. Cobo Safe를 추천합니다. 프로젝트가 멀티시그를 사용한다면, 운영 시 효율성에 약간의 영향을 줄 수 있지만, Cobo Safe를 통해 특정 인물이 특정 작업을 수행하도록 지정할 수 있습니다. 예를 들어 3/5 멀티시그에서 신뢰할 수 있는 노드에게 보안 리스크 모니터링 권한을 부여하고, 프로토콜이 공격받고 자금이 해커 주소로 이체되고 있음을 감지했을 때, 계약에 일시 중단 기능이 있다면 이를 실행할 수 있도록 권한을 부여할 수 있습니다.
또한 DEX 마켓메이커의 경우, Owner 권한을 제한하지 않으면 Owner가 자금을 다른 주소로 이체할 수 있는데, Cobo Safe를 통해 이체 가능한 주소와 조작 가능한 토큰 페어를 제한하고, 자금 인출 주소를 특정 주소로만 설정할 수 있습니다. Cobo Safe는 효율성을 높이면서도 일정 수준의 보안을 보장합니다.
일곱째, 제3자 요소 도입 시 보안성을 확보하세요. 생태계의 일원으로서 각 프로젝트는 자신의 상류 및 하류가 있습니다. 보안 측면에서는 "상류 및 하류는 기본적으로 안전하지 않다"는 원칙을 가져야 합니다. 상류든 하류든 간에 반드시 검증을 수행해야 합니다. 제3자 요소는 우리가 통제하기 어렵기 때문에 보안 리스크가 특히 큽니다. 따라서 제3자 요소 도입에 매우 주의해야 합니다. 계약이 오픈소스라면 이를 도입하거나 호출할 수 있지만, 비공개 소스라면 절대 참조해서는 안 됩니다. 우리는 그 내부 로직을 알 수 없으며, 도입한 계약 자체가 업그레이드 가능한 계약일 수도 있습니다. 정상적으로 사용할 때는 문제가 없을 수 있지만, 어느 날 갑자기 악의적인 계약으로 업그레이드될 가능성은 통제할 수 없습니다.
사용자/LP가 스마트 계약의 보안 여부를 판단하는 방법
일반 사용자는 프로젝트의 보안 여부를 다음 6가지 기준으로 판단할 수 있습니다.
첫째, 계약이 오픈소스인지 확인하세요. 계약 소스가 공개되지 않은 프로젝트는 절대 접근하지 마세요. 우리는 그 계약이 무엇을 하는지 알 수 없습니다.
둘째, Owner가 멀티시그를 사용하는지, 멀티시그가 탈중앙화되어 있는지 확인하세요. 멀티시그를 사용하지 않으면 프로젝트의 비즈니스 로직과 내용을 판단할 수 없으며, 보안 사건 발생 시 해킹인지 여부도 판단할 수 없습니다. 멀티시그를 사용하더라도 그 구성이 탈중앙화되어 있는지 확인해야 합니다.
셋째, 계약의 기존 거래 내역을 확인하세요. 특히 시장에는 유사한 계약을 만들어 낚시 사기를 시도하는 프로젝트가 많습니다. 이때 계약 배포 시간, 상호작용 횟수 등을 확인하는 것은 계약의 안전성을 판단하는 기준이 됩니다.
넷째, 계약이 프록시 계약인지, 업그레이드 가능 여부, 타임락 존재 여부를 확인하세요. 계약이 완전히 업그레이드 불가능하다면 너무 경직됩니다. 계약이 업그레이드 가능하도록 하는 것이 좋습니다. 그러나 업그레이드 시에는 업그레이드 내용이나 중요 파라미터 변경 시 타임락을 두어 사용자에게 충분한 검토 기회를 주는 것이 바람직하며, 이는 투명성을 확보하는 방법이기도 합니다.
다섯째, 다수 기관의 감사를 받았는지 확인하세요(감사 회사에 맹목적으로 신뢰하지 마세요). 또한 Owner 권한이 과도하게 크지 않은지 확인하세요. 우선 한 곳의 감사 회사만 믿어서는 안 됩니다. 다양한 감사 회사와 감사 인원은 문제를 바라보는 관점이 다릅니다. 프로젝트가 여러 기관의 감사를 받고, 발견된 다양한 문제를 모두 수정했다면, 단일 감사보다 훨씬 안전합니다. 책임감 있는 프로젝트팀은 다수의 감사 기관을 통해 교차 감사를 시행합니다.
또한 Owner 권한이 과도하게 크지 않은지도 확인해야 합니다. 예를 들어 일부 폐쇄형 프로젝트(Pi Xiong pan)는 Owner가 사용자 자금을 완전히 통제할 수 있으며, 소량의 토큰을 구매할 때는 정상적으로 거래되지만, 대량 구매 시 Owner가 즉시 거래를 잠글 수 있습니다. NFT 프로젝트도 마찬가지입니다. 정상적인 프로젝트의 Owner 권한은 제한적이어야 하며, 위험한 작업을 수행하지 않고, 중요한 작업은 타임락을 통해 사용자에게 알려야 합니다. 특히 시장이 좋지 않을 때 각종 도망치는 프로젝트가 많기 때문에, 사용자는 Owner 권한에 반드시 주의해야 합니다.
여섯째, 오라클(Oracle)을 주의 깊게 살펴보세요. 프로젝트가 시장에서 입지 있는 주요 오라클을 사용한다면 큰 문제는 없겠지만, 자체 개발 오라클이나 아무 토큰을 담보로 가격을 입력할 수 있는 오라클을 사용한다면 주의가 필요합니다. 오라클에 문제가 있거나 조작 가능성이 있다고 판단되면, 프로젝트 수익률이 아무리 높더라도 참여해서는 안 됩니다.
TechFlow 공식 커뮤니티에 오신 것을 환영합니다
Telegram 구독 그룹:https://t.me/TechFlowDaily
트위터 공식 계정:https://x.com/TechFlowPost
트위터 영어 계정:https://x.com/BlockFlow_News














