스마트계약 보안 취약점 5가지와 실무 대응 방안

스마트계약의 주요 보안 취약점은 재진입 공격, 정수 오버플로/언더플로, 권한 제어 문제, 잔액 조건 무효화, 짧은 주소 공격 5가지입니다. 각각 다른 공격 메커니즘과 예방 방법이 있으므로 배포 전 반드시 검증해야 합니다.

🔥 이 글의 핵심  |  
스마트계약 보안 취약점 5가지와 실무 대응 방안

스마트계약 보안이 중요한 이유와 대표 취약점

스마트계약은 블록체인에 한 번 배포되면 수정이나 롤백이 거의 불가능해요. 그래서 취약점이 발견되면 자산 탈취, 무단 이체 등 금융 피해가 즉시 발생합니다.

스마트계약은 단순한 프로그래밍 오류도 자산 이동 규칙을 왜곡시켜 직접적인 손실로 이어져요. 따라서 개발 단계부터 배포, 운영 단계까지 이어지는 다층 검증 체계가 필수입니다.

현재 실무에서 발견되는 가장 흔한 취약점은 5가지예요:

  1. 재진입 공격(Reentrancy)
  2. 정수 오버플로/언더플로(Integer Overflow/Underflow)
  3. 메시지 호출과 권한 제어 문제
  4. 잔액 조건 무효화
  5. 짧은 주소 공격(Short Address Attack)

이 5가지는 서로 다른 공격 메커니즘을 가지고 있으며, 각각 다른 예방 방법이 필요해요.

재진입 공격: 반복 호출로 자금을 여러 번 탈취

재진입 공격(Reentrancy)은 스마트계약의 가장 치명적인 취약점이에요. 외부 계약으로 자금을 보낼 때 상태 변경이 뒤늦게 일어나, 공격자가 함수를 다시 호출해 자금을 여러 번 탈취할 수 있거든요.

공격 원리

정상 흐름:
1. 출금 함수 호출
2. 자금 송금
3. 잔액 기록 차감

공격 흐름:
1. 출금 함수 호출
2. 자금 송금 (⚠️ 송금 직후 공격 코드 실행 가능)
3. 공격자가 다시 출금 함수 호출
4. 잔액 차감 전에 또 다시 출금

이렇게 반복되면 실제 보유 금액보다 훨씬 많은 자금이 탈취돼요.

예방 방법

  • Checks-Effects-Interactions 패턴: 상태 변경을 먼저 하고 외부 호출은 나중에
  • 재진입 가드(Reentrancy Guard): 함수 실행 중 재호출 방지
  • mutex 또는 lock 메커니즘: 동시 실행 차단

정수 오버플로/언더플로: 계산 오류로 잔액 왜곡

정수 오버플로/언더플로는 변수의 저장 범위를 벗어났을 때 값이 회전하는 취약점이에요. 예를 들어 8비트 변수가 255를 넘으면 0으로 돌아가는 식이죠.

실제 피해 사례

  • 사용자 A의 잔액: 100 토큰
  • 100 토큰을 다른 사용자에게 전송하려고 함
  • 트랜잭션 과정에서 계산이 오버플로우
  • 결과: 잔액이 음수가 되어야 하는데, 최대값으로 점프 (예: 2^256 – 1)
  • 사용자 A는 갑자기 천문학적 잔액을 갖게 됨

예방 방법

  • SafeMath 라이브러리: 모든 연산에 검증 추가
  • 언더플로 방지 패턴: 음수 값 불가능하게 검증
  • 최신 Solidity 버전: 0.8.0 이상은 자동 overflow/underflow 체크

메시지 호출과 권한 제어 문제: 권한 우회로 무단 조작

메시지 호출과 권한 제어 문제는 함수 접근 제어가 제대로 되지 않아 권한 없는 사용자가 중요한 작업을 실행하는 취약점이에요.

공격 방식

  • 퍼블릭 함수 오용: 관리자만 호출해야 하는 함수가 누구나 호출 가능
  • Delegatecall 오용: 외부 컨트랙트에 자신의 저장소 접근 권한을 줘서 상태 변조
  • 권한 검증 부재: 함수 시작 시 호출자 확인이 없음

예방 방법

  • 접근제어자(onlyOwner, onlyAdmin) 사용: 함수 접근 제한
  • 권한 검증 강화: 함수 시작에 require 추가
  • Delegatecall 사용 제한: 신뢰할 수 있는 컨트랙트에만 사용
  • 코드 리뷰: 권한 흐름을 명시적으로 문서화

잔액 조건 무효화와 짧은 주소 공격

잔액 조건 무효화는 ‘잔액이 충분한지 확인’이라는 중요한 검증을 공격으로 무효화하는 취약점이에요. 예를 들어 조건 검증 전에 상태를 미리 변경해버리면 검증이 의미 없어지죠.

짧은 주소 공격(Short Address Attack)

짧은 주소 공격은 지갑 주소 입력 시 의도적으로 짧은 주소를 사용해 바이트 시프트를 유발하는 공격이에요.

예시:
– 정상 주소: 0x1234567890abcdef…(40자)
– 공격 주소: 0x1234567890abcd…(38자, 1바이트 부족)
– 결과: EVM이 자동으로 0을 패딩해서 금액이 256배 증가될 수 있음

예방 방법

잔액 조건:
– 조건 검증을 상태 변경 전에 수행
– 불변성 검증: 변경 전후 잔액 합계 확인

짧은 주소:
– 주소 길이 검증: require(input.length == 42)
– 표준 라이브러리 사용: 자동 검증
– 충돌 감지: 입력 주소의 표준화 확인

현재 오픈AI와 금융보안원 등이 AI 기반 취약점 탐지 시스템을 개발해 개발 단계에서 이런 문제들을 사전에 발견하려고 노력하고 있어요.

자주 묻는 질문

Q. 스마트계약을 배포하기 전에 반드시 감사를 받아야 하나요?

금융 관련 스마트계약이라면 필수예요. 최소한 자동화된 정적 분석 도구(예: Slither, MythX)로 검증하고, 가능하면 전문 감사 회사의 코드 리뷰를 받는 게 좋습니다. 이더리움의 대규모 프로토콜들은 거의 모두 제3자 감사를 거칩니다.

Q. 재진입 가드를 사용하면 재진입 공격이 100% 방지되나요?

가드가 있으면 대부분의 재진입 공격이 차단되지만, 크로스-함수 재진입(한 함수에서 다른 함수로 재진입)이 가능할 수 있어요. Checks-Effects-Interactions 패턴과 함께 사용하면 훨씬 안전합니다.

Q. SafeMath 없이도 Solidity 0.8.0 이상은 안전한가요?

네, Solidity 0.8.0부터는 오버플로우/언더플로우가 자동으로 차단돼요. 하지만 unchecked 블록을 사용하는 경우가 있으므로, 가스 최적화를 위해 unchecked를 쓸 때는 수동 검증이 필요합니다.

Q. 이미 배포된 취약한 스마트계약은 어떻게 하나요?

롤백이 불가능하므로, 프록시 패턴(업그레이드 가능한 컨트랙트)을 미리 설계해야 해요. 없다면 새 계약을 배포하고 기존 자산을 마이그레이션하거나, 긴급 pause 함수로 임시 동결할 수밖에 없습니다.

Q. 스마트계약 보안을 공부하려면 어디서 시작하면 좋을까요?

OpenZeppelin의 공식 문서와 Ethernaut 워게임을 추천해요. Ethernaut은 각 취약점을 실제로 공격하고 방어하는 방법을 배울 수 있는 최고의 학습 자료입니다.