시작 할 때에는 문제의 임무를 먼저 확인한다.
이번 단계에서는 초능력을 사용해서 10번의 결과를 추측해야 한다고 한다.
먼저 인스턴스 가져오기 버튼을 통해 메타마스크에 트랜잭션을 발생시키고
인스턴스 주소를 불러온다.
컨트랙스 소스코드를 보면
openzepplin의 SafeMath 라이브러리를 사용한다.
상태변수 3가지
- consecutiveWins : 횟수를 저장하는 변수 public 프론트에서 조회 가능하다.
- lastHash : hash값
- FACTOR : 랜덤 값을 만들어 낼 때 사용하는 값.
생성자
- 컨트랙트 생성시에 consecutiveWins를 0으로 선언한다.
flip이라는 함수는 bool 값을 반환한다.
solidity 공식 문서에서 blockhash와 block.number 전역변수로 사용 가능하다고 나와있다.
- block.number : 현재 블록 번호
- blockhash : 256개의 가장 최근 블록 중 하나일 때 주어진 블록의 해시 그렇지 않으면 0을 반환을 나타낸다고 한다.
- revert : 수동 오류를 발생시키고 사용하지 않은 모든 가스를 환불한다.
시작
소스코드를 리믹스에 붙여넣고
import 부분은 현재 버전차이로 인해 수정한다.
import 'https://github.com/OpenZeppelin/openzeppelin-contracts/blob/solc-0.6/contracts/math/SafeMath.sol';
그리고 새로운 파일을 하나 더 만들고
위의 coinFilp을 공격하는 소스를 작성한다.
import를 통해서 다른 컨트랙트 또한 불러올 수 있다.
개발자 도구 콘솔에서 await contract.address 로 컨트랙트 주소를 얻은 후에
Deploy 부분에 컨트랙트 주소를 넣어준다.
- 생성자 선언 부분에 address로 주소값을 받기 때문에 이처럼 가능한 것이다.
이후에 Deploy를 진행한다.
contract.consecutiveWins() 로 현재 횟수를 확인하고
배포 된 컨트랙트에서 filp 버튼을 누르고 트랜잭션을 발생시킨다.
그리고 다시 contract.consecutiveWins() 로 확인해보면 계속해서 누적횟수가 올라갈 것이다.
누적이 10이 되면 문제는 클리어된다.
취약점
이번 레벨에서는 컨트랙트에서 다른 컨트랙트의 함수를 사용할 수 있다는 것을 알게 되었는데.
Attack 컨트랙트의 flip 함수에서 CoinFlip의 flip함수를 불러 사용한다.
blockhash를 이용해서 난수를 생성하며,
Attack 컨트랙트에서 해당 값을 구하고 CoinFlip의 Flip함수를 호출하면
같은 값이 나온다.
즉 안전한 난수 생성을 할 필요가 있다라고 생각이 된다.
'Ethereum > Ethernaut' 카테고리의 다른 글
5. Token (0) | 2021.07.20 |
---|---|
4.Telephone (0) | 2021.07.15 |
2.Fallout (0) | 2021.07.09 |
1. Fallback (0) | 2021.07.08 |
0. Hello Ethernaut (0) | 2021.07.08 |