9

I've created a method to allow my project EditVideoBot to be 'decentralised', where rather than the program processing and uploading all video editing requests on my own central server, users can volunteer to run this program on their computer and take some of the load off my server.

I'd like to be able to start distributing the program, but I have one major concern:

In order for the program to upload the final edited video to Twitter, it needs my Twitter API keys. Obviously, I need a way to encrypt the keys so they're not accessible to the user running the program (otherwise they have full access to my account).

The bot is programmed in Python. I don't really know where to begin with keeping the keys secure if the program is running on another computer.

Edit: If there was a method with the Twitter API to generate keys that have restricted priveliges (e.g. they can only access the media-upload endpoint but not any other endpoints) that would be the best method. (like with Cloudflare's API). Then, they'd forward the returned media-id to my server where it has full access and posts the tweet attaching the media ID. I don't think they have that capability though, so another method is needed.

pigeonburger
  • 671
  • 1
  • 4
  • 12
  • 18
    I think your best bet is to expose an API in your server that different bot programs send videos to post to Twitter. – Limit Mar 23 '21 at 04:29
  • 10
    With regard to your edit, even if Twitter allowed this, you wouldn't want to publish the keys to be able to upload arbitrary media to your account. Someone would inevitably abuse them in a way that would get your account banned. – Zach Lipton Mar 24 '21 at 03:59
  • 4
    Rule #1: any program running on a computer, _cannot_ hide anything from the rightful owner of that computer. Rule #2: You _should not_ take a key issued on your name and then publish it to someone else. – inquisitive Mar 24 '21 at 07:56

2 Answers2

41

As specified, the problem is completely impossible. You can not, and should not attempt to, make a program - much less a script - do something its user can't see. There are many ways the attacker could break this. They could just read and analyze your python scripts (even if compiled, .pyc is easy to decompile). They could debug the program as it runs. They could intercept the network requests it makes to Twitter and pull the key out of there. They could replace the Python HTTPS library with one that wraps the official API and also logs a copy of the requests and responses to plain text. They could load your program as a library of another python program and programmatically examine its contents... Seriously, people keep asking about this and it just can not be done.

As @Limit's comment says, your best bet is to expose an API from your server, and have your script call that with whatever it wants to put on Twitter. You can then validate the message before posting it, rate-limit each client's uploads, prevent abuse of the account such as deleting tweets or using DMs, and revoke third-party access to the account entirely just by disabling the endpoint on your server. This isn't enough to totally prevent abuse, but it'll do a lot better than any method of trying to hide secrets in a Python script.

Another option is to use unique Twitter accounts per user. Either require the users to create/supply their own account (which your server then learns about and monitors for uploads, perhaps with specific tags or mentions), or automatically create one (well, as automatically as Twitter will let you get away with) for each node and don't use them for anything else (the user running the node would still have full access to the account in each case, but not to any other accounts).

Or you could just have the nodes send the resulting videos to your server, and your server decides what to do with them. This is basically the same as the first viable approach, except the new endpoint is not "send video here to upload to Twitter", it's just "send video here when done" and you-the-server-owner decide what to do with it then.

CBHacking
  • 40,303
  • 3
  • 74
  • 98
  • 4
    Unique Twitter accounts would probably not end up too well. I think the best option right now is to just have the video sent to my server, where it gets uploaded from so it can still maintain sole access to the account. I appreciate the detailed answer. – pigeonburger Mar 23 '21 at 20:32
  • 1
    I get where you're coming from, but although it may be impractical, it's strictly speaking not impossible. Homomorphic encryption and Intel SGX come to mind. – Fax Mar 24 '21 at 15:58
  • Hey CBHacking, one question, because Twitter is using HTTPS it would be impossible to intercept the network if you are using a custom HTTPS package. won't it? – Vinay Sheoran Mar 29 '21 at 20:34
  • because for an attacker to decrypt the intercepted data, he/she needs to add/replace CA certificate for the HTTPS library, use the library that doesn't allow changing CA, or write your own. – Vinay Sheoran Mar 29 '21 at 20:40
  • 1
    @VinaySheoran What you're describing is more commonly known as "pinning" a certificate (or public key), and there are legit reasons to do it, but it doesn't actually solve the problem here. *EVEN* if you manage to prevent decryption of the network traffic, the attacker can still decompile your app to find its secrets. But getting around pinning is easy. You could find the place in the app where Twitter's key is pinned, and replace it. You could replace the whole library with a different one. You could patch the library to always return true for every cert validity check. Tons of options. – CBHacking Mar 30 '21 at 07:37
10

Obviously, I need a way to encrypt they keys so they're not accessible to the user running the program

Obviously, this is impossible.

Keys are just data. Software is just data. Everything is just data, and if the data is in someone else’s computer, you cannot prevent them from accessing the data! (It is just like writing something on a piece of paper and handing it to someone else – you cannot prevent them from reading it! The only exception is if you encrypt the data and do not give them access to the decryption key – but that will not help you here.)

The above discussion implies that you need to trust the user with the key. You cannot avoid this trust problem, but you may be able to shift it to a different target. Some hardware, such as Intel CPUs that support Software Guard Extensions, allows its owner to effectively hand control of the hardware back to the manufacturer, at least as far as the so-called “enclave” is concerned. If …

  1. you can convince the user to run your code in a supported enclave;
  2. you trust the manufacturer to keep their private key secret (which is a very big “if”, especially if the same key is used in every copy of the hardware);
  3. you use the corresponding public key to verify that the user is in fact using the enclave;
  4. you trust the manufacturer or your code to avoid side channel attacks (which is also a very big “if”, given that recent CPUs – including some designed with side channel attacks in mind – already have many known attacks); and
  5. you trust the manufacturer to make the enclave immune to any other software or hardware-based attacks (which is also a very big “if” given that the user has physical control over the hardware)

… then you shift the trust problem from the user to the manufacturer. In spite of all these caveats, some people seem to think enclaves are useful; technically, this is an answer to the question posed. But there are so many issues with it that it does not seem like a real answer.

In any case, your overall aim of creating a distributed bot that can post to your account sounds like a disaster waiting to happen. If you do not trust the volunteers to refrain from accessing your API keys, how can you trust them to, say, refrain from returning the kind of videos you do not want to be associated with? One answer is to use an enclave, with all of the caveats discussed above.

users can volunteer to run this program on their computer and take some of the load off my server

There might be an easier way of making this happen, which was hinted at in the EditVideoBot FAQ:

Where can I find the source code of the bot?

You can't, not yet at least. The main reason I haven't made it open source is because I don't know where I want to take this project in the future. I predict that I'll eventually make it open source, however.

Just do it. It is good for spreading the computing load among many computers. It is good for spreading the development effort among many developers. Most relevant to this site, it is good for security.

Brian Drake
  • 332
  • 1
  • 8
  • 1
    As long as the keys are not distributed as part of the source, of course. – GalacticCowboy Mar 23 '21 at 19:24
  • As long as you aren't using SGX, a very heavy-handed technology that I hope never gets mainstream adoption. – user253751 Mar 23 '21 at 20:28
  • 3
    @user253751 Nah, that doesn't work either. To use Twitter's API, the data needs to leave the enclave. (Also the enclave is only secure against people who aren't trying to get the data out.) – wizzwizz4 Mar 23 '21 at 21:16
  • @wizzwizz4 well all communication with their API is via TLS, presumably. Enclaves are not secure against some variants of Spectre, but imagine Intel fixes that... – user253751 Mar 23 '21 at 21:20
  • 4
    @user253751 You must have a vivid imagination. You're giving the keys to the user, on the user's computer, and expecting them to remain hidden. _Who says they have to be put in the enclave in the first place?_ All that has to happen is for _anyone_ to exfiltrate _Intel's_ key. – wizzwizz4 Mar 23 '21 at 21:29
  • @wizzwizz4 The server wouldn't give you the key (maybe even the code) until you present your certificate signed by your CPU's certificate which is signed by Intel. That's what's scary about SGX. Yes, someone could theoretically leak Intel's key at which point your users have to buy a new CPU with a new certificate signed by Intel's key. And of course if you get caught etching your CPU with acid to view the transistors and see the key and sharing that key online, they'll revoke the key. – user253751 Mar 24 '21 at 09:45
  • 1
    +1 for the notion that you also have to trust the users to actually do the requested edit and not return something else instead. – AVee Mar 24 '21 at 13:21
  • 1
    I added sections about enclaves in response to the comments above. But I have little knowledge of them. In particular, I wonder if the manufacturers really use the same key in each copy of the hardware. That does not seem reasonable. – Brian Drake Mar 24 '21 at 14:49
  • @BrianDrake I believe each CPU has its own key and a signature from Intel's key. – user253751 Mar 24 '21 at 15:18
  • 1
    @wizzwizz4 You're giving the encrypted keys to the user, which is decrypted in the CPU. You're right that some data needs to leave the enclave, but it could be a single-use token. Doesn't stop the user from uploading a different video with said token though. – Fax Mar 24 '21 at 16:12