起因#
推友がツイートを投稿しているのを見て、あるスマートコントラクトの深刻な脆弱性について言及していました。
流程分析#
攻撃者はコントラクトの VOTEToken()
関数を大量に呼び出し、無から大量の VOTETRUMP
トークンを生成し、その後 Uinswap
を通じて ETH
に交換し、アービトラージを実現しました。
漏洞分析#
最近、Solidity 残酷共学 (DeFiHackLabs x WTF Academy)に参加しており、コースの第 11 講:構造体と修飾子には次のような説明があります:
注意:構造体は異なる Solidity バージョンでの構文が一貫していません。Solidity 0.4.22 以前では、構造体は constructor を使用せず、コントラクト名と同名の関数を構造体として使用していました。この古い書き方は、開発者が記述時に誤りを犯しやすく(例えば、コントラクト名が Parents の場合、構造体名を parents と書く)、構造体が普通の関数になってしまい、脆弱性を引き起こす可能性があります。そのため、0.4.22 バージョン以降は新しい constructor の書き方が採用されました。
コントラクトコードを確認すると、使用されている Solidity
バージョンは ^0.4.11
で、0.4.22
よりも低いことがわかります。これは、このコントラクトの構造体定義が旧版のルールに従っていることを意味します。
構造体の誤り:コントラクト名は VeritaseumToken ですが、実際に定義されている構造体名は VOTEToken です。両者が一致しないため、VOTEToken 関数は構造体として認識されず、普通の公共関数となってしまいました。さらに、関数は可視性修飾子を使用していないため、誰でも自由に呼び出すことができ、その関数を呼び出すことで自分のアカウントの VOTETRUMP トークン残高をトークンの最大供給量まで増やすことができます。
この設計ミスは攻撃者に条件を提供し、彼らは VOTEToken () 関数を呼び出すことで大量の VOTETRUMP トークンを鋳造し、最終的に分散型取引所でアービトラージを行いました。
修復漏洞#
- Solidity バージョンのアップグレード:まず、Solidity バージョンを 0.4.22 以上にアップグレードすることをお勧めします。これにより、constructor キーワードを使用して構造体を定義できます。これにより、構造体名のスペルミスによる脆弱性を回避できます。
- 構造体定義の修正:コントラクトコードのバージョンをアップグレードできない場合、構造体名がコントラクト名と一致することを確認する必要があります。このケースでは、VOTEToken () を VeritaseumToken () に変更する必要があります。
- 適切な権限管理の追加:古い構造体定義を使用している場合でも、重要な関数には適切な権限管理(例えば onlyOwner 修飾子)を追加し、任意のユーザーがこれらの関数を呼び出してトークンを鋳造することを防ぐ必要があります。
警示#
この脆弱性は、低バージョンの Solidity を使用してコントラクトを書く際には、構造体名の命名規則を厳守し、スペルミスによる深刻なセキュリティ問題を避ける必要があることを思い出させます。また、トークンの鋳造、移転などの重要な操作に関与する関数には、権限管理メカニズムを導入して、悪意のあるユーザーがコントラクトの脆弱性を悪用するのを防ぐ必要があります。
さらに、コントラクトを設計する際には、最新の安定版 Solidity を使用することをお勧めします。これにより、新機能を利用し、既知の脆弱性を修正し、コントラクトのセキュリティを向上させることができます。