Secret Vault on Aptos

First Flight #46
Beginner FriendlyWallet
100 EXP
View results
Submission Details
Severity: high
Valid

H-1 Storage variables on-chain are publicly visible so anyone can view the secret

Description

Storage variables on blockchain networks are inherently public and accessible to all network participants, rendering any variable designated as "secret" effectively non-confidential. So when an owner sets a secret then anyone can access the storage and get the secret by querying for example the storage per transaction hash.

Risk

High

Likelihood: High

  • Reason: Any user that knows how to read the storage of the chain, they can access the secret.

Impact: High

  • Reason: Severe disruption of protocol functionality since the secret that should be accessible only by the owner is actually accessible by anyone.

Proof of Concept

The below test case shows that anyone can read the secret directly from the blockchain.

  1. Start a local Aptos node in a separate terminal

aptos node run-local-testnet --with-faucet
  1. Initialize an account

aptos init --profile local --network local

Returns

Account: `12936a4eafcbd1e525464b55f12a336b6551d758a0f128f9c2752aa84accb618` created
  1. In the Move.toml file replace the secret_vault entry under [dev-addresses] with the address found in account (from .aptos/config.yaml). It is the same address created in previous step.

  2. Deploy in --dev

aptos move publish --profile local --dev

it should return similar information as below:

{
"Result": {
"transaction_hash": "0xe2a8e1f421ca790ea7d42a86c1b0091171e12b8b7aad16d1c46f2ab4648ac8be",
"gas_used": 2090,
"gas_unit_price": 100,
"sender": "12936a4eafcbd1e525464b55f12a336b6551d758a0f128f9c2752aa84accb618",
"sequence_number": 0,
"replay_protector": {
"SequenceNumber": 0
},
"success": true,
"timestamp_us": 1755584419589578,
"version": 14640,
"vm_status": "Executed successfully"
}
}
  1. Submit a transaction to set a secret

aptos move run --function-id 12936a4eafcbd1e525464b55f12a336b6551d758a0f128f9c2752aa84accb618::vault::set_secret --args hex:68656c6c6f --url http://127.0.0.1:8080 --private-key PRIVATE_KEY_OF_ACCOUNT_12936a4eafcbd1e525464b55f12a336b6551d758a0f128f9c2752aa84accb618

it returns a transaction hash

{
"Result": {
"transaction_hash": "0x68d3a8ec3185fd5f3dc50ae238d956e2fe3473e9f9bf0719260580f5d5a3c71b",
"gas_used": 437,
"gas_unit_price": 100,
"sender": "12936a4eafcbd1e525464b55f12a336b6551d758a0f128f9c2752aa84accb618",
"sequence_number": 1,
"replay_protector": {
"SequenceNumber": 1
},
"success": true,
"timestamp_us": 1755584793062672,
"version": 14937,
"vm_status": "Executed successfully"
}
}
  1. Get transaction by hash

curl --request GET \
--url http://127.0.0.1:8080/v1/transactions/by_hash/0x68d3a8ec3185fd5f3dc50ae238d956e2fe3473e9f9bf0719260580f5d5a3c71b \
--header 'Accept: application/json, application/x-bcs'

Note: Referred to the documentation provided by the local running node, http://127.0.0.1:8080/v1/spec#/operations/get_transaction_by_hash, to see the syntax of this request.

Among other info, it returns the hex value we set as the secret, 68656c6c6f, which proves that anyone can access the secret with a get request

...
...
vault::set_secret",
"type_arguments":[],
"arguments":["0x68656c6c6f"],
"type":"entry_function_payload"
...
...

Recommended Mitigation

The overall architecture of the module should be rethought. One could encrypt the secret off-chain, and then store the encrypted secret on-chain. This would require the user to remember a password off-chain to decrypt the secret.

Updates

Lead Judging Commences

bube Lead Judge 15 days ago
Submission Judgement Published
Validated
Assigned finding tags:

Anyone can see the `secret` on chain

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.