[Decentralized Application Security Project (DASP)] (http://www.dasp.co/index.html)
1. Reentrancy (recursive call vulnerability call to the unknown)
function withdraw(uint _amount) {
require(balances[msg.sender] >= _amount);
msg.sender.call.value(_amount)();
balances[msg.sender] -= _amount;
}
- msg.sender 가 smart contract 였을때 해당 smart contract가 실행이 되는데 이때 Fallback 함수에서 다시 withdraw 를 실행하게 되면 무한으로 계속 인출 되게 된다. (다오 사건)
2. Access Control
function initContract() public {
owner = msg.sender;
}
- public으로 외부에서 아무나 접근할 수 있어서 문제가 발생.
function () payable {
if (msg.value > 0)
Deposit(msg.sender, msg.value);
else if (msg.data.length > 0)
_walletLibary.delegatecall(msg.data);
}
contract WalletLibary is WalletEvents {
function initMultiOwned(address[] _owners, uint _required) {
}
function initWallet(address[] _owners, uint _required, uint _daylimit) {
initMultiOwned(_owners, _required);
}
}
- delegate call 을 통해서 라이브러리에 있는 함수를 호출해서 문제 발생. (Parity Multi-sig Wallet)
3. Arithmetic Issues
function withdraw(uint _amount) {
require(balances[msg.sender] - _amount > 0);
msg.sender.transfer(_amount);
balances[msg.sender] -= _amount;
}
- 위코드는 실제로 내 잔고 보다 _amount 양이 많다면 결과는 마이너스 값을 가지게 된다. 하지만 _amount 타입이 unsigned integer 이므로 마이너스 를 표현하기 위해서 어마무시한 큰 숫자로 변하게 된다.
- openzeppelin safeMath lib 사용 하여 방지. (https://github.com/OpenZeppelin/openzeppelin-solidity)
4. Unchecked Return Values For Low Level Calls
function withdraw(uint256 _amount) public {
require(balances[msg.sender] >= _amount);
balances[msg.sender] -= _amount;
etherLeft -= _amount;
msg.sender.send(_amount);
}
- msg.sender.send()를 할때 문제가 발생할때에 대한 예외가 필요하다.
- msg.sender.transfer 를 사용하거나 msg.sender.send 의 반환값을 확인하여 성공 유무에 따라서 별도의 예외처리가 필요하다.
5. Denial of Service
function becomePresident() payable {
require(msg.value >= price); // must pay the price to become president
president.transfer(price); // we pay the previous president
president = msg.sender; // we crown the new president
price = price * 2; // we double the price to become president
}
function selectNextWinners(uint256 _largestWinner) {
for (uint256 i = 0; i < largestWinner, i++) {
// heavy code
}
largestWinner = _largestWinner;
}
- Gas Limit에 도달했거나 예상치 못한 throw 를 실행시켰을 때 사용할 수 없는 계약이 되어버리는 취약점.
- 악성 사용자가 Gas를 소모하게 되는 트랜잭션에 특정 조건을 증가시키게 되면 필요한 Gas 양이 Gas Limit 에 초과가 되면며 실행이 되지 못한게된다.
6. Bad Randomness
uint256 private seed;
function play() public payable {
require(msg.value >= 1 ether);
iteration++;
uint randomNumber = uint(keccak256(seed + iteration));
if (randomNumber % 2 == 0) {
msg.sender.transfer(this.balance);
}
}
function play() public payable {
require(msg.value >= 1 ether);
if (block.blockhash(blockNumber) % 2 == 0) {
msg.sender.transfer(this.balance);
}
}
- Contract 내 생성된 랜던값은 모든 노드들이 같은 결과물을 실행해야 하기 때문에 의 랜덤의 결과값이 같아야 하므로 하드웨어적인 랜던값을 사용하지 못하고 TimeStamp, Seed, Block을 기준으로 랜던값을 생성해 내게 된다.
- 위 코드는 짝수일 경우 Ethereum 을 보내게 되는데 악의적인 Smart Contract가 짝수일때만 요청을 보내게 되면 항상 이기게 된다.
7. Front-Running
1. Alice는 일정량의 가스를 포함한 트랜잭션을 수행한다.(해결책 포함)
2. 네트워크에있는 누군가는 Alice의 트랜잭션(해결책 포함)을 보고 더 높은 가스 가격으로 제출하고 최종 마이닝 되기를 기다린다.
3. 마이너들은 더 높은 수수료를 받기위해서 두번째 트랜잭션을 채택하게 되고, 결국 공격자의 트랜잭션이 선택되어 지게된다.
- 이더리움 마이너 들은 외부 소유 주소 (EOA)를 대신하여 코드 실행에 대한 가스 요금을 통해 항상 보상을받으며, 사용자는 거래를보다 신속하게 채굴 할 수 있도록 더 높은 수수료를 지정할 수 있다.
Ethereum 블록 체인은 공개되어 있으므로 누구나 다른 사람들의 보류중인 거래 내용을 볼 수 있다. 즉, 특정 사용자가 퍼즐이나 다른 중요한 비밀에 대한 솔루션을 공개하는 경우 악의적 인 사용자가 솔루션을 훔쳐 원래 거래를 선점하기 위해 더 높은 수수료로 거래를 복사 할 수 있게된다.
8. Time manipulation
function play() public {
require(now > 1521763200 && neverPlayed == true);
neverPlayed = false;
msg.sender.transfer(1500 ether);
}
- 특정시간에 선착순 한명한테 보상을 준다고 하였을때 시간을 조작해서 우선순위를 조작할 수 있다.
9 Short Address Attack
- Ethereum Address 는 20byte로 인자값 32byte는 아래와 같이 채워지게 된다.
(함수의해쉬값[4byte], Zero-padding[12byte] + Address[29byte] , 함수의 인자2 [32byte] )
문제는 Address 주소가 19byte 뿐이라면 데이타구조가 (함수의해쉬값 [4byte], Zero-padding[12byte] + Address[19byte] , 함수의 인자2 [33byte] ) 가 되게되므로 amount 양이 8bit왼쪽으로 이동하게되어 원래 보내려고 하던 양보다 256배 큰수가 된다. 따라서 web3 library 에서 check address 로 주소가 20byte 인지 확인을 해서 개발을 해야한다. https://web3js.readthedocs.io/en/1.0/web3-utils.html
Congratulations @birdgang! You have completed some achievement on Steemit and have been rewarded with new badge(s) :
You made your First Comment
Click on any badge to view your own Board of Honor on SteemitBoard.
For more information about SteemitBoard, click here
If you no longer want to receive notifications, reply to this comment with the word
STOP
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit
Congratulations @birdgang! You received a personal award!
Click here to view your Board
Do not miss the last post from @steemitboard:
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit
Congratulations @birdgang! You received a personal award!
You can view your badges on your Steem Board and compare to others on the Steem Ranking
Vote for @Steemitboard as a witness to get one more award and increased upvotes!
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit