CSRF in Gemini

1. Francesco Gazzetta (fgaz (a) fgaz.me)

Hi all,

I just wrote down a few thoughts about cross-site request forgery in
Gemini:

gemini://gemini.circumlunar.space/~/fgaz/posts/2020-06-15-csrf-in-gemini/

I'm starting this thread to brainstorm ideas about the last point.
Basically:

> CSRF protection via non-native nonces is ugly, can we do better than
> the web?

Cheers
-- Francesco

Link to individual message.

2. solderpunk (solderpunk (a) SDF.ORG)

On Mon, Jun 15, 2020 at 04:09:47PM +0200, Francesco Gazzetta wrote:
 
> I'm starting this thread to brainstorm ideas about the last point.

Thanks for getting this conversation started!

It's perhaps a little bit tedious for users, but the simplest solution I
can think of for things like this is a convention that all requests
which trigger side-effects (like comments, etc.) must be made with a
client certificate, because that will make it very clear to the user
that something is happening and no surprises are possible.

I strongly suspect that completely preventing this kind of thing will be
impossible if we simultaneously insist on a simple protocol and a
frictionless user experience - in which case, everybody knows which one
will be prioritised. :)  But if we can somehow pull off both at once
that will be best.

Cheers,
Solderpunk

Link to individual message.

3. Felix Queißner (felix (a) masterq32.de)

Hey!

> I just wrote down a few thoughts about cross-site request forgery in Gemini:

Good read! I thought about that as well?

>> CSRF protection via non-native nonces is ugly, can we do better than
>> the web?
I think one solution would be to force clients to remove queries from
all URLs. It's not a really elegant solution and makes CGI stuff harder
to implement, but will prevent a lot of URL-fuckery. I'm also always
scared when clicking links in interactive things, because double
postings are really easy to achieve with the query appended to URLs.
Hitting refresh in your browser to see new posts? You create a new post
in the guestbook!

While writing this, i got the following idea (which seams reasonable to me):
Specify that a response to INPUT MUST be passed with a query-parameter
"?input=?" where "?" is the data from the user. The data is fully
urlencoded with all forbidden characters(space,?,=,?) replaced with
their percent-encoding.

Also specify that clients SHOULD remove the "input"-parameter between
redirects and in documents using the gemini-scheme.

This allows us to prevent passing accidential or malicious data via
redirects, but doesn't help against a spam-bot that targets a site
directly. It also makes client implementation a bit harder.

Regards
- xq

Link to individual message.

4. Peter Vernigorov (pitr.vern (a) gmail.com)

This type of attack impacts more than just endpoints that rely on
query parameter. For example, one can delete their astrobotany plant
simply by getting redirected to /app/plant/harvest/confirm (although
that is not strictly deletion). If a certificate is already activated
for this site, then this will not help stop the attack.

However, the difference I see between HTTP/HTML and Gemini is that
this attack is not happening in an invisible iframe/xhr request, but
in plain sight of the user. Once they are redirected to any of the
impacted pages, they will see a message from server informing them of
their actions. "you posted a comment", "you harvested/deleted your
plant". Perhaps an easy workaround is to let user undo their action?
"you posted a comment, would you like to undo?" This has an additional
positive side effect of an easy undo of human errors, in case the
comment was submitted prematurely, or contains an error.

On Mon, Jun 15, 2020 at 5:05 PM Felix Quei?ner <felix at masterq32.de> wrote:
>
> Hey!
>
> > I just wrote down a few thoughts about cross-site request forgery in Gemini:
>
> Good read! I thought about that as well?
>
> >> CSRF protection via non-native nonces is ugly, can we do better than
> >> the web?
> I think one solution would be to force clients to remove queries from
> all URLs. It's not a really elegant solution and makes CGI stuff harder
> to implement, but will prevent a lot of URL-fuckery. I'm also always
> scared when clicking links in interactive things, because double
> postings are really easy to achieve with the query appended to URLs.
> Hitting refresh in your browser to see new posts? You create a new post
> in the guestbook!
>
> While writing this, i got the following idea (which seams reasonable to me):
> Specify that a response to INPUT MUST be passed with a query-parameter
> "?input=?" where "?" is the data from the user. The data is fully
> urlencoded with all forbidden characters(space,?,=,?) replaced with
> their percent-encoding.
>
> Also specify that clients SHOULD remove the "input"-parameter between
> redirects and in documents using the gemini-scheme.
>
> This allows us to prevent passing accidential or malicious data via
> redirects, but doesn't help against a spam-bot that targets a site
> directly. It also makes client implementation a bit harder.
>
> Regards
> - xq

