목록web3/The Ethernaut (9)
Tyojong
문제 설명코드 분석문제 컨트랙트 배포 시 설정된 패스워드와 일치하는 패스워드를 unlock함수 인자로 넣으면 금고의 잠금이 해제된다.익스플로잇password 변수가 private로 선언되어 있지만 private은 단순히 다른 컨트랙트에서 접근을 막을 뿐, 외부에서 직접 스토리지를 조회하는 것은 막지 못한다. cast storage 명령어를 사용해 storage 슬롯을 읽는다. (슬롯0: locked, 슬롯1: password) 알아낸 패스워드를 unlock함수의 인자로 넣고 실행시키면 문제를 해결할 수 있다.
문제 설명코드 분석이번 문제의 컨트랙트 코드를 보면 이더를 받기 위한 함수가 정의되지 않았다. 원래 컨트랙트에서는 이더를 받기 위해 receive() 함수, fallback() 함수, payable 함수를 사용해야한다.해당 함수들을 사용하지 않는 컨트랙트에 이더를 보내면 해당 트랜잭션은 revert된다.Selfdestructselfdestruct는 solidity에서 스마트 컨트랙트를 블록체인에서 제거하고, 남은 이더를 지정된 주소로 강제 전송하는 함수이다.이 함수를 사용하게 되면 컨트랙트의 어떤 코드도 실행하지 않고 강제로 이더를 전송하게 된다. receive나 fallback이 없어도, 이더 수신을 거부하는 로직이 있어도 강제로 받게 된다.익스플로잇공격 컨트랙트를 생성하여 selfdesturct를 이..
문제 설명코드 분석Delegate 컨트랙트는 배포 시 owner가 정해지지만 pwn() 함수를 이용해 owner를 호출한 사용자로 변경할 수 있다. Delegation 컨트랙트는 배포시 호출한 사용자가 owner로 지정된다.fallback() 함수는 컨트랙트에 존재하지 않는 함수를 호출할 경우 실행된다. fallback() 함수에서는 address(delegate)를 통해 위 Delegate 컨트랙트를 불러온다.Delegate컨트랙트의 함수를 delegatecall을 이용해 호출한다.call vs delegatecallCA1에서 CA2의 함수를 call로 호출하면 CA2의 storage를 이용하지만CA1에서 CA2의 함수를 delegatecall로 호출하면 CA1의 storage를 이용하게 된다. del..
문제 설명코드 설명호출한 사용자의 잔액에서 _.value 만큼 _to에게 토큰을 전송한다.보내는 토큰은 잔액보다 많지 않아야 하고 _value값 만큼 사용자의 잔액에서 차감되며 _to의 잔액이 증가한다.익스플로잇solidity 0.6 버전에서는 언더플로우체크가 존재하지 않는다.balances[msg.sender] (사용자의 잔액) 보다 _value값이 크면 뺄셈 이후 음수가 되어야 하지만 uint의 경우 음수가 불가능하므로 언더플로우가 발생하게 된다. 사용자의 잔액이 20토큰으로 주어졌기 때문에 20보다 큰 값을 _value인자로 전달하면 된다. 문제 컨트랙트 transfer함수에 아무 주소와 21을 인자로 주면 문제가 해결된다.
문제 설명코드 분석이전 블록해시값과 FACTOR를 나눈 몫이 1이면 true값 아니면 false값을 반환하여_guess로 받은 bool값과 일치하면 consecutiveWins값이 1증가하고 틀리면 0으로 초기화된다. 이더리움에서 블록은 12초에 하나씩 생성되는데 하나의 블록에서 12초안에 10번의 트랜잭션을 보내면 모두 맞거나, 모두 틀리거나 50% 확률로 성공할 수 있는 가능성이 있다.때문에 문제에서는 이를 방지하기 위해 이전 트랜잭션에서 사용한 블록 해시와 현재 트랜잭션의 블록 해시를 비교해 일치하면 revert시켜 모두 다른 트랜잭션에서 시도하도록 만들었다.익스플로잇EOA(사용자)가 CA1(공격 컨트랙트)를 실행하고 CA1이 CA2(문제 컨트랙트)를 실행하면 이 과정은 하나의 트랜잭션으로 실행된다..
문제 설명코드 분석처음 배포자가 owner로 설정되고 changeOwner에 주소를 넣고 호출 시 넣은 주소가 owner가 된다.단, changeOwner함수를 호출한 주소(msg.sender)가 트랜잭션을 시작한 주소(tx.origin)랑 동일하면 안된다. 즉, 공격자가 changeOwner함수를 직접 호출해 owner를 설정하면 적용되지 않는다.익스플로잇msg.sender의 경우 스마트 컨트랙트 또는 사용자(EOA)의 주소를 받아온다.하지만 tx.origin의 경우 사용자(EOA)의 주소만 가져온다. 공격 컨트랙트를 생성해 컨트랙트에서 changeOwner를 호출하면 msg.sender는 공격 컨트랙트의 주소가 되고 tx.origin의 경우 사용자의 주소가 되어 owner를 변경할 수 있게된다.공격 ..
문제 설명 코드 분석Fal1out함수를 호출하면 owner가 되는데 접근제어가 존재하지 않아 누구나 호출하여 owner가 될 수 있다.컨트랙트명은 Fallout이지만 함수명은 Fal1out이라서 constructor로 동작하지 않는다.(옛날 버전에서는 컨트랙트명과 함수명이 동일하면 constructor로 사용이 되었다. 현재는 X) 익스플로잇이 문제는 컨트랙트의 소유권만 획득하면 해결되는 문제이므로 Fal1out()함수만 실행시키면 해결된다.
문제 설명이 문제는 Fallback, receive 함수가 잘못 설정되었을 때 발생할 수 있는 취약점을 학습할 수 있다.이 문제를 해결하기 위해서는 컨트랙트의 소유권을 획득하고 컨트랙트 잔고를 0으로 만든다.(모든 이더를 빼낸다.) 코드 분석배포자를 owner로 설정하고 owner의 초기 기여금을 1000 ETH로 설정한다. contribute() 함수는 0.001 ETH 미만의 금액만 받을 수 있고 받은 기여금을 저장한다.호출자의 기여금이 소유자의 기여금보다 많으면 owner(소유권)을 이전한다. 호출자의 현재 기여금을 알려주는 읽기 전용 함수이다. 호출자가 소유자인지 확인하는 제한자이다. 제한자가 적용되어 있는 함수로 소유자만 호출 가능하다.소유자 주소를 payable 타입으로 캐스팅하고 (ETH를 ..
이 문제는 password변수의 값이 private설정이 아닌 public설정으로 되어있어 발생하는 취약점으로변수 설정이 잘못 될 경우 민감한 정보가 노출될 수 있는 취약점이 발생한다는 것을 보여준다.인스턴스 생성 후 개발자 도구의 console 탭을 이용해 문제를 해결하면 된다.help()를 이용해 사용할 수 있는 함수 목록을 확인할 수 있다. 함수를 통해 여러 정보를 확인할 수 있고 await를 이용해 내가 원하는 값만 출력할 수 있다. 문제 설명에 contract.info() 또는 await contract.info()를 입력하라고 한다. await contract.info() 를 입력하니 info1() 을 입력하라고 한다. await contract.info1() 을 입력하니 이번에는 hello ..
