www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁 > 物聯(lián)網(wǎng) > 區(qū)塊鏈
[導(dǎo)讀] 如果你在數(shù)字貨幣世界待過足夠時間,也許你聽說過1或2個智能合約攻擊時間,這些攻擊導(dǎo)致了幾千萬美元的盜竊損失。最著名的攻擊是DAO事件,這是數(shù)字貨幣世界最受期待的項目之一,同時也是智能合約的改革。

如果你在數(shù)字貨幣世界待過足夠時間,也許你聽說過1或2個智能合約攻擊時間,這些攻擊導(dǎo)致了幾千萬美元的盜竊損失。最著名的攻擊是DAO事件,這是數(shù)字貨幣世界最受期待的項目之一,同時也是智能合約的改革。雖然很多人聽說過這些攻擊,但是很少人知道到底發(fā)生了什么,是怎么發(fā)生的,以及如何避免這些錯誤。

智能合約是動態(tài)的,復(fù)雜的以及難以置信地強大。雖然他們的潛力是很難想象,但是也不可能一夜之間就成為了攻擊的對象。也就是說,對于往后的數(shù)字貨幣,我們可以從之前的錯誤中學(xué)到經(jīng)驗,然后一起成長。雖然DAO是已經(jīng)發(fā)生的事情,但是這對于開發(fā)者,投資者,以及社區(qū)成員對于智能合約攻擊來說,都是一個很好的例子。

今天,我想和大家聊聊從DAO事件中,我們學(xué)到的3件事。

攻擊#1:重入攻擊

當(dāng)攻擊者通過對目標(biāo)調(diào)用提款操作的時候,重入攻擊就會發(fā)生,就好像DAO事件一樣。當(dāng)合約不能在發(fā)出資金之前更新狀態(tài)(用戶余額),攻擊者就可以連續(xù)進(jìn)行提取函數(shù)調(diào)用,來獲得合約中的資金。任何時候攻擊者獲得以太幣,他的合約都會自動地調(diào)用反饋函數(shù),function (),這就再次調(diào)用了提現(xiàn)合約。這時候,攻擊就會進(jìn)入遞歸回路,這時候這個合約中的資金就會轉(zhuǎn)入攻擊者。因為目標(biāo)合約都在不停地調(diào)用攻擊者的函數(shù),這個合約也不會更新攻擊者的余額。當(dāng)前的合約不會發(fā)現(xiàn)有任何問題,更清楚地說,合約函數(shù)中包含反饋函數(shù),當(dāng)合約收到以太幣和零數(shù)據(jù)的時候,合約函數(shù)就會自動執(zhí)行。

攻擊流程

1.攻擊者將以太幣存入目標(biāo)函數(shù)

2.目標(biāo)函數(shù)就會根據(jù)存入的以太幣而更新攻擊者的約

3.攻擊者請求拿回資金

4.資金就會退回

5.攻擊者的反饋函數(shù)生效,然后調(diào)用提現(xiàn)功能

6.智能合約的邏輯就會更新攻擊者的余額,因為提現(xiàn)又被成功調(diào)用

7.資金發(fā)送到攻擊者

8.第5-7步重復(fù)使用

9.一旦攻擊結(jié)束,攻擊者就會把資金從他們自己的合約發(fā)送到個人地址

1*UeDgMZo2n0skHzgkl352zQ

重入攻擊的遞歸回路

很不幸地是,一旦這個攻擊開始,無法停下。攻擊者的提現(xiàn)功能會被一次次地調(diào)用,直到合約中的燃料跑完,或者被害者的以太幣余額被消耗光。

代碼

下面就是DAO合約的簡單版本,其中會包括一些介紹來為這些不熟悉代碼/ solidity語言更好地理解合約。