Link to individual message.

5. Sean Conner (sean (a) conman.org)

It was thus said that the Great Francesco Gazzetta once stated:
> Hi all,
> 
> I just wrote down a few thoughts about cross-site request forgery in
> Gemini:
> 
> gemini://gemini.circumlunar.space/~/fgaz/posts/2020-06-15-csrf-in-gemini/

  I read the article and I don't think this is that much of an issue with
Gemini.  It lacks javascript.  It lacks cookies.  It serverely limits the
data that can be posted.  Authentication is done via certificates.  About
the only valid issue is the SPAM issue you brought up, but I think it *is*
possible to detect since the server will have the IP address of the
sender---repeated requests could be blocked by blocking the IP address.

  Another issue with the nonce (other than how to send it back) is that a
malicious bot can just make a request that returns the nonce and use it,
like like a Gemini client with a human driver will do.

  It's an issue, but less of one than on the web.

  -spc

Link to individual message.

6. Francesco Gazzetta (fgaz (a) fgaz.me)

On Mon, 15 Jun 2020 14:30:07 +0000
solderpunk <solderpunk at SDF.ORG> wrote:

> It's perhaps a little bit tedious for users, but the simplest
> solution I can think of for things like this is a convention that all
> requests which trigger side-effects (like comments, etc.) must be
> made with a client certificate, because that will make it very clear
> to the user that something is happening and no surprises are possible.

Doesn't this imply that all requests with a client cert will have to be
confirmed by the user?

> I strongly suspect that completely preventing this kind of thing will
> be impossible if we simultaneously insist on a simple protocol and a
> frictionless user experience - in which case, everybody knows which
> one will be prioritised. :)  But if we can somehow pull off both at
> once that will be best.

Of course, which is why I wrote

> But this would require a separator, and we all know where this leads.

:)

Still, I don't think this is a matter of frictionless user experience,
more like... developer ux? Unless we find something simpler than nonces.

Link to individual message.

7. Francesco Gazzetta (fgaz (a) fgaz.me)

On Mon, 15 Jun 2020 17:05:33 +0200
Felix Quei?ner <felix at masterq32.de> wrote:

> I think one solution would be to force clients to remove queries from
> all URLs. It's not a really elegant solution and makes CGI stuff
> harder to implement, but will prevent a lot of URL-fuckery.

That coul be a good and clean solution, if we get microbotany, gus, etc
to move the stuff they put in the query to a path fragment. Too bad
this means that it's no longer possible to use cgi for that stuff.

> While writing this, i got the following idea (which seams reasonable
> to me): Specify that a response to INPUT MUST be passed with a
> query-parameter "?input=?" where "?" is the data from the user. The
> data is fully urlencoded with all forbidden characters(space,?,=,?)
> replaced with their percent-encoding.
> 
> Also specify that clients SHOULD remove the "input"-parameter between
> redirects and in documents using the gemini-scheme.

Less clean, but preserves cgi functionality and it's stateless! I like
this

> This allows us to prevent passing accidential or malicious data via
> redirects, but doesn't help against a spam-bot that targets a site
> directly. It also makes client implementation a bit harder.

Eh, the spam problem is a problem on its own anyway, and I probably
should have made a different example in my article.

Link to individual message.

8. Francesco Gazzetta (fgaz (a) fgaz.me)

On Tue, 16 Jun 2020 00:11:35 +0200
Peter Vernigorov <pitr.vern at gmail.com> wrote:

