[취미로 해킹 #8] 함수 선택자 충돌? 개발자가 삐지면 다 죽는 이유
2025. 11. 06. 15:26
수정됨

교보재(함수 선택자 충돌).zip
2.5MB
개요: 해당 콘텐츠는 가상 시스템의 숨겨진 결함을 파고드는 일지 시뮬레이션입니다.
제목: 함수 선택자 충돌? 개발자가 삐지면 다 죽는 이유
분야: 스마트 컨트랙트(solidity)
소개
겉보기엔 완벽한 '구식 명품' 컨트랙트를 만난다. 시스템은 모든 부적절한 접근을 차갑게 거절하지만, 그 의도된 실패 방식이 어딘가 부자연스럽다. 그는 정문이 아닌, 시스템의 실패가 속삭이는 비밀 통로를 추적하기 시작한다.
범위
프록시 설계 방식 중 UUPS와 TPP의 차이.
성공 로직이 아닌, 'else'로 대표되는 시스템의 예외 처리 및 실패 로직의 중요성.
프록시와 구현체 간의 '함수 선택자 충돌'이 어떻게 시스템 탈취로 이어질 수 있는지에 대한 이론적 접근.
참고
해당 콘텐츠는 교보재로 활용되는 10,000원 상당의 전자책(PDF)을 제공합니다.
교보재 참고 자료 목록
No. 799: 탈중앙화라는 완벽한 환상과 그것을 깨뜨리는 관리자
No. 800: EVM의 DELEGATECALL은 누구의 시점으로 세상을 보는가
No. 801: 아무도 부르지 않은 함수, fallback이 응답하는 이유
No. 802: 우아한 포장지의 비밀, transfer는 왜 _transfer를 부를까?
No. 803: 가장 비싼 땅, 이더리움에서 28바이트를 아끼는 기술
No. 804: Code is Law의 배신, 그리고 프록시라는 구원
No. 805: 결정론이라는 신성한 감옥, EVM
아래 퀴즈의 정답을 알고 계신다면, 이번 콘텐츠는 건너뛰셔도 좋습니다.
스마트 컨트랙트 세계에는 '프록시(Proxy)'라는 특별한 설계가 있습니다. 프록시는 '영구적인 주소(로비)' 역할을 하고, 실제 로직이 담긴 '구현 컨트랙트(사무실)'를 뒤에 숨겨둡니다. 이렇게 하면 나중에 '사무실'만 새것으로 교체(업그레이드)할 수 있죠.
이 '로비(프록시)'에는 두 종류의 방문자가 있습니다.
관리자: '사무실'을 교체할 수 있는 특별한 열쇠를 가졌습니다.
일반 사용자: '사무실'의 기능(예: 토큰 전송)만 이용합니다.
이때 한 탐정이 '일반 사용자'의 계정으로 '관리자 전용 기능'(예: 사무실 교체)을 호출해 봤습니다.
당연히 트랜잭션은 실패(Reverted)했습니다. 관리자가 아니니 당연하죠. 하지만 이상한 점이 발견되었습니다. 이더리움 사용 내역(가스비)을 보니, 단순히 "당신은 관리자가 아닙니다"라며 문전박대당한 것치고는 가스(Gas)가 비정상적으로 많이 소모되었습니다.
단순한 거절은 가스비가 거의 들지 않아야 정상입니다. 이것은 '단순 실패'가 아니라 '복잡한 실패'였습니다.
분석 결과, 이 현상은 관리자인지 확인하는 이 코드의 else 블록, 즉 '관리자가 아닐 경우'의 처리 방식 때문이었습니다.
다음 코드의 ██████████에 들어갈, 이 비정상적인 가스 소모를 유발한 '위험한 한 줄'은 무엇일까요?
// 관리자인지 확인하는 수정자(modifier)
modifier ifAdmin() {
if (msg.sender == _admin()) {
// 1. 당신이 관리자라면...
_; // 요청한 기능을 실행하세요.
} else {
// 2. 당신이 관리자가 아니라면...
██████████
}
}1. _fallback();
2. revert("Caller is not the admin");
3. emit AdminCallFailed(msg.sender);
4. require(gasleft() > 50000, "Low gas");
이번에 새로 담당한 녀석, 첫인상은 꽤 깐깐해 보였다. 마치 최신 유행은 아니지만, 클래식한 수트로 쫙 빼입은 느낌이다. 코드베이스는 견고하고 널리 알려진 라이브러리를 기반으로 잘 짜여 있었지만, 결정적으로 컴파일러 버전이 pragma solidity 0.6.12였다. 2020년 스타일. 이건 빈티지도 아니고 그냥 구식이었다. 0.8.x 버전부터 기본으로 챙겨주는 산술 오버플로우 방어 같은 안전장치도 없던 시절. SafeMath 라이브러리를 악세서리처럼 주렁주렁 달아야만 했던 그 시대의 코드엔, 그 시대의 보안 철학이 그대로 남아있기 마련이다. ‘단단하지만 낡은 성벽’ 느낌. 성벽은 두껍지만, 설계 사상 자체가 현대의 공성 무기, 즉 새로운 공격 패턴들을 견디도록 설계되지 않았다는 위태로움이 느껴졌다.
요즘 프록시라면 UUPS가 맞다. UUPS(범용 업그레이드 가능 프록시 표준)는 프록시는 그저 ‘멍청한’ 껍데기로 남겨두고, 모든 스마트한 로직은 구현체에 맡기는 미니멀리즘이 트렌드니까. 하지만 이 녀석은 정반대였다. 프록시 자체가 관리자 로직을 품고 있는, 그 시절 유행하던 '투명 프록시 패턴(TPP)'이었다. 이런 하이브리드 디자인은 언제나 복잡하다. 관리자의 공간과 사용자의 공간이 명확히 분리되지 않으면, 반드시 문제가 생긴다. 경계가 모호하면 월담이 더 자주 발생하는 법이니까.
잠금 해제하고, 전체 내용을 확인하세요
결제 즉시 열람 · 평생 소장

교보재(함수 선택자 충돌).zip
2.5MB