While developing my EOS account exchange www.eosnameswaps.com, it was brought to my attention, by Todd Fleming, that there was a possible attack vector on my contract using the eosio.msig system contract. I have decided to demonstrate this attack, so that other developers in the EOSIO community can be aware of it, and implement counter measures where necessary.
First, we start with a test account, user1, with the following permissions
Next, user2 proposes a multisig action takemeback that will, at a later date, restore the original owner permission to user1
We can confirm this proposal is live by using the multisig review action
Now, user1 approves this proposal, but does not yet execute it. The updateauth transaction is now fully approved, and does not require any further signing by user1, even if user1’s permissions change!
We list the user1 account for sale on www.eosnameswaps.com which automatically changes the user1’s owner/active keys to the exchange contract
The exchange contract now has full ownership rights over the user1 account, and is able to change them to a new owner, once user1’s account is bought. At this stage, the original owner of user1, or anyone else for that matter, should have no ability to do anything with the account. However, if user2 now executes the multisig proposal,
We see that the original owner permission is restored! If an account had been sold, the original owner could take it back and keep the money he made from the sale; a profitable venture.
Todd Fleming suggested a relatively simple method for mitigating the above mentioned threat, that involves checking the eosio.msig tables for any active proposals from the account being sold. Initially I believed this would work, but I have realized that if the permissions proposal is made by a different account, user2 as shown above, to the one being sold, I have no easy way to check the tables. There does not seem to be any simple methods for determining whether there are any active msig proposals that affect an account, that were not proposed by that account.
My best idea at the moment is to use a combination of EOS-JS and block explorers to screen an account for any msig proposals. This would need to be done off-contract though, and may be unworkable if there is a delay in the block explorer; a script can easily execute all of the necessary actions within a few seconds.
I have demonstrated a viable attack vector using the eosio.msig contract. I don’t believe this affects many of the contracts already deployed, as there is rarely a need for a contract to the change account permissions. Having said that, it would be pretty easy for a rogue contract to ‘infect’ an account using msig if it were given active permissions, and then siphon off EOS over a period of time; the user could change their keys, but it wouldn’t help.
Is this a bug in the eosio.msig contract? No, I don’t think so. I am sure Block.One was aware of potential edge-cases when they designed the contract to carry transaction approvals into the future, potentially overriding later permission changes. There may be changes that could be made to the eosio.msig contract to mitigate security issues, but I will leave that to others to comment on.
I am personally very excited with the possibilities of the eosio.msig contract, and I look forward to developing new dApps that utilize it. It is thanks to a strong EOS community that I was able to build my dApp in the first place, and then secure it against potential threats.