스마트 계약은 자동화된 블록체인 계약으로 탈중앙화와 투명성을 제공하지만, 코드에 존재하는 취약점으로 인해 수백억 원대의 해킹 피해가 발생하기도 했습니다. 본 글에서는 스마트 계약에서 자주 발생하는 보안 취약점들과 실제 해킹 사례를 중심으로 스마트 계약의 리스크를 분석합니다.
1. 재진입(Reentrancy) 취약점
가장 대표적인 보안 문제로, 외부 호출을 하는 함수에서 상태 변경 이전에 이더를 전송하면 공격자가 해당 계약을 반복 호출할 수 있습니다. 상태 업데이트가 뒤로 밀리면 잔액이 줄어들지 않은 상태로 자금이 반복 인출됩니다.
대표 사례: The DAO 해킹 (2016)
- 피해 규모: 약 6000만 달러
- 원인: 출금 함수에서 외부 호출 후 상태 업데이트
- 결과: 이더리움과 이더리움 클래식으로 체인 분리
function withdraw() public {
require(balances[msg.sender] > 0);
(bool sent, ) = msg.sender.call{value: balances[msg.sender]}("");
require(sent, "Failed to send Ether");
balances[msg.sender] = 0; // 취약한 위치
}
2. 정수 오버플로우/언더플로우
Solidity에서는 uint256과 같은 정수 타입이 최대값을 넘거나 최소값 아래로 내려가면 값이 순환(over/under flow)될 수 있습니다. 이는 공격자가 토큰 발행량이나 잔액을 조작할 수 있는 위험을 내포합니다.
대표 사례: BeautyChain 토큰 해킹 (2018)
- 문제: SafeMath 미사용으로 잔액이 0보다 작아져 오버플로우 발생
- 결과: 임의의 수량을 전송 가능
function transfer(address _to, uint256 _value) public {
balances[msg.sender] -= _value; // 언더플로우 가능
balances[_to] += _value;
}
3. delegatecall 오용
delegatecall은 외부 계약의 코드를 현재 컨텍스트에서 실행할 수 있도록 하는 기능이지만, 외부 코드를 신뢰할 수 없는 상태에서 사용할 경우 심각한 보안 문제가 발생할 수 있습니다.
대표 사례: Parity Wallet 해킹 (2017)
- 피해 규모: 약 15만 ETH
- 문제: 공유 라이브러리 계약의 selfdestruct 가능성 노출
- 결과: 모든 다중서명 지갑 동결
4. Timestamp 의존
block.timestamp는 조작이 가능한 블록 정보이기 때문에 조건문에 활용할 경우 예측 가능한 결과를 유도할 수 있습니다. 특히 랜덤값 생성에 사용되면 치명적인 문제를 유발합니다.
if (block.timestamp % 2 == 0) {
// 이긴 사용자에게 보상
}
5. 접근 제어 미흡
스마트 계약 함수에 대한 권한 제어가 부족하면 아무나 중요한 함수(예: 파라미터 변경, 이더 전송)를 호출할 수 있어 치명적인 피해가 발생할 수 있습니다.
대표 사례: Rubixi 수수료 변경 사고
- 문제: 초기 설정자 주소 변경 함수가 공개되어 있었음
- 공격자는 자신을 개발자로 등록한 후 수수료 전액 탈취
6. 무한 루프 및 Gas Limit 초과
for 또는 while 루프에서 반복 횟수가 불확정일 경우 gas limit을 초과하여 실행이 실패하거나, DDoS 공격 벡터로 악용될 수 있습니다.
스마트 계약 보안을 위한 대응 방안
- SafeMath: 정수 연산 보호를 위한 라이브러리 사용
- ReentrancyGuard: 재진입 보호를 위한 Modifier 적용
- OpenZeppelin: 검증된 라이브러리 활용
- Audit: 외부 보안 감사 필수
- Testnet 테스트: 배포 전 충분한 시뮬레이션
결론
재진입 공격: The DAO 해킹처럼 상태 업데이트 순서 오류로 자산 탈취 가능
정수 오버플로우: 수량 조작으로 토큰 시스템 붕괴 유발
delegatecall: 외부 코드 실행은 신중하게 사용해야 하며, 계약 전체 파괴 가능
timestamp: 예측 가능하므로 보안 판단 기준으로 부적절
접근 제어 문제: 관리자 함수는 반드시 onlyOwner 같은 제어 필요
스마트 계약은 코드에 의해 자산을 관리하기 때문에, 보안은 선택이 아닌 필수입니다. 배포 전 충분한 테스트와 감사 과정을 거쳐야 하며, 보안에 대한 지속적인 관심과 개선이 필요합니다.