Solidityで開発されたスマートコントラクトがさまざまな既知および未知の攻撃を受けやすいのと同様に、小さな抜け穴が(さまざまな規模の)経済的損失につながることを確認しました。 悪用者はバグや抜け穴を利用してスマートコントラクトを覗き込み、それらを操作して攻撃を実行します。 ここでは、Solidityプログラミング言語で一般的に発生する上位5つのエラーの包括的なリストを示します。
QuillAuditsでは、適応方法論に従ってすべてのハッキングの要点を把握し、潜在的な脅威を回避するために将来のスマートコントラクトにその学習を実装します。
Solidityプログラミング言語のエラー
1. 未チェックの外線通話
この問題は、最も一般的に観察されるSolidityの落とし穴のひとつであるため、そもそもこの問題を取り上げています。 一般的に、外部アカウントにイーサリアムを送信するには、 転送() 関数。 これとは別に、外部呼び出しを行うために最も広く使用されているXNUMXつの関数は次のとおりです。 コール(), 送信()、ここでは主に コール() 関数は、開発者がさまざまな外部呼び出しを実行するために広く使用されています。
しかし、 コール() & 送信() 関数は、呼び出しが成功したかどうかを指定するブール値を返します。 したがって、この場合、関数のいずれかが コール() or 送信() タスクの実行に失敗すると、元に戻ります 偽。 したがって、開発者が戻り値をクロスチェックしないと、落とし穴になります。
脆弱性
以下の例を検討してください。
契約ロト{
boolpublic payedOut = false;
パブリックウィナーに対応します。
uintpublic winAmount;
//…ここに追加機能
関数sendToWinner()public {
require(!payedOut);
winer.send(winAmount);
payedOut = true;
}
関数withdrawLeftOver()public {
require(payedOut);
msg.sender.send(this.balance);
}
}
上記のロトのような契約では、 勝者 受け取り 勝ち額 エーテルの残り物を少し残して、外部のエージェントから引き出します。
ここで、契約の落とし穴は[11]行目にあります。 送信 応答の相互検証なしで使用されます。 上記の例では、 勝者 トランザクションが失敗した場合(ガスの不足、または意図的にフォールバック機能を投入する契約の場合)、承認します 支払い済み に設定する true エーテルの取引が成功したかどうかに関係なく。 この場合、悪用者は誰でも撤回できます 勝者 経由の賞金 取り消すLeftOver 機能。
QuillAuditのアプローチ
社内の開発者チームは、以下を使用してこのバグに取り組んでいます。 [転送] 代わりに機能 [送信] 外部トランザクションが元に戻ると[転送]が元に戻るため、機能します。 また、[send]を使用している場合は、常に戻り値をクロスチェックしてください。
私たちが従う強力なアプローチのXNUMXつは、[撤退パターン]を利用することです。 ここでは、外部送信機能を残りのコードベースから論理的に分離し、エンドユーザーが撤回関数を呼び出すため、失敗する可能性のあるトランザクションの負担をエンドユーザーに負わせます。
2.再入可能
イーサリアムスマートコントラクトは、他の外部コントラクトからのコードを呼び出して利用します。これを実行するには、コントラクトは外部コールを送信する必要があります。 これらの外部呼び出しは脆弱であり、攻撃を受けやすいです。DAOハッキングの場合、このような攻撃のXNUMXつが最近発生しました。
脆弱性
契約が未知のアドレスにエーテルを送信すると、攻撃者はそのような攻撃を実行します。 この場合、攻撃者はフォールバック機能で悪意のあるコードを所有する外部アドレスでコントラクトを作成でき、コントラクトがこのアドレスにエーテルを送信すると、この悪意のあるコードが呼び出されます。
事実: 「再入可能性」という用語は、外部の悪意のあるコントラクトが脆弱なコントラクトを介して関数を呼び出し、コード実行パスが「再入可能」するという事実から造られました。
以下の例を考えてみましょう。これは、預金者が1週間にXNUMXつのイーサリアムのみを引き出すことができるイーサリアムボールトです。
契約EtherStore {
uint256 public withdrawalLimit = 1イーサリアム;
マッピング(アドレス=> uint256)public lastWithdrawTime;
マッピング(アドレス=> uint256)パブリックバランス;
関数depositFunds()外部支払い可能{
バランス[msg.sender] + = msg.value;
}
関数withdrawFunds(uint256 _weiToWithdraw)public {
require(balances [msg.sender]> = _weiToWithdraw);
//引き出しを制限します
require(_weiToWithdraw <= withdrawalLimit);
//撤回できる時間を制限する
require(now> = lastWithdrawTime [msg.sender] + 1週間);
require(msg.sender.call.value(_weiToWithdraw)());
バランス[msg.sender]-= _ weiToWithdraw;
lastWithdrawTime [msg.sender] =今;
}
}
上記の契約では、[depositFunds]と[withdrawFunds]の1つのパブリック関数があります。 [depositFunds]は送信者の残高を増やすために使用されますが、[withdrawFunds]は引き出す金額を指定します。 この場合、引き出される量がXNUMXイーサリアム未満であれば成功します。
ここでの落とし穴は、エーテルの移動が行われる[17]行にあります。 攻撃者は、[EtherStores]のコントラクトアドレスを唯一のコンストラクターパラメーターとして悪意のあるコントラクトを作成する可能性があります。 これにより、[etherStore]がパブリック変数になるため、攻撃を受けやすくなります。
QuilllAuditのアプローチ
スマートコントラクトの潜在的な再入可能性の脆弱性を回避するために、さまざまな手法に従います。 一番最初で最良の方法は、エーテルを外部契約に転送するときに組み込みの[転送]関数を使用することです。
次に、契約からエーテルを送信する前に、状態変数のすべてのロジック変更を確実に実行することが重要です。 [EtherStore]の例では、行[18]と[19]を行[17]の前に配置する必要があります。
XNUMX番目の手法は、再入可能な呼び出しを防ぐためにも使用できます。 ミューテックスの導入を通じて。 これは、コードの実行中にコントラクトをロックする状態変数の追加です。
3.デフォルトの可視性
Solidityで使用する関数には可視性指定子があり、それらを呼び出す方法を規定しています。 関数の呼び出しを決定するのは可視性です。 ユーザーによる外部、他の派生契約による、内部のみまたは外部のみ。 可視性指定子の誤った使用がスマートコントラクトに大きな脆弱性を引き起こす可能性があることを見てみましょう。
脆弱性
デフォルトでは、関数の可視性は[public]であるため、外部ユーザーは特定の可視性なしで関数を呼び出すことができます。 このバグは、開発者がプライベートである必要がある(またはコントラクト自体の中で呼び出すことができる)関数の可視性を指定するのを忘れた場合に発生します。 例えば;
契約HashForEther {
関数withdrawWinnings(){
//アドレスの最後の8桁の0進文字がXNUMXの場合に勝者
require(uint32(msg.sender)== 0);
_sendWinnings();
}
関数_sendWinnings(){
msg.sender.transfer(this.balance);
}
}
上記の契約は、単純な住所推測の報奨金ゲームです。 ここでは、関数の可視性が指定されていないことがわかります。特に[_sendWinnings]関数は[public](デフォルト)であるため、任意のアドレスから呼び出して賞金を盗むことができます。
QuillAuditのアプローチ
私たちの社内チームは、常に最良の監査慣行に従う経験豊富な開発者で構成されています。ここでは、関数の可視性を明示的に指定する必要があります。公開する場合でも、言及する必要があります。
4.コンストラクターの使用を保護する
一般に、コンストラクターは特別な関数と呼ばれ、コントラクトの初期化中に重要な特権タスクを実行するために使用されます。 Solidity [v0.4.22]以前は、コンストラクターは、それらを含むコントラクトで使用されていたのと同じ名前を保持していました。 ここで、開発フェーズ中にコントラクト名が変更されたが、コンストラクター名は同じままである場合を考えてみましょう。この抜け穴は、攻撃者にスマートコントラクトへの簡単なエントリを提供することもできます。
脆弱性
コントラクト名が変更されてもコンストラクターの名前が変更されていない場合、重大な結果につながる可能性があります。 例えば:
契約OwnerWallet {
公共の所有者に宛ててください。
//コンストラクタ
function ownerWallet(address _owner)public {
所有者= _owner;
}
// 後退する。 エーテルを集める。
関数()支払い可能{}
関数withdraw()public {
require(msg.sender == owner);
msg.sender.transfer(this.balance);
}
}
上記の契約では、所有者のみが[withdraw]関数を呼び出してetherを引き出すことができることがわかります。 ここでは、コンストラクターの名前がコントラクトとは異なるために脆弱性が発生します(最初の文字が異なります!)。 したがって、エクスプロイトは[ownerWallet]関数を呼び出して自分自身を所有者として承認し、[withdraw]を呼び出すことでコントラクト内のすべてのエーテルを撤回できます。
QuillAuditのアプローチ
Solidityコンパイラのバージョン[0.4.22]に準拠しています。 このバージョンではキーワードが導入されています。 [コンストラクター]これは、コントラクト名と一致する関数の名前を必要とします。
5.Tx.Origin認証
ここで、[Tx.Origin]はSolidityのグローバル変数であり、最初に呼び出しまたはトランザクションを実行したアカウントのアドレスが含まれています。 この変数は認証に使用できません。使用すると、契約がフィッシング攻撃に対して脆弱になるためです。
脆弱性
[tx.origin]変数を介してユーザーを承認するコントラクトは、ユーザーが誤ったコントラクトに対して認証されたアクションを実行するように導く外部攻撃にさらされます。 以下の例を考えてみましょう。
契約フィシャブル{
公共の所有者に宛ててください。
コンストラクター(アドレス_owner){
所有者= _owner;
}
function()external payable {} //エーテルを収集する
function withdrawAll(address _recipient)public {
require(tx.origin == owner);
_recipient.transfer(this.balance);
}
}
ここ[11]行目で、コントラクトは[tx.origin]を使用して[withdrawAll]関数を承認しています。
QuillAuditのアプローチ
通常、スマートコントラクトの承認に[tx.origin]を使用することは避けています。 [tx.origin]の使用は厳密に禁止されているわけではありませんが、いくつかの特定の使用例があります。 [tx.origin]を使用して、外部コントラクトが現在のコントラクトを呼び出すことを拒否できます。これは、[require(tx.origin == msg.sender)]の形式の[require]で実行できます。 これは、コントラクトを通常のコードレスアドレスに制限する現在のコントラクトを呼び出すための中間コントラクトの呼び出しを回避するために行われます。
最終的なまとめ
Solidity言語のXNUMXつの一般的な落とし穴を包括的にカバーしました。 スマートコントラクトを開発する際、設計上不変であることを忘れてはなりません。つまり、一度作成すると、ソースコードにパッチを適用する方法がありません。
これは、展開前に利用可能なセキュリティテストおよび監査ツールを利用することを開発者に大きな課題としてもたらします。
スマートコントラクトに対する潜在的な悪意のある脅威、および上記のリスクの一部を発見することは、監査専門家の社内チームによって非常にユニークで堅牢な方法で実行されます。 QuillAuditsは、セキュリティ調査に最善を尽くして、契約を安全に保つためのすべてのソフトウェアセキュリティプラクティスで契約を最新の状態に保ちます。
QuillHashに連絡する
何年にもわたる業界での存在感により、 クイルハッシュ 世界中にエンタープライズソリューションを提供してきました。 専門家のチームを持つQuillHashは、DeFiエンタープライズを含むさまざまな業界ソリューションを提供する大手ブロックチェーン開発会社です。スマートコントラクト監査で支援が必要な場合は、専門家に連絡してください。 ここで!
その他の更新については、QuillHashをフォローしてください
出典:https://blog.quillhash.com/2021/06/04/top-5-common-errors-in-solidity-programming-language/
- 11
- 利点
- すべて
- 監査
- 認証
- 承認
- BEST
- ブロックチェーン
- バグ
- バグ
- コール
- 例
- 原因となる
- 挑戦する
- コード
- コマンドと
- 会社
- 縮小することはできません。
- 契約
- 電流プローブ
- DAO
- DeFi
- 設計
- Developer
- 開発者
- 開発
- Enterprise
- エーテル
- イーサリアム
- イベント
- 専門家
- ファイナンシャル
- 名
- フォーム
- 無料版
- function
- 未来
- ゲーム
- GAS
- グローバル
- 素晴らしい
- ハック
- こちら
- 認定条件
- HTTPS
- 巨大な
- 含めて
- 産業を変えます
- IT
- 言語
- つながる
- 主要な
- LINE
- リスト
- 一致
- その他
- 所有者
- パッチ
- パターン
- フィッシング詐欺
- フィッシング攻撃
- 処方する
- 現在
- プライベート
- プログラミング
- 公共
- 引き
- 研究
- 応答
- REST
- 安全な
- セキュリティ
- サービス
- セッションに
- 簡単な拡張で
- 小さい
- スマート
- スマート契約
- スマート契約
- So
- ソフトウェア
- 固い
- ソリューション
- 都道府県
- 成功
- テスト
- ソース
- 脅威
- 時間
- top
- トップ5
- トランザクション
- 取引
- us
- users
- 値
- ボールト
- 視認性
- 脆弱性
- 脆弱性
- 脆弱な
- 週間
- 誰
- 以内
- 年