๋ฌธ์ ํด์ค์ ๋ค์ด๊ฐ๊ธฐ ์ , ์ด๋ฒ ํฌ์คํ ์ ์ด๋๋ ๋ด์์ ์ฝ์์ฐฝ๊ณผ ์ํธ์์ฉ์ ํ ์ค ์๊ณ ๊ธฐ๋ณธ์ ์ธ ๋ฆฌ๋ฏน์ค ๋ฐ ๋ฉํ๋ง์คํฌ ์ฌ์ฉ๋ฒ์ด ์์ง๋์ด ์๋ค๋ ๊ฐ์ ํ์ ํด์ค์ ์งํํฉ๋๋ค.
์ด๋ฒ ๋ฌธ์ ์ ๋ชฉํ๋ King์ด ๋๋ ๊ฒ์ด๋ค. ์ฌ์ค ์ฝ๋๋ง ๋ณด๋ฉด prize๋ณด๋ค ํฐ ๊ธ์ก๋ง ๊ฑธ๋ฉด ์์์ ์ค๋ฅผ ์ ์๊ธฐ ๋๋ฌธ์ ๋ฌด์ฒ์ด๋ ๊ฐ๋จํ ๋ฌธ์ ์ฒ๋ผ ๋ณด์ธ๋ค. ์ค์ ๋ก ๋จ ํ๋ฒ์ sendTransaction์ ํตํ์ฌ ์ด๋ฒ ๋จ๊ณ๋ฅผ ํด๊ฒฐ ํ ์ ์๋ค. ๊ทธ๋ฌ๋, Ethernaut์ด ๋งํ๊ณ ์ถ์ ๋ฌธ์ ๋, Your goal is to break it.์ฆ, ์์ํ ์์์ ์ค๋ฅผ ์ ์๋ ๋ฐฉ๋ฒ์ ๊ตฌํ๋ผ๊ณ ํ๋ ๊ฒ์ด๋ค. ์! ์ด์ ์์ข๋ฅผ ์ฐจ์งํ๋ฌ ์ฝ๋์์ผ๋ก ๋ค์ด๊ฐ ๋ณด์!
์ด๋ฒ ๋ฌธ์ ๋ฅผ ๋ค๋ฅธ ๋จ๊ณ์์ ํด๊ฒฐํ๋ ๋ฐฉ๋ฒ๋๋ก ์ฃผ์ด์ง ์ฝ๋๋ฅผ ๋ฐ๋ก ๋ฆฌ๋ฏน์ค์ ๋ณต์ฌํด๋ ์ปดํ์ผ์ด ๋ถ๊ฐ๋ฅ ํ ๊ฒ์ด๋ค. importํ๊ณ ์๋ Ownable.solํ์ผ์ ์ฐพ์ง ๋ชปํด์ ๋ฐ์ํ๋ ๋ฌธ์ ์ด๋, https://github.com/OpenZeppelin/openzeppelin-solidity/blob/v1.0.5/contracts/ownership/Ownable.sol (์ด๋๋์์ 0.4.18์ปดํ์ผ์ ์ฌ์ฉํ๋ฏ๋ก, ์ต์ ์ฝ๋๊ฐ ์๋ ์ฝ๋์์ ์ด ํ์์๋ Ownable์ ๋งํฌ)์ด๊ณณ์์ ์ฝ๋๋ฅผ ๋ณต์ฌํ์ฌ ํจ๊ป ์ปดํ์ผ ํ๊ฑฐ๋, ๋ฆฌ๋ฏน์ค์์ Ownable.sol ํ์ผ์ ๋ฏธ๋ฆฌ ๋ง๋ค์ด ๋์์ผ ํ๋ค.
์์๋ฅผ ํ์ทจํ๊ณ ์์ํ ์์ข๋ฅผ ์ฐจ์งํ๊ธฐ ์ํด ์ปจํธ๋ํธ ์ด๋ฆ์ ์ ๋ณต์๋ผ๊ณ ์ง์๋ค. ์ ๋ณต์ ์ปจํธ๋ํธ๋ฅผ ๋์ ๊ณ์ ์ผ๋ก ๋ฐฐํฌํ์.
//์์ฑ์
function King() public payable {
king = msg.sender; // King ์ปจํธ๋ํธ๋ฅผ ๋ฐฐํฌ ํ๋ ๊ณ์ ์ด king์ด ๋๋ค.
prize = msg.value; // ์ปจํธ๋ํธ๋ฅผ ๋ฐฐํฌํ ๋, ๊ธฐ์
ํ ๊ฐ์ด prize๊ฐ ๋๋ค.
}
function() external payable {
require(msg.value >= prize || msg.sender == owner);
king.transfer(msg.value);
king = msg.sender;
prize = msg.value;
}
์ธ๋ถ์์ ๋ฐ๋ก King์์ฑ์(function)์ ํธ์ถํ์ฌ ์ด๋ฒ ๋ฌธ์ ๋ฅผ ํด๊ฒฐ ํ ์ ์์ง๋ง, constructor๊ฐ ์๊ธด ์ง๊ธ์ ์ํฉ์ ๊ณ ๋ คํ๋ฉด ์ ๋๋ก ๋ ํ์ด ๋ฒ์ด ์๋๋ค.
์ต๋ช ํจ์๋ฅผ ์ฃผ๋ชฉํด๋ณด์! ์ ํจ์ฑ์ ๊ฒ์ฌํ๋ require๋ฌธ์์ prize๋ณด๋ค ์์์ ์ค๋ฅผ ๊ณ์ ์ value๊ฐ ์ปค์ผํ๊ณ , sender์ owner๊ฐ ๊ฐ์์ผ ํ๋ค. ์ด๋๋์ผ๋ก ๋ถํฐ ๋ฌธ์ ๊ฐ ๋ฐฐํฌ๋์์๋๋ sender์ owner๊ฐ ๊ฐ์ง๋ง ์ฐ๋ฆฌ๊ฐ ๋ค๋ฅธ ์ปจํธ๋ํธ๋ฅผ ํตํด sender์ owner๋ฅผ ๋ค๋ฅด๊ฒ ๋ง๋ค๋ฉด ์์ํ ์์์ ์ค๋ฅผ ์ ์๋ค!
pragma solidity ^0.4.18;
contract Conqueror {
function Conqueror() public {}
function victory(address _king) public payable {
_king.call.value(msg.value)();
}
function() public payable {
revert();
}
}
victory ํจ์๋ ์ธ์๋ก ๋ฐ์ target ์ฃผ์์ fallback ํจ์๋ฅผ msg.value๋งํผ์ ๊ธ์ก์ ์ ์กํ๋ ํํ๋ก ํธ์ถํ๋ค.
์ ์์๋ traget์ด ๋ ํจ์๊ฐ fallback์ด๊ธฐ ๋๋ฌธ์ ()์ํ๋ก ๋์๋ค. ๋ง์ฝ target ์ปจํธ๋ํธ์ ๊ณต๊ฒฉ๋์ ํจ์๋ก a()๋ผ๋ ํจ์๊ฐ ์๋ค๋ฉด(bytes4(sha3("a()")))์ ์ฌ์ฉํด์ Methods Id๋ฅผ ์์๋ธ๋ค. Methods Id๋ฅผ ๋ฆฌ๋ฏน์ค์์ ์์๋ด๋ ๋ฐฉ๋ฒ์ ํ์์ Delegation Problem ์์ ์ค๋ช
ํด ๋์๋ค.
bytes4(sha3("a()"))
์ด๋๋ฆฌ์์์๋ ์ปดํ์ผ ๋ ํจ์๋ฅผ, ์๋ฆฌ๋ํฐ๋ก ์์ฑํ ํจ์์ sha3 ํด์๊ฐ ์ฒซ 4๋ฐ์ดํธ๋ฅผ ์ด์ฉํ์ฌ ์๋ณํ๋ค. ๊ฒ์ค์์ ํจ์๋ฅผ ํธ์ถํ ๋๋ ABI๊ฐ ์๋ ค์ ธ ์๊ธฐ ๋๋ฌธ์ ์ปดํ์ผ ์ด์ ์ ํจ์๋ช ์ ์ฌ์ฉํ ์ ์์ง๋ง, ํธ์ถํ ๊ฒฝ์ฐ์๋ ์ปดํ์ผ๋ ํจ์์ ์๋ณ์๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค.
call ํจ์๋ ์์ ์์นํ ์ฃผ์์ ๋ํด value ์ธ์๋ก ์ง์ ํ ๊ธ์ก(wei ๋จ์)๋ฅผ ์ก๊ธํ๋ค. ์ด๋, value ๋ค์ ์ค๋ ๊ดํธ ์์ ํจ์๋ฅผ ๋ฃ์ผ๋ฉด ๋์ ๊ณ์ฝ์ ํจ์๋ฅผ ํธ์ถํ๋ค.
์ฆ, '_kingํจ์์ ์์นํ fallbackํจ์๋ฅผ msg.value๋งํผ ์ ์กํ ๊ธ์ก์ผ๋ก ์ง์ ํ๋ฉฐ ํธ์ถํ๋ค'๋ ์๋ฏธ๋ค.
Fallback ํจ์๋ ๋ค๋ฅธ ๋๊ตฐ๊ฐ๋ก๋ถํฐ Conqueror ์ปจํธ๋ํธ๋ฅผ ๋ณดํธํ๊ธฐ ์ํด์ ๋ฃ์ด๋์ ํจ์ ์ด๋ค. Conqueror ์ปจํธ๋ํธ์ ํธ๋์ญ์ ์ ๋ฐ์์์ผ๋ ๋ฐ๋ก revert์์ผ์ ์ปจํธ๋ํธ๋ฅผ ๋ณดํธํ๋ค. ์ฌ์ค ์ด๋ฌธ์ ๋ฅผ ํ์ ๋๋ ๊ผญ ์์ฑํ์ง ์์๋ ๋๋ค.
ํ์ฌ owner์ king์ ์์ ๋ช ์๋ ์ฃผ์์ด๊ณ , prize๋ 1ETH ์ด๋ค. ์ฆ, 1์ด๋ ์ด์์ King์ CA์ ์ ์กํ๋ฉด ์์ด ๋ ์ ์๋ค.
๋ฆฌ๋ฏน์ค์์ ๋ฐฐํฌํ Conqueror ์ปจํธ๋ํธ๋ฅผ ํ์ฉํ์ฌ target์ด ๋ King์ ์ฃผ์๋ฅผ ๋ฃ๊ณ , Value ๊ฐ์ 1์ด๋ ์ด์์ ๊ธ์ก์ ๋ฃ๊ณ ํธ๋์ญ์ ์ ๋ฐ์์ํจ๋ค.
๊ทธ๋ฌ๋ ๊ฐ์ค๋ฆฌ๋ฐ๊ณผ ์์๋ฃ๋ฅผ ๋๋ํ๊ฒ ์ง์ ํด ์ฃผ์์์๋ ๋ถ๊ตฌํ๊ณ , Out of gas ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ค.
๋กญ์จ ๋คํธ์ํฌ ์์ ๋ฌธ์ ๋ก ์ธ์ํ๊ณ ๊ทธ๋ฅ King ์ปจํธ๋ํธ์ 1์ด๋ ์ด์์ ๊ธ์ก์ ๋ฃ์ด์ ๋ค์๋จ๊ณ๋ก ๋์ด๊ฐ์.
ํ์๊ฐ out of gas๋ฌธ์ ๋ฅผ ๊ณ ๋ฏผํ๋ค๊ฐ ๊ฐ์ค๋ฆฌ๋ฐ๊ณผ ๊ฐ์ค๊ฐ๊ฒฉ์ ์ ์๋ฅผ ์ ๋ชป ์ดํดํ๊ณ ์๋ค๋ ๊ฒ์ ๊นจ๋ฌ์๋ค. ๋ฉํ๋ง์คํฌ์์ ๊ฐ์ค ์์๋ฃ๋ฅผ ๋๋ฅด๋ฉด ๊ฐ์ค ๊ฐ๊ฒฉ๊ณผ ๊ฐ์ค ๋ฆฌ๋ฐ์ด ๋์จ๋ค.
์ด๋ ์ค์บ์์ ํธ๋์ญ์ ์์์ฆ์ ํ์ธํด ๋ณด๋ฉด, Actual Tx Cost/Feeํญ๋ชฉ์ด ๋ณด์ธ๋ค. ์ด๊ฒ์ด ๋ด๊ฐ ์ง์ ํ ๊ฐ์ค ๊ฐ๊ฒฉ์ ์ค์ ์ฌ์ฉํ ๊ฐ์ค์(Gas Used By Txn)์ ๊ณฑํ์ฌ ๊ณ์ฐ๋ ๊ฒฐ๊ณผ๊ฐ ๋์จ๋ค. ์๋ ํ์์ ์ด๋์ค์บ๋ด์ญ์ ํ์ธํ๋ฉด์ ๊ฐ์ค์ ๋ํ ์ดํด๋๋ฅผ ๋์ด์!
๋ค์ ๋กญ์จ ํ ์คํธ๋ท์์ ์งํํ ๊ฒฐ๊ณผ ๋ฌธ์ ์์ด ์ ์คํ๋๋ค.
ํ์์ King Problem ์ฑ๊ณต Receipt
์ฐธ๊ณ ๋ก, ์ ์ด๋์ค์บ์์ ๋ณด์ฌ์ง๋ To๋ฅผ ๋ค์ฌ๋ค๋ณด๋ฉด ์ด๋๊ฐ 2์ฐจ๋ก์ ๊ฑธ์ณ์ ๋ณด๋ด์ก๋๋ฐ King์ปจํธ๋ํธ ๋ด๋ถ์ ์์ฑ๋ ์๋์ ๊ฐ์ ์ฝ๋๋๋ฌธ์ ๋ฐ์ํ ๊ฒ์ด๋ค.
king.transfer(msg.value);
๋์ ํ์ด๋ฒ์ด ๋ง๋์ง ์ ๊ฒํด ๋ณด๊ธฐ์ํด์ ํ๊ฒฝ๋ง ๋ฐ๊ฟ ํ ์คํธ๋ฅผ ์งํํ๋ค.
์์ ๊ฐ์ด Conqueror ์ปจํธ๋ํธ๋ฅผ ํ์ฉํ์ฌ2์ด๋๋ฅผ ์ ์กํ์ฌ King(์ ์ฌ์ง์ ๋ณด๋ฉด ํน๊ณผ ์ค๋๊ฐ ๋ค๋ฅด๋ค)์ด ๋๊ณ ๋ค๋ฅธ ์ฃผ์(0x4b0....)๋ก King์ปจํธ๋ํธ์ 3์ด๋ ์ด์์ ํธ๋์ญ์ ๋ฐ์์ํค๋ฉด revert์ฒ๋ฆฌ๊ฐ ๋ ๊ฒ์ ์ฝ์์ฐฝ์์ ํ์ธ ํ ์ ์๋ค. King.sol์ ์ทจ์ฝ์ ์ด ์๋ ์ ํจ์ฑ ์ฒดํฌ ์กฐ๊ฑด๋ฌธ์์ ์ ๋ณต์ ์ปจํธ๋ํธ๊ฐ sender์ owner๊ฐ ๋ค๋ฅด๊ฒ ๋ง๋ค์ด ๋์๊ธฐ ๋๋ฌธ์ ์์ธ์ฒ๋ฆฌ๊ฐ ๋๋ ๊ฒ์ด๋ค.
์ด๋ฒ ๋ฌธ์ ๋ฅผ ํตํ์ฌ ์ ์์ ์ธ ์๋๋ฅผ ๊ฐ์ง ์ปจํธ๋ํธ์ ์ํด์ ๋ด๊ฐ ๋ฐฐํฌํ ์ฝ๋๊ฐ ๋ณธ๋์ ์๋์๋ ๋ค๋ฅด๊ฒ ์์ฉํ ์ ์๋ค๋ ๊ฒ์ ์ฒดํํ๋ค. ์ด๊ฒ์ ์ค์ ์ค๋งํธ ์ปจํธ๋ํธ๋ก ๊ฒฝ๋งค์ ๊ด๋ จ๋ ์๋น์ค๋ฅผ ์ ๊ณตํ ๋ ์์ ๊ฐ์ ๊ณต๊ฒฉ์ ๋ํ ๋๋น์ฑ ์ด ์๋ค๋ฉด, ์ ์์ ์ธ ๊ณต๊ฒฉ์์ ์ํ ๊ณต๊ฒฉ์ ๋ฐ์ผ๋ฉด ์๋ฌด๋ ์ ์ฐฐ ํ ์ ์๋ ๋ฌธ์ ๋ฅผ ๋ฐ์์ํจ๋ค. ๋๋ฌธ์ ์ฐ๋ฆฌ๋ ์กฐ๊ฑด๋ฌธ์ ์์ฑํ ๋์๋ ์ ์คํ๊ฒ ์ฝ๋๋ฅผ ์ง์ผํ๋ค.
๋ค์๋ฒ์๋ 10๋จ๊ณ Re-entrancy์์ ๋ง๋์!