Capture the Token: Hack this canister for 1 ICP

I created a small canister that tests how well the IC can keep a secret. The canister running behind https://6b4pv-sqaaa-aaaah-qaava-cai.raw.ic0.app/ has used the Internet Computer’s random tape to get a random value and keep it in memory. If you find a way to obtain that secret value (or manage guess very well), you can get the one ICP token stored in this account and get bragging rights.

You can read more about this challenge in the README of the repository, which also contains the code of the canister.

Even if you don’t think you can obtain or guess the secret, you might enjoy reading through more of that, as you can learn a lot about the Internet Computer this way; this little project touched upon

  • The random tape
  • Controller-less canisters
  • Certified variables
  • Canister Signatures, and how they can be used to let canisters “hold” ICP (they currently can’t hold them directly
  • Keys, Principals and account numbers

Note that I do not expect this challenge to be solvable! It can only be done if my canister, Motoko or the Internet Computer have a bug, or maybe if node providers collaborate.

Whoever builds the tool that, given the right secret, would indeed unlock that token, already deserves some bragging rights! Maybe I should do a similar challenge with a secret that can be obtained without waiting for a serious bug in Motoko or the Internet Computer…

Enjoy!

(This is a private little project of mine, and not by DFINITY or the ICA or anyone else.)

19 Likes

Worth learning. Thanks

Great challenge, I like this combining hacking and explain.

I have a question:

Is it to say, as long as the http_request interface is implemented, The ‘logical’ canister can integrate front-end functions?

and Internet identity canister also does not have a separate front-end canister, and its front-end assets are also directly integrated into the Internet identity canister?

1 Like

A canister is a canister, there is no technical difference between a “frontend canister” and other canisters. Whenever a canister provides the http_request method you can use it via <cid>.raw.ic0.app. To make it usable with <cid>.ic0.app you also have to add the necessary certification headers. Unfortunately, the specification for both of these features hasn’t made it to the light of the public yet, even though all relevant code (e.g. icx-proxy) has.

6 Likes

Great challenge.

Would like to know how i can call the http_request from the local machine ?

http://localhost:8000/?canisterId=qoctq-giaaa-aaaaa-aaaea-cai&id=qoctq-giaaa-aaaaa-aaaea-cai

Good question, but maybe worth a separate thread on this forum, to keep this one a bit topical?

1 Like

Hope you will explain the answer. I only incremented the failed attempts counter :sweat_smile:

I won’t be able to reveal the answer - this would require a bug to surface, and I don’t know of such a bug yet! :slight_smile:

Could you all work on(or direct me to) the source for the front end asset canister code? It would be interesting to get at the url parsing code that I don’t want to have to rewrite.

1 Like

The foundation and ICA should seriously consider something like this with A LOT more ICP in it. You could fill it with a bunch of cycles and let the foundation be the controller such that when the canister dies it refunds the foundation. (I think that is what happens if I remember correctly).

This tests: the security of the canisters and the security of nodes. If you $100 million sitting on a node it incentivizes someone to crack open the node and start poking around. You don’t have to start that high…you could increase it every week. This would go a good way to showing the community that you are confident in the systems.

3 Likes

Too late, I am not longer the controller of this one. The foundation is free to run their own capture-the-token challenge :slight_smile:

Otherwise I agree, up-ing the stakes here would be interesting and worthwhile. Although I am not sure how much it proves – those running the nodes can trivially get the token out from the node state.

Maybe I should create a second one where someone has to modify the canister state to get the token. This should then be really un-hackable, even with collaboration with individual node providers. And it wouldn’t be hard to do…

1 Like

those running the nodes can trivially get the token out from the node state.

Could we get some transparency on this? I’d rather have it be clear how this happens so no one puts a key with significant value on a node than have it be mysterious and cause egg on the face of the project. I have second hand info from a node runner that “they have no way to get in to the machine”, but I don’t think they are very technical.

I’m guessing a tech-savvy person could plug in a monitor, open a repl, dump the wasm memory, and sift through it looking for key like bits.

2 Likes

I don’t know the details either, I must admit, and also think that more clarity would help here. I said “trivially” above in a abstract sense, not ruling out the existence of ”pragmatic” restrictions that make accessing the state harder in practice.

I had to re-deploy the challenge because of a bug in my code. I updated the post above to point to the new canister.

The “old” canister is still there, and it still holds 1 ICP, but the challenge just got much harder: You now have to somehow change the canister state or code to extract the token (or reverse SHA256). I guess having two challenges isn’t bad after all :slight_smile:

4 Likes

What kind of collaboration is required to achieve this goal? @nomeata
The Random generation of mainnet is around 4 seconds, one of our plans is try to generate 100 random seeds ahead, and use them randomly - we need to evaluate the risk of such plan.

I don’t think I am the right person to ask here, as I don’t know much about the practical hurdles of those running nodes to access the state.

My pessimistic assumption would be that at least one node provider is malicious, and will will leak your data, and I would thus not put any data that must be kept secret onto the Internet Computer.

If you want to run something like a lottery, you really shouldn’t pre-calculate the seed, but only fire the call to raw_rand() off after all bets are in. That should then be safe.

1 Like