Неправильное управление разрешениями — одна из распространенных проблем безопасности в смарт-контрактах, особенно когда администраторам или определенным учетным записям предоставляются чрезмерные разрешения. Если ключевые функции контракта, такие как передача активов, изменение статуса контракта или обновление логики контракта, могут выполняться по желанию неавторизованными лицами, это создаст серьезную угрозу безопасности. Ниже я приведу пример того, что может произойти, если разрешения не управляются должным образом, и как снизить этот риск посредством правильного проектирования.
Предположим, у нас есть смарт-контракт, который управляет выпуском и передачей цифрового актива. В этом контракте учетной записи администратора предоставляются неограниченные права создавать новые активы и без ограничений передавать их на любую учетную запись.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract MismanagedPermissions {
mapping(address => uint256) public balances;
address public admin;
constructor() {
admin = msg.sender;
}
function mint(address to, uint256 amount) public {
require(msg.sender == admin, "Only admin can mint");
balances[to] += amount;
}
function transfer(address from, address to, uint256 amount) public {
require(balances[from] >= amount, "Insufficient balance");
balances[from] -= amount;
balances[to] += amount;
}
}
В этом контракте функция mint позволяет учетным записям администраторов создавать новые активы без ограничений. Хотя это может показаться разумным разрешением, но если безопасность учетной записи администратора скомпрометирована или разработчик контракта по ошибке устанавливает ненадежный адрес в качестве администратора, это открывает дверь для злоумышленников.
Злоумышленник может получить закрытый ключ учетной записи администратора различными способами, либо разработчик контракта может случайно установить вредоносный адрес в качестве администратора. Как только злоумышленник получит контроль над учетной записью администратора, он сможет по своему желанию вызвать функцию mint, создать неограниченное количество активов и перенести их на свою учетную запись, тем самым получая незаконную прибыль.
MismanagedPermissions contract = new MismanagedPermissions();
contract.mint(msg.sender, 1000000); // Злоумышленники вычеканили большое количество активов
Чтобы предотвратить проблемы безопасности, вызванные неправильным управлением разрешениями, мы можем принять следующие меры:
Ниже приведен пример улучшенного контракта, в который добавлены ограничения разрешений и механизм мультиподписи:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract SafePermissions {
mapping(address => uint256) public balances;
mapping(address => bool) public admins;
uint256 public dailyMintLimit;
uint256 public dailyMinted;
constructor(uint256 _dailyMintLimit) {
dailyMintLimit = _dailyMintLimit;
admins[msg.sender] = true; // Первый участник
}
modifier onlyAdmin() {
require(admins[msg.sender], "Only admin can perform this action");
_;
}
function mint(address to, uint256 amount) public onlyAdmin {
require(dailyMinted + amount <= dailyMintLimit, "Daily mint limit exceeded");
balances[to] += amount;
dailyMinted += amount;
}
function addAdmin(address newAdmin) public onlyAdmin {
admins[newAdmin] = true;
}
function removeAdmin(address adminToRemove) public onlyAdmin {
delete admins[adminToRemove];
}
}
В этом улучшенном контракте мы представили концепцию нескольких администраторов и установили ежедневное ограничение на количество создаваемых активов, чтобы предотвратить неограниченное создание активов. В то же время мы также предоставляем возможность добавлять и удалять администраторов, для чего требуются разрешения существующего администратора.
Благодаря этим улучшениям мы можем значительно повысить безопасность контрактов и снизить риск неправильного управления разрешениями. В практических приложениях необходимо дальнейшее совершенствование механизмов управления разрешениями и контроля безопасности на основе конкретных бизнес-сценариев и требований безопасности.