contract babyDAO {

/* assign key/value pair so we can look up

credit integers with an ETH address */

mapping (address => uint256) public credit;

/* a funcTIon for funds to be added to the contract,

sender will be credited amount sent */

funcTIon donate(address to) payable {

credit[msg.sender] += msg.value;

/*show ether credited to address*/

funcTIon assignedCredit(address) returns (uint) {

return credit[msg.sender];

/*withdrawal ether from contract*/

funcTIon withdraw(uint amount) {

if (credit[msg.sender] >= amount) {

msg.sender.call.value(amount)();

credit[msg.sender] -= amount;

如果我們看下函數(shù)withdraw(),我們可以看到DAO合約使用address.call.value()來發(fā)送資金到msg.sender。不僅如此,在資金發(fā)出后,合約會更新credit[msg.sender]的狀態(tài)。攻擊者在發(fā)現(xiàn)了合約代碼中的問題,就能夠使用類似下面的ThisIsAHodlUp {}來將資金轉(zhuǎn)入contract babyDAO{}合約。

import ‘browser/babyDAO.sol’;

contract ThisIsAHodlUp {

/* assign babyDAO contract as "dao" */

babyDAO public dao = babyDAO(0x2ae...);

address owner;

/*assign contract creator as owner*/

constructor(ThisIsAHodlUp) public {

owner = msg.sender;

/*fallback function, withdraws funds from babyDAO*/

function() public {

dao.withdraw(dao.a(chǎn)ssignedCredit(this));

/*send drained funds to attacker’s address*/

function drainFunds() payable public{

owner.transfer(address(this).balance);

需要注意地是,這個后退函數(shù),function(),會調(diào)用DAO或者babyDAO{}的提現(xiàn)函數(shù),來從合約中盜取資金。從另個方面來說,當(dāng)攻擊者想要把所有偷竊來的資金賺到他們的地址,drainFunds()功能會被調(diào)用。

解決方案

現(xiàn)在,我們應(yīng)該清楚重放攻擊會利用兩個特別的智能合約漏洞。第一個是當(dāng)合約的狀態(tài)在資金發(fā)出之后,而不是之前進(jìn)行更新。由于在發(fā)出資金前無法更新合約狀態(tài),函數(shù)就會在中間計算的時候被打斷,合約也認(rèn)為資金其實還沒有發(fā)出。第二個漏洞就當(dāng)合約錯誤地使用address.call.value()來發(fā)出資金,而不是address.transfer() 或者 address.send()。這兩個都受限于2300gas,只記錄一個事件而不是多個外部調(diào)用。

contract babyDAO{

....

function withdraw(uint amount) {

if (credit[msg.sender] >= amount) {

credit[msg.sender] -= amount; /* updates balance first */

msg.sender.send(amount)(); /* send funds properly */

攻擊2:下溢攻擊

雖然DAO合約不會讓受害者掉入下溢攻擊,我們能夠通過現(xiàn)有的babyDAO contract{}來更好地理解這些攻擊為什么會發(fā)生。

首先,我們需要理解什么是256單位制。一個256單位制是由256個字節(jié)組成。以太坊的虛擬機是使用256字節(jié)來完成的。因為以太坊虛擬機受限于256字節(jié)的大小,所以數(shù)字的范圍是0到4,294,967,295 (22??)。如果我們超過這個范圍,那么數(shù)字就會重置到范圍的最底部(22?? + 1 = 0)。如果我們低于這個范圍,這個數(shù)字就會重置到這個范圍的頂端(0–1= 22??)。

當(dāng)我們從零中減去大于零的數(shù),就會發(fā)生下溢攻擊,導(dǎo)致一個新的22??數(shù)集?,F(xiàn)在,如果攻擊者的余額發(fā)生了下溢,那么這部分余額就會更新,從而導(dǎo)致整個資金被盜。

攻擊流程

攻擊者通過發(fā)出1Wei到目標(biāo)合約,來啟動攻擊。

合約認(rèn)證發(fā)出資金的人

隨后調(diào)用1Wei的提現(xiàn)函數(shù)

合約會從發(fā)送者的賬戶扣除的1Wei,現(xiàn)在賬戶余額又是零

因為目標(biāo)合約將以太幣發(fā)給攻擊者,攻擊者的退回函數(shù)被處罰,所以提現(xiàn)函數(shù)又被調(diào)用。

提現(xiàn)1Wei的事件被記錄

攻擊者合約的余額就會更新兩次,第一次是到零,第二次是到-1。

攻擊者的余額回置到22??

攻擊者通過提現(xiàn)目標(biāo)合約的所有資金,從而完成整個攻擊

代碼

/*donate 1 wei, withdraw 1 wei*/

function attack() {

dao.donate.value(1)(this);

dao.withdraw(1);

/*fallback function, results in 0–1 = 2**256 */

function() {

if (performAttack) {

performAttack = false;

dao.withdraw(1);

/*extract balance from smart contract*/

function getJackpot() {

dao.withdraw(dao.balance);

owner.send(this.balance);

解決方案

為了防止受害人陷入下溢攻擊,最好的方法是看更新的狀態(tài)是否在字節(jié)范圍內(nèi)。我們可以添加參數(shù)來檢查我們的代碼,作為最后一層保護(hù)。函數(shù)withdraw()的首行代碼是為了檢查是否有足夠的資金,第二行是為了檢查超溢,第三個是檢查下溢。

contract babysDAO{

....

/*withdrawal ether from contract*/

function withdraw(uint amount) {

if (credit[msg.sender] >= amount

&& credit[msg.sender] + amount >= credit[msg.sender]

&& credit[msg.sender] - amount <= credit[msg.sender]) {

credit[msg.sender] -= amount;

msg.sender.send(amount)();

需要注意,就像我們之前討論,我們上面的代碼是在發(fā)出資金之前更新用戶的余額。

攻擊#3:跨函數(shù)競爭條件

最后要說的,就是跨函數(shù)競爭攻擊。就像在重放攻擊中所說,DAO合約不能正確的更新合約狀態(tài),并且可以讓資金被盜竊。DAO問題和外部調(diào)用中的部分原因是跨函數(shù)競爭條件攻擊的潛在原因。雖然以太坊中所有的轉(zhuǎn)賬是線性發(fā)生(一個在另一個后面), 外部調(diào)用(另一個合約或者地址的調(diào)用)如果沒有被合理管理,就會成為災(zāi)難的導(dǎo)火線。在現(xiàn)實世界中,他們是完全可以避免的。當(dāng)兩個函數(shù)被調(diào)用并且分享同個狀態(tài),跨函數(shù)競爭條件攻擊就會發(fā)生。這個合約就會想到,現(xiàn)在有兩個合約狀態(tài)存在,但是現(xiàn)實是只有一個真正的合約狀態(tài)存在。我們不能同時獲得X = 3和X = 4這兩種結(jié)果。 讓我們用一個例子來說明這個內(nèi)容。

攻擊和代碼

contract crossFunctionRace{

mapping (address => uint) private userBalances;

/* uses userBalances to transfer funds */

function transfer(address to, uint amount) {

if (userBalances[msg.sender] >= amount) {

userBalances[to] += amount;

userBalances[msg.sender] -= amount;

/* uses userBalances to withdraw funds */

function withdrawalBalance() public {

uint amountToWithdraw = userBalances[msg.sender];

require(msg.sender.send(amountToWithdraw)());

userBalances[msg.sender] = 0;

上面的合約有2個功能 – 一個是可以轉(zhuǎn)移資金,另一個是提現(xiàn)資金。我們假設(shè)攻擊者調(diào)用了函數(shù)transfer(),然后同時使用外部調(diào)用函數(shù)withdrawalBalance()。userBalance[msg.sender]的狀態(tài)通過2個不同的方向被抽出。用戶的余額還沒有被設(shè)為0,但是盡管資金已經(jīng)被提取,攻擊者也能夠轉(zhuǎn)移資金。這樣情況下,合約可以讓攻擊者使用雙花,這也是區(qū)塊鏈技術(shù)想要解決的問題之一。

注意:如果有函數(shù)分享狀態(tài),跨函數(shù)競爭條件攻擊就會在多個合約中發(fā)生。

-在調(diào)用外部函數(shù)之前,應(yīng)該完成所有的內(nèi)部工作

-避免發(fā)生外部調(diào)用

-在不可避免地時候,使用外部函數(shù)“不可信”

-在外部調(diào)用不可避免的情況下,使用互斥

根據(jù)下面的合約,我們可以看到一個例子1) 在完成外部調(diào)用之前,完成內(nèi)部工作。2)將所有外部調(diào)用都設(shè)為“不可信”。我們的合約會讓資金發(fā)送到一個地址,并且允許用戶一次性將資金存入合同。

contract crossFunctionRace{

mapping (address => uint) private userBalances;

mapping (address => uint) private reward;

mapping (address => bool) private claimedReward;

//makes external call, need to mark as untrusted

function untrustedWithdraw(address recipient) public {

uint amountWithdraw = userBalances[recipient];

reward[recipient] = 0;

require(recipient.call.value(amountWithdraw)());

//untrusted because withdraw is called, an external call

function untrustedGetReward(address recipient) public {

//check that reward hasn’t already been claimed

require(!claimedReward[recipient]);

//internal work first (claimedReward and assigning reward)

claimedReward = true;

reward[recipient] += 100;

untrustedWithdraw(recipient);

我們可以看出,這個合約的首個函數(shù)在發(fā)送資金到用戶的合約/地址的時候,就會發(fā)生外部調(diào)用。同樣地,獎勵函數(shù)在發(fā)送一次性獎勵的時候,也會使用提現(xiàn)函數(shù),因為這也是不可信的。同樣重要地是,合約需要執(zhí)行所有內(nèi)部工作。就好像重入攻擊,函數(shù)untrustedGetReward()會在允許提現(xiàn)之前,讓用戶獲得一次性的獎勵,從而防止跨函數(shù)競爭條件攻擊。

在真實世界,智能合約不需要依賴于外部調(diào)用。事實上,外部調(diào)用在很多情況下,在工作環(huán)境中都幾乎不可能發(fā)生的。由于這個原因,使用互斥體來“定”一些狀態(tài),并且讓擁有者有能力去改變狀態(tài),可以幫助防止這類災(zāi)難。雖然互斥體非常有效,但是當(dāng)用于多個合約的時候,都會變的很棘手。如果你使用互斥體來防止這類攻擊,你需要很仔細(xì)地確保沒有其他方法來鎖定,或者永遠(yuǎn)不會釋放。如果使用互斥體的方法,在寫入智能合約的時候,你需要保證你完全理解潛在的危險。

contract mutexExample{

mapping (address => uint) private balances;

bool private lockBalances;

function deposit() payable public returns (bool) {

/*check if lockBalances is unlocked before proceeding*/

require(!lockBalances);

/*lock, execute, unlock */

lockBalances = true;

balances[msg.sender] += msg.value;

lockBalances = false;

return true;

function withdraw(uint amount) payable public returns (bool) {

/*check if lockBalances is unlocked before proceeding*/

require(!lockBalances && amount > 0 && balances[msg.sender]

>= amount);

/*lock, execute, unlock*/

lockBalances = true;

if (msg.sender.call(amount)()) {

balances[msg.sender] -= amount;

lockBalances = false;

return true;

以上,我們可以看到合約mutexExample()會有私人鎖定狀態(tài),來實行deposit()函數(shù)功能和withdraw()函數(shù)。鎖定會防止用戶能夠在所有的初步調(diào)用完成之前,成功完成withdraw()調(diào)用,可以防止任何種類的跨函數(shù)競爭條件攻擊。

最后的結(jié)果

力量越大,責(zé)任越大。雖然區(qū)塊鏈和智能合約技術(shù)每天都在革新,但是風(fēng)險依然很高。攻擊者從沒有放棄去尋找機會來攻擊這些合約。這取決于我們來保證,我們可以從之前項目的問題中學(xué)習(xí)經(jīng)驗,來讓我們獲得成長。希望通過這篇文章,以及其他系列文章,你可以更明白智能合約攻擊。

本站聲明: 本文章由作者或相關(guān)機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: 驅(qū)動電源

在工業(yè)自動化蓬勃發(fā)展的當(dāng)下,工業(yè)電機作為核心動力設(shè)備,其驅(qū)動電源的性能直接關(guān)系到整個系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動勢抑制與過流保護(hù)是驅(qū)動電源設(shè)計中至關(guān)重要的兩個環(huán)節(jié),集成化方案的設(shè)計成為提升電機驅(qū)動性能的關(guān)鍵。

關(guān)鍵字: 工業(yè)電機 驅(qū)動電源

LED 驅(qū)動電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個照明設(shè)備的使用壽命。然而,在實際應(yīng)用中,LED 驅(qū)動電源易損壞的問題卻十分常見,不僅增加了維護(hù)成本,還影響了用戶體驗。要解決這一問題,需從設(shè)計、生...

關(guān)鍵字: 驅(qū)動電源 照明系統(tǒng) 散熱

根據(jù)LED驅(qū)動電源的公式,電感內(nèi)電流波動大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關(guān)鍵字: LED 設(shè)計 驅(qū)動電源

電動汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產(chǎn)業(yè)的重要發(fā)展方向。電動汽車的核心技術(shù)之一是電機驅(qū)動控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機驅(qū)動系統(tǒng)中的關(guān)鍵元件,其性能直接影響到電動汽車的動力性能和...

關(guān)鍵字: 電動汽車 新能源 驅(qū)動電源

在現(xiàn)代城市建設(shè)中,街道及停車場照明作為基礎(chǔ)設(shè)施的重要組成部分,其質(zhì)量和效率直接關(guān)系到城市的公共安全、居民生活質(zhì)量和能源利用效率。隨著科技的進(jìn)步,高亮度白光發(fā)光二極管(LED)因其獨特的優(yōu)勢逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關(guān)鍵字: 發(fā)光二極管 驅(qū)動電源 LED

LED通用照明設(shè)計工程師會遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關(guān)鍵字: LED 驅(qū)動電源 功率因數(shù)校正

在LED照明技術(shù)日益普及的今天,LED驅(qū)動電源的電磁干擾(EMI)問題成為了一個不可忽視的挑戰(zhàn)。電磁干擾不僅會影響LED燈具的正常工作,還可能對周圍電子設(shè)備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關(guān)鍵字: LED照明技術(shù) 電磁干擾 驅(qū)動電源

開關(guān)電源具有效率高的特性,而且開關(guān)電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機重量也有所下降,所以,現(xiàn)在的LED驅(qū)動電源

關(guān)鍵字: LED 驅(qū)動電源 開關(guān)電源

LED驅(qū)動電源是把電源供應(yīng)轉(zhuǎn)換為特定的電壓電流以驅(qū)動LED發(fā)光的電壓轉(zhuǎn)換器,通常情況下:LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: LED 隧道燈 驅(qū)動電源
關(guān)閉