7월 29일 Zepplin Solution 블로그에 게시된 글(https://blog.zeppelin.solutions/augur-rep-token-critical-vulnerability-disclosure-3d8bdffd79d2)을 우리말로 옮겼습니다.
요지는 Zepplin Solution에서 두달 간 이더리움의 스마트 컨트랙트 개발 언어인 Serpent에 감사를 수행하여 수두룩한 취약점을 발견하였고, 그 중 버퍼오버플로우와 타입 검사를 하지 않는 Serpent 두 가지 취약점을 이용하여 공격자가 Augur에서 모든 REP 토큰 전송을 비활성화 할 수 있는 취약점을 발견했다는 내용입니다. Augur 팀은 Solidity로 REP 토큰을 재작성하였고 기존 토큰의 잔고를 새 REP 토큰 잔고로 마이그레이션을 마쳤습니다. (https://medium.com/@AugurProject/serpent-compiler-vulnerability-rep-solidity-migration-5d91e4ae90dd)
비탈린 부테린은 2017년 7월 15일 자신의 트위터에서 Serpent가 outdated라고 선언한 바 있습니다. (~~~ embed:886400133667201024) twitter metadata:Vml0YWxpa0J1dGVyaW58fGh0dHBzOi8vdHdpdHRlci5jb20vVml0YWxpa0J1dGVyaW4vc3RhdHVzLzg4NjQwMDEzMzY2NzIwMTAyNCl8 ~~~
-이하 Zepplin Solution 블로그 전문 번역-
이주전, Serpent 컴파일러의 감사를 마치고 그 결과를 Augur 팀에 비공개로 보냈습니다. 8가지 치명적이게 심각한 취약점을 발견하여 Serpent가 매우 저품질인 것을 알아냈습니다.
며칠 후, 치명적인취약점이 REP 토큰 생성에 영향도 주는 것을 알게됩니다. 간단히 말해서, 토큰의 reputation 배열을 초과하는 쓰기 작업[역주: 버퍼 오버플로우 취약점]이 공격자가 creation 타임스탬프를 수정할 수 있게 합니다. 이는 컨트랙트가 크라우드 세일이 여전히 진행되고 있다고 착각하게 만들고 모든 토큰 전송을 비활성화 할 수 있게합니다. 이러한 심각한 취약점이 악용하면 2억 달러(약 2,246억 원)에 달하는 REP 경제 전체가 중단될 수 있습니다.
The Complete Story
비공개적으로 이러한 문제를 알리기 위해 Augur 팀에 2017년 7월 13일에 연락했습니다. 주지해야 할 점은 심각한 취약점은 Augur의 코드가 아니라 Serpent 컴파일러 코드에 내재한다는 것 입니다. Augur 팀에 Augur 프로젝트의 피해를 최소화할 mitigation plan을 제안하였으며 그들은 이를 수용하였습니다. 그 내용은 아래와 같습니다.:
1- OpenZepplin의 재사용가능한 컴포넌트를 바탕으로 새 REP 스마트 컨트랙트를 Solidity로 작성할 것.
2- 새 REP 토큰 컨트랙트를 감사 받을 것
3- 취약점 공개 25시간 전인 2017년 7월 24일에 거래소와 지갑 서비스 제공자에게 취약점을 알릴 것
4- 새 REP 토큰 컨트랙트를 이더리움 블록체인에 배포할 것
5- 2017년 7월 25일에 기존 REP 토큰을 동결할 것(취약점을 스스로 공개할 것)
6- 동결된 REP 토큰을 새 REP 토큰으로 마이그레이션할 것
새 토큰은 Augur팀이 OpenZeppelin을 사용하여 개발하였고 Zeppelin Solution 팀에게 감사받았습니다. 새 토큰 배포, 마이그레이션, 관련된 스크립트 또한 감사를 받았습니다.
REP 취약점 설명
어떻게 기존 REP 토큰이 동결될 수 있는지 이해하려면, 우선 Serpent의 치명적이게 심각한 취약점을 이해해야 합니다.
첫째, Serpent 컨트랙트는 배열의 범위를 초과하여 접근함으로써 storage location을 덮어쓸 수 있습니다. 즉, Serpent contract가 배열의 길이보다 큰 위치에서 배열에 액세스하려고 시도하면 Serpent는 이를 제지하지 않습니다.
둘째, Serpent 언어는 타입이 없습니다. 모든 데이터에 모든 오퍼레이션을 수행할 수 있습니다. 모든 값은 256-bit 시퀀스이며 이는 주소, 컨트랙트, 정수형 변수, 배열로 사용 가능합니다. 더군다나 트랜잭션에서 사용자가 전송 한 데이터를 검사하지 않습니다.
우리는 예상치 못한 데이터를 함수 인자에 포함함으로써 REP contract가 storage location을 덮어쓰도록 강제할 수도 있겠다는 생각에 이르렀습니다.
위의 정보를 바탕으로 공격이 어떻게 작동할지 다음의 토큰 컨트랙트 소스 코드를 직접 살펴볼 수 있습니다.
공격을 위해선 receiver 인자를 reputation 배열의 길이(2**160)보다 크게끔 트랜잭션을 작성하여 REP 컨트랙트에 transfer call을 전송해야합니다. 일견 배열의 크기는 합리적이여 보입니다. 이더리움의 주소의 길이는 오직 160 bits 일 수 밖에 없으니깐요.
그러나 Serpent는 타입과 배열 범위를 검사하지 않으며 Receiver 인자는 공격자가 온전히 제어할 수 있음을 유념해야합니다. receiver 인자가 reputation 배열(60번째 줄)을 참조하도록 사용되면 컨트랙트의 다른 storage location을 수정하는 데 (receiver 인자를)사용할 수 있습니다.
어떤 receiver 값이 어떤 storage location에 매핑되는지를 설명하는 것은 지나치게 복잡하므로 독자의 몫으로 남기겠습니다. 아래의 call을 살펴보는 것만으로도 충분합니다.
transfer(2**160+4, 1)
REP 토큰의 decimals 스토리지 변수를 18에서 19로 변경합니다. REP 동결 트랜잭션은 다음과 같습니다.
transfer(2160+6, 1010)
이는 creation 스토리지 변수를 10**10씩 증가시켜 140 번째 줄에 정의된 stillCreating 매크로를 통해 약314년 후에 크라우드세일이 시작된다고 컨트랙트가 여기게 할 수 있습니다. 이후에 발생하는 모든 transfer call은 55 번째 줄의 체크 코드로 인해 실패하게 됩니다.
중요한 점은 이 공격을 수행하는데 필요한 REP 밸런스는 0.0000002145 USD(글 작성 시점)입니다.
두개의 컴파일러 버그로 인해 단일 트랜잭션이2억 달러(약 2,246억 원)와 REP 경제를 중단시킬 힘을 가질 수 있습니다.
결론
Serpent가 가진 많은 문제가 해결되지 않는 이상 안전하다고 생각해서는 안됩니다. Serpent로 작성된 컨트랙트를 사용하는 모든 프로젝트는 위에서 제시한 mitigation plan를 참조하여 Solidity로 마이그레이션하길 권합니다. 이에 대한 도움이 필요하면 연락바랍니다. Solidity 컴파일러의 공식 감사도 필요하다고 생각하며 이는 이더리움 파운데이션과 논의중입니다.
다른 소프트웨어 컴포넌트와 마찬가지로 스마트 컨트랙트 또한 취약성이 있습니다. 우리 업계는 안전한 스마트 컨트랙트 코드를 확보하기 위한 개선된 메커니즘을 필요로 합니다.
스마트 컨트랙트 보안에 관심이 있으신 분은 우리의 슬랙 채널에 참여하거나 우리의 Medium 블로그를 팔로우하세요. 우리 팀에 지원해도 됩니다. 우리는 또한 스마트 컨트랙트 보안 개발과 감사 작업도 제공가능 합니다.
참조
Serpent Compiler Vulnerability, REP & Solidity Migration - Augur (https://medium.com/@AugurProject/serpent-compiler-vulnerability-rep-solidity-migration-5d91e4ae90dd)
Serpent Compiler Audit - Zeppelin Solutions (https://blog.zeppelin.solutions/serpent-compiler-audit-3095d1257929)
Zeppelin Solutions Serpent Compiler Audit v1.0.0 - Zeppelin Solutions (https://docs.google.com/document/d/1_PqXuAkvgUAOG3jbBvaUvqN6W90eJ3N4IdTLNMRAijo/edit)
Vitalik Buterin tweeted @ 16 Jul 2017 - 01:40 UTC
Disclaimer: I am just a bot trying to be helpful.
Congratulations @gurrpi! You received a personal award!
You can view your badges on your Steem Board and compare to others on the Steem Ranking
Do not miss the last post from @steemitboard:
Vote for @Steemitboard as a witness to get one more award and increased upvotes!