> This type of attack impacts more than just endpoints that rely on
> query parameter. For example, one can delete their astrobotany plant
> simply by getting redirected to /app/plant/harvest/confirm (although
> that is not strictly deletion). If a certificate is already activated
> for this site, then this will not help stop the attack.

I think that's also a different problem. Such endpoints should IMO
require input from the user, like "Type yes to confirm". Or there could
be an additional 1x code for requesting a simple yes/no confirmation.
This code could easily fallback to 10, by having the buttons send "yes"
or "no" and the question say "Do you confirm? Type yes/no".

> However, the difference I see between HTTP/HTML and Gemini is that
> this attack is not happening in an invisible iframe/xhr request, but
> in plain sight of the user. Once they are redirected to any of the
> impacted pages, they will see a message from server informing them of
> their actions. "you posted a comment", "you harvested/deleted your
> plant". Perhaps an easy workaround is to let user undo their action?
> "you posted a comment, would you like to undo?" This has an additional
> positive side effect of an easy undo of human errors, in case the
> comment was submitted prematurely, or contains an error.

Undo is not always easy to implement though (strawman: you launched a
nuclear missile. undo?), and one has to remember to do it for every
page, much like remembering to escape string-concatenated sql
statements.

Link to individual message.

9. Francesco Gazzetta (fgaz (a) fgaz.me)

On Mon, 15 Jun 2020 21:28:08 -0400
Sean Conner <sean at conman.org> wrote:

> Authentication is done via
> certificates.

But unless confirmation is required for _every_ request with a
certificate (is it? I'll have to re-read the spec) then the problem
persists, since the request is done by the victim.

> About the only valid issue is the SPAM issue you
> brought up, but I think it *is* possible to detect since the server
> will have the IP address of the sender---repeated requests could be
> blocked by blocking the IP address.

It's not detectable without nonces, because the spammer doesn't have to
do any request, only the victims (with presumably different IPs)

>   Another issue with the nonce (other than how to send it back) is
> that a malicious bot can just make a request that returns the nonce
> and use it, like like a Gemini client with a human driver will do.

Yes, but like in the web we can act on that first request an check for
client cert (which the attacker won't have) and IP (which will always
be the attacker's one)

Link to individual message.

10. Jason McBrayer (jmcbray (a) carcosa.net)

Francesco Gazzetta <fgaz at fgaz.me> writes:

>> CSRF protection via non-native nonces is ugly, can we do better than
>> the web?

My swimming-against the current proposal: all Gemini requests must be
idempotent. The easy way to make a request idempotent is to make it have
no side-effects.

Yes, this effectively limits Gemini to a document-delivery protocol, and
strictly constrains what apps could be built on top of it. That may not
be a bad thing.

-- 
+-----------------------------------------------------------+  
| Jason F. McBrayer                    jmcbray at carcosa.net  |  
| If someone conquers a thousand times a thousand others in |  
| battle, and someone else conquers himself, the latter one |  
| is the greatest of all conquerors.  --- The Dhammapada    |

Link to individual message.

11. solderpunk (solderpunk (a) SDF.ORG)

On Tue, Jun 16, 2020 at 11:12:22AM -0400, Jason McBrayer wrote:
 
> My swimming-against the current proposal: all Gemini requests must be
> idempotent. The easy way to make a request idempotent is to make it have
> no side-effects.
> 
> Yes, this effectively limits Gemini to a document-delivery protocol, and
> strictly constrains what apps could be built on top of it. That may not
> be a bad thing.

I am leaning toward "all Gemini requests made without client
certificates should be idempotent" - stay tuned for *much* more detail
later tonight.  I have ideas which, I hope, will let us make people who
are only interested in a document-delivery protocol *and* hopeless nerds
who want to build apps happy, and even keep them out of each other's
hair to the extent that they want to be...

Cheers,
Solderpunk

Link to individual message.

---

Previous Thread: gemini-mode.el is now in MELPA

Next Thread: [SPEC-CHANGE] Simplified client certs, URI scheme, alt text