[HN Gopher] Show HN: Ots - share a secret via one-time URL
       ___________________________________________________________________
        
       Show HN: Ots - share a secret via one-time URL
        
       Author : slavomirvojacek
       Score  : 64 points
       Date   : 2021-08-09 13:38 UTC (9 hours ago)
        
 (HTM) web link (github.com)
 (TXT) w3m dump (github.com)
        
       | contravariant wrote:
       | Edit: This information is apparently outdated, see discussion
       | below.
       | 
       | > # Why should I trust you with my secrets?
       | 
       | > All secrets are encrypted end-to-end, which means the plaintext
       | values never leave your device. We do not log, track, share, or
       | store the encryption key that protects your secret. You can check
       | the client code to learn more about how we create the encryption
       | key as well as what data is being sent to our servers.
       | 
       | Those are all good, but ultimately don't really answer the
       | question when the decryption key is part of the URL. If you
       | wanted to avoid the necessity to trust secure.sniptt.com the
       | decryption key should at least have been placed inside the
       | fragment. Then you could at least verify if it's being sent to
       | the server or not. As it is it's _definitely_ sent to the server,
       | you 'll just have to trust them that they wont use it for
       | anything nefarious
        
         | slavomirvojacek wrote:
         | Hi, I am one of the core members at Sniptt - we recently made
         | the decryption key part of the fragment precisely for the above
         | reason. I believe the GIF in the README is outdated :) - the
         | newer versions of the CLI ought to place the decryption key in
         | the fragment, but please let me know if that's not the case!
         | Thanks.
        
           | contravariant wrote:
           | Oh, nice to see you're on top of things. Looks like the
           | online version does indeed include the decryption key
           | separately in a fragment.
        
           | BiteCode_dev wrote:
           | Is there a rate limit ? Because the convenience the cli gives
           | would make it really easy to create a FUSE driver for it and
           | store abitrary files.
        
             | slavomirvojacek wrote:
             | Hi, yes we've got basic rate limits in place, as well as
             | other protective measures as this is pretty much an open
             | endpoint. Please let me know if you'd like to learn more
             | about how we're protecting the API as this is indeed quite
             | an interesting topic in itself. Thanks!
        
               | BiteCode_dev wrote:
               | Great. Are you considering removing your call to google
               | fonts ? It gives way too much data to google for
               | something that is privacy oriented.
               | 
               | Also, do you have a grace period for your burn after
               | reading URL so that it can safely be sent by chats and
               | emails system that visit any link you post ?
        
               | slavomirvojacek wrote:
               | Great question - we will likely be looking at G Fonts
               | alternatives as we are planning to revamp the entire
               | website over the coming weeks/months.
               | 
               | As for "grace period", are you asking about URL/link
               | previews and whether those have any effect on reading the
               | secret? If so, the answer is no - the secret will only be
               | read once the client-side JavaScript code is loaded and
               | executed, only certain layout components are rendered
               | server-side.
               | 
               | But I may have misunderstood your question, in which case
               | please do not hesitate to ask again :)
        
               | BiteCode_dev wrote:
               | Well, if you receive the url using gmail, google will
               | visit the link, and execute the JS code. If you don't
               | have a grace period, your secret will be unreadable
               | before the human as a chance to get to it.
               | 
               | Just saying that because, while at 0bin we have a 1 day
               | default expiration delay, users can chose burn after
               | reading. But we had to add a small grace period to allow
               | for user to check the URL, reload by listake, send vua
               | gmail, etc.
               | 
               | I thin ots burn after reading by default so it could
               | affect you.
        
               | cuu508 wrote:
               | I have run into this problem as well, my webapp sends
               | one-time login/unsubscribe/etc links via email and bots
               | like Office365 click on them, and, yes, they execute JS
               | as well.
               | 
               | A standard workaround is to serve a page with a submit
               | button on HTTP GET, and actually perform the
               | login/unsubscribe/whatever on HTTP POST.
               | 
               | In case of emails, one can also observe the email scanner
               | bots run almost immediately after the email goes out. We
               | can use this as a bot detection heuristic, and make life
               | a little easier for human users:
               | 
               | * if the login link is clicked within 5 minutes of email
               | being sent, treat it as a possible bot activity and
               | require the extra button press
               | 
               | * otherwise, assume the visitor is human, and auto-click
               | the button via JS on page load
               | 
               | More context in this StackOverflow question:
               | https://stackoverflow.com/questions/59281750/strategies-
               | to-p...
        
         | BiteCode_dev wrote:
         | Yep, that's what we do with https://0bin.net.
         | 
         | Also you must avoid client side 3rd party scrips, so no
         | analytics. Also no cdn. I hope ots will self host their google
         | fonts at some point, since you basically slink all secret URL
         | to you google account (albeit without pwd) if you are logged
         | in.
         | 
         | We also had several demands for an url shortener but couldn't
         | find a sustainable way to do it. 3rs party have rate limits and
         | hosting our own would get us back to step one.
         | 
         | DMCA also gets really interesting when you get a request but
         | they don't include the hash because some of their tooling strip
         | it along the way.
         | 
         | Anyway, even with all that, you still trust us since we could
         | inject a rogue script at any time in the page.
         | 
         | So the process really protects only us as host (see our faq),
         | but if you want real security, use pgp or signal. Or if you
         | like the cmd thingy, magic wormhole is kinda awesome.
         | 
         | Still better than sending a password using plan text of course
         | :)
        
           | giancarlostoro wrote:
           | The alternative is to do file transfers through WebRTC which
           | is supposed to be end-to-end from my understanding.
        
             | BiteCode_dev wrote:
             | If you use a webclient, it doesn't matter, you trust the
             | server no matter what you use. Ots cli has the advantage of
             | being auditable once, and remain on your computer.
        
               | giancarlostoro wrote:
               | True, I was thinking about the problem from a web only
               | perspective, since WebRTC tries to do a direct connection
               | between peers and only uses a third party server when one
               | or both connections are behind a NAT.
        
               | BiteCode_dev wrote:
               | If you initiate the session from your browser it doesn't
               | matter. At best you get better cryto since it's native,
               | but nothing more, and you can't store the result, so the
               | receiver has to be connected.
               | 
               | If you don't, then the point is moot, and the problem has
               | been solved with the excellent magic whormhole cli.
        
           | contravariant wrote:
           | Yeah guess you'd have to write your own client if you really
           | wanted to be sure nobody could read the message in transit.
           | But not sending the password to the server should at least
           | remove the obvious
           | 
           | And credit to the Sniptt team, apparently they do actually
           | put the password in the fragment in newer versions (and
           | presumably you could build your own client for it using this
           | repository if you're extra paranoid).
        
             | BiteCode_dev wrote:
             | Yes, I think if they remove the cdn call it will start to
             | be quite nice
        
         | zie wrote:
         | This is what firefox send did. The code is still maintained
         | here: https://github.com/timvisee/send
        
       | redm wrote:
       | The problem with these one-time URL's is that most people share
       | them in places where the "one-time" is usually a cloud provider.
       | If you share over IM, the IM service will check the URL to
       | provide preview, or virus scan it. Same for many email providers.
       | By the time you try to open it, it's already been burned.
       | 
       | You can whitelist those parties, but it somewhat defeats the
       | purpose of a secure one-time link.
        
         | lixtra wrote:
         | The encrypted content should be served (and burned server-side)
         | only to a POST request. No sane service can expect a POST
         | request to be idempotent and therefore shouldn't fire it
         | (twice).
        
         | bradknowles wrote:
         | That's why I password protect any one-time URLs that I ever
         | use, regardless of the provider.
         | 
         | They can't cause the URL to auto-expire if they don't have the
         | password.
         | 
         | This password on the one-time URL is something that I share via
         | less secure methods and is easily guessable. It's only purpose
         | is to prevent the one-time URL from being auto-expired by
         | malware checkers or preview creators.
        
           | slavomirvojacek wrote:
           | We're considering adding additional password protection as a
           | new feature (see https://github.com/sniptt-
           | official/ots/issues/2) - this password can then be shared via
           | other channels with the recipient.
        
         | slavomirvojacek wrote:
         | Hi, we will be using https://aws.amazon.com/waf/features/bot-
         | control/ which should help somewhat, but I think we will have
         | to spend a bit more time trying to establish a more robust
         | solution.
        
       | slavomirvojacek wrote:
       | Hi all, since we've had a bit of traction today I thought I'd ask
       | whether there are any additional features you'd like to see
       | added?
       | 
       | For example, some sort of "self-serve" UI where you could get an
       | API key which would allow users/teams have dedicated rate-limits
       | and not use the default/public limits? Or a self-hosted option
       | where the API could be deployed to the company's cloud of choice?
       | 
       | Or.. leave as is?
       | 
       | Please let us know! :)
        
         | kodablah wrote:
         | > Or a self-hosted option where the API could be deployed to
         | the company's cloud of choice?
         | 
         | Can put it on Tor and give an ephemeral onion link (I wrote
         | https://github.com/cretz/bine to help w/ just these use cases).
         | So people could access via Tor browser or via the same CLI with
         | a "client"/"get" command. Can even have the ephemeral server
         | determine its been HTTP "GET"d and kill itself. Then you don't
         | even need a public website.
        
         | bndw wrote:
         | Is the server component running at api.ots.sniptt.com open
         | source? I looked through the org's repositories and wasn't able
         | to find it.
        
           | slavomirvojacek wrote:
           | It is not at the moment but we are considering making the
           | server + maybe infra repos public in the future, most likely
           | when we've agreed on and implemented some sort of self-hosted
           | option(s).
           | 
           | We will probably write a blog post or two about how we've
           | designed the API + infra around it as there are some
           | interesting topics to be covered.
           | 
           | One of the goals was to also have fun and experiment with a
           | few approaches we've been wanting to use but could not on our
           | daily jobs.
           | 
           | For reference, everything is on AWS and we are using AWS CDK
           | (TypeScript), having moved away from serverless.com recently.
           | 
           | We are ONLY using managed services/resources which are "fully
           | serverless" (API GW, WAF, Dynamo + Dynamo Streams, Lambda,
           | EventBridge, ...) - to save cost, to minimise waste, to
           | reduce ops, etc.
           | 
           | Hope this helps, happy to provide more details.
        
       | bndw wrote:
       | If anyone is curious like I was, here's a quick review of what
       | the linked code does:
       | 
       | - Reads plaintext input from stdin
       | 
       | - Symmetrically encrypts the plaintext using a 32-byte
       | [cryptographically] random generated key (AES-256 GCM)
       | 
       | - POSTs the ciphertext and expiry (default 24h) to
       | https://api.ots.sniptt.com/secrets
       | 
       | - The server responds with a URL to view the secret via a
       | response header
       | 
       | - Query string "?ref=cli&v=<version>" are appended to the secret
       | URL
       | 
       | - The decryption key is base64 encoded and appended to the secret
       | URL as a Fragment, "#<key>"
       | 
       | - The secret URL is printed to stdout
        
         | slavomirvojacek wrote:
         | Hi, just for completeness - the decryption key is added to the
         | secret URL as a fragment in the penultimate step.
        
           | bndw wrote:
           | Thanks for the correction, updated.
        
       | fishtoaster wrote:
       | Man, I would love a self-hosted version of this. I've worked at a
       | lot of tiny startups and it often goes like this:
       | 
       | 1. Sam needs to send some sensitive credentials to Alex
       | 
       | 2. Well, we know we shouldn't use slack or email
       | 
       | 3. We should probably use a shared password manager, but that'd
       | be a much larger conversation with the whole dev team
       | 
       | 4. There are a ton of options if I search "share secrets
       | securely," but I'd have to dig into a few to figure out if I
       | trust A. that company and B. their security model
       | 
       | 5. Fuck it, just share it on slack, delete the message later, and
       | hope for the best. We'll figure out a better solution "next
       | time."
       | 
       | I'd love something simple and self-hosted that I could throw onto
       | heroku, or deploy as a ready-made container, that'd provide one-
       | time-use urls like this. It'd be a great way to have slightly
       | better secret delivery over insecure channels (like slack) in the
       | early days of an eng team before we get around to setting up a
       | unified system for secret sharing. And easy self-hosting means we
       | don't have to solve the trust problem every time.
        
         | pimlottc wrote:
         | Onceler is one option based on Ruby, in-memory storage only:
         | 
         | https://github.com/ab/onceler
        
         | nickjj wrote:
         | What about option 6?
         | 
         | Create a GPG key and encrypt / decrypt your messages.
         | 
         | It takes about 10 minutes once to set up your key and then it's
         | easy to send and receive encrypted messages with no central
         | server since you could send the encrypted text over whatever
         | transport mechanism you prefer (gist, email, etc.).
        
           | slavomirvojacek wrote:
           | We kinda did this with the snip cli (which is one of our
           | other repos besides the ots cli). It's basically a wrapper
           | around PGP with some additional features like vaults to
           | facilitate sharing PGP encrypted secrets with a team. And...
           | It takes less than 10 minutes to set up :P
        
         | swiley wrote:
         | Both S/MIME (encrypted email) and OMEMO (signal style encrypted
         | IM for XMPP with keys generated and verified client side) have
         | been around for quite a while. That your organization doesn't
         | have one of these is a complete failure of whoever is running
         | IT.
        
         | slavomirvojacek wrote:
         | Hi, I am one of the co-creators of Sniptt.
         | 
         | We faced this ourselves countless times, and it is exactly why
         | we created both OTS and Snip (https://github.com/sniptt-
         | official/snip - like OTS but with the ability to persist
         | secrets and also create shared vaults etc.).
         | 
         | Pleased to say that self-hosted options for both OTS and Snip
         | are currently top of our roadmap.
         | 
         | Keep an eye on the repos for updates! :)
        
           | penagwin wrote:
           | Myself and I'm sure many other's can't wait to try it once
           | you have the self hosted version!
        
         | Pirate-of-SV wrote:
         | For the last couple of years my org has been self-hosting
         | Yopass https://github.com/jhaals/yopass. We use it to share
         | secrets (with one time URLs) with each other.
        
       | yewenjie wrote:
       | I have been wondering recently - how secure are URLs? For example
       | Telegram's bot API is authenticated with a token which has to be
       | included in the URL for any request.
       | 
       | What kind of failure modes are there regarding this?
        
         | jerf wrote:
         | If you use HTTPS, they're pretty much as secure as HTTPS itself
         | is. Anything that would let you obtain or modify the token at
         | that point would be a break of HTTPS.
         | 
         | (Unless you're using some weird system where the secret is in
         | the domain name, in which case it can be a bit more
         | complicated, but who does that?)
         | 
         | If you use HTTP they're not secure at all.
        
         | itake wrote:
         | If they click on the URL while their internet is out, then the
         | URL may remain in their browser's search history. The search
         | history may sync between the devices, so if someone has access
         | to your phone, they may get the secret URL when your internet
         | resumes (and you haven't clicked yet).
         | 
         | This probably isn't terrible though.
        
           | remram wrote:
           | In this case, the links are one-use, so if it's in your
           | history it's already gone (and therefore secure).
        
       ___________________________________________________________________
       (page generated 2021-08-09 23:02 UTC)