# [RFC DRAFT] Automatic CSRF Protection

- Thread: https://externals.io/message/93136
- Original archive: https://news-web.php.net/php.internals/93136
- Started by Yasuo Ohgaki on 2016-05-10T03:24:29+00:00
- Messages: 65
- Page 1 of 3: messages 1 to 25 (25 per page, add `?page=N` to the URL)
- Next page: https://externals.io/message/93136.md?page=2
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #93136 — Yasuo Ohgaki — 2016-05-10T03:24:29+00:00

URL: https://externals.io/message/93136#93136

Hi all,

It's not nice to work on the same code (i.e. session module) for
multiple RFCs, but time is limited.

I would like to hear from ideas/comments before I write patch for this.
https://wiki.php.net/rfc/automatic_csrf_protection

Thank you for your comments.

Regards,

P.S. Precise session ID management is important, but this one is also
important. I'll finish and start voting 2 active session RFCs soon. I
may finish all of them hopefully.

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #93139 — Stanislav Malyshev — 2016-05-10T04:44:59+00:00

URL: https://externals.io/message/93136#93139 · In reply to: #93136

Hi!

> I would like to hear from ideas/comments before I write patch for this.
> https://wiki.php.net/rfc/automatic_csrf_protection

Could you explain a bit more - when token validation happens? Where the
SESSCSRF comes from? Does this mean that every session application now
has to support URL rewrite? What happens with applications that do not
produce HTML at all, such as REST, or those that produce data further
modified by Javascript frontend?

-- 
Stas Malyshev
smalyshev@gmail.com

---

## #93141 — Rowan Collins — 2016-05-10T09:38:17+00:00

URL: https://externals.io/message/93136#93141 · In reply to: #93136

Yasuo Ohgaki wrote on 10/05/2016 04:24:
> Hi all,
>
> It's not nice to work on the same code (i.e. session module) for
> multiple RFCs, but time is limited.
>
> I would like to hear from ideas/comments before I write patch for this.
> https://wiki.php.net/rfc/automatic_csrf_protection

I think rewriting every URL, and erroring if the token on a URL has 
expired, will not be useful for most people. What happens if I copy the 
URL of a page into an e-mail or Twitter post? As soon as anybody clicks 
that link, they're going to get an error raised; maybe it will recover 
by clearing their session, causing them to log out unnecessarily; maybe 
it will refuse to show the content claiming they're not authenticated. 
In the worst case, someone might take my URL and use the CSRF token 
against me - they have a time limit, but if the application author 
relied on this protection, the same token will be valid for any action 
on the site.

As described, the feature seems to assume that all pages are potential 
CSRF targets, when even an authenticated user on a forum spends most of 
their time on URLs which retrieve data and have no side effects. As Stas 
pointed out, not all content is amenable to rewriting, either, which 
could lead to a false sense of security - dare I compare the infamous 
magic quotes? A good implementation of CSRF protection has to consider 
when to generate a token, when to check it, and what to do on failure - 
trying to submit a comment with an invalid CSRF token might re-display 
the comment form with pre-filled content, for instance - and this 
proposal doesn't seem to address that.

I think this is the kind of feature that can only really be addressed by 
an application framework, which can have greater knowledge of when 
actions are being triggered, link tokens to specific actions, and so on.

Regards,
-- 
Rowan Collins
[IMSoP]

---

## #93142 — Yasuo Ohgaki — 2016-05-10T10:57:23+00:00

URL: https://externals.io/message/93136#93142 · In reply to: #93141

Hi Rowan,


> Yasuo Ohgaki wrote on 10/05/2016 04:24:
> > […]
>
>
> I think rewriting every URL, and erroring if the token on a URL has expired,
> will not be useful for most people. What happens if I copy the URL of a page
> into an e-mail or Twitter post? As soon as anybody clicks that link, they're
> going to get an error raised; maybe it will recover by clearing their
> session, causing them to log out unnecessarily; maybe it will refuse to show
> the content claiming they're not authenticated. In the worst case, someone
> might take my URL and use the CSRF token against me - they have a time
> limit, but if the application author relied on this protection, the same
> token will be valid for any action on the site.

To protect all of URLs automatically, all URLs need to have token.
That's the reason why all URLs have token. The risk is the same as
Trans SID session management.

> As described, the feature seems to assume that all pages are potential CSRF
> targets, when even an authenticated user on a forum spends most of their
> time on URLs which retrieve data and have no side effects. As Stas pointed
> out, not all content is amenable to rewriting, either, which could lead to a
> false sense of security - dare I compare the infamous magic quotes? A good
> implementation of CSRF protection has to consider when to generate a token,
> when to check it, and what to do on failure - trying to submit a comment
> with an invalid CSRF token might re-display the comment form with pre-filled
> content, for instance - and this proposal doesn't seem to address that.
>
> I think this is the kind of feature that can only really be addressed by an
> application framework, which can have greater knowledge of when actions are
> being triggered, link tokens to specific actions, and so on.

Because of  likelihood of the vulnerability, it's better provide basic
infrastructure. IMO. It's possible to give more control to users.

 - Specify protected method GET/POST or both.
 - Add session_csrf_validate() for manual validation

Implementation is simple enough even with these addition. (Added to RFC)

I considered to protect whole application while I was writing this RFC
draft. Thank you for point this out!

Regards,

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #93143 — Yasuo Ohgaki — 2016-05-10T11:04:32+00:00

URL: https://externals.io/message/93136#93143 · In reply to: #93139

Hi Stas,


> > […]
>
> Could you explain a bit more - when token validation happens? Where the
> SESSCSRF comes from? Does this mean that every session application now
> has to support URL rewrite? What happens with applications that do not
> produce HTML at all, such as REST, or those that produce data further
> modified by Javascript frontend?

when token validation happens?
 - As soon as `session_start()` is executed.

Where the SESSCSRF comes from?
 - Session module generates random CSRF generation key from
php_ranbom_bytes(). It generate SESSCSRF SHA1 hash value by using the
key and ttl value.

Does this mean that every session application now has to support URL rewrite?
 - No. URL rewriter is used transparently from applications.

What happens with applications that do not produce HTML at all, such as REST,
 - These apps may add SESSCSRF value manually.

or those that produce data further modified by Javascript frontend?
 - JS code may add SESSCSRF value manually.

Thank you for clarification!

Regards,

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #93144 — Niklas Keller — 2016-05-10T11:44:21+00:00

URL: https://externals.io/message/93136#93144 · In reply to: #93142

Yasuo Ohgaki <yohgaki@ohgaki.net> schrieb am Di., 10. Mai 2016 12:57:

> Hi Rowan,
>
> On Tue, May 10, 2016 at 6:38 PM, Rowan Collins <rowan.collins@gmail.com>
> wrote:
> > […]
> expired,
> > […]
> page
> > […]
> they're
> > […]
> show
> > […]
> someone
> > […]
>
> To protect all of URLs automatically, all URLs need to have token.
> That's the reason why all URLs have token. The risk is the same as
> Trans SID session management.
>
> > […]
> CSRF
> > […]
> pointed
> > […]
> to a
> > […]
> good
> > […]
> token,
> > […]
> pre-filled
> > […]
> an
> > […]
> are
> > […]
>
> Because of  likelihood of the vulnerability, it's better provide basic
> infrastructure. IMO. It's possible to give more control to users.
>
>  - Specify protected method GET/POST or both.
>

GET should never require automatic CSRF protection. If you need this,
you're doing something fundamentally wrong.

The only exception are things like OAuth, but these have to be handled
manually anyway.

 - Add session_csrf_validate() for manual validation
>
> Implementation is simple enough even with these addition. (Added to RFC)
>
> I considered to protect whole application while I was writing this RFC
> draft. Thank you for point this out!
>
> Regards,
>
> --
> Yasuo Ohgaki
> yohgaki@ohgaki.net

---

## #93145 — Albert Casademont — 2016-05-10T11:52:53+00:00

URL: https://externals.io/message/93136#93145 · In reply to: #93144

Why use sessions for CSRF Protection? That an be implemented with simple
cookies.

https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29_Prevention_Cheat_Sheet#Double_Submit_Cookies

Btw, not sure if this should be in php core though...it's more an
application thing...



> Yasuo Ohgaki <yohgaki@ohgaki.net> schrieb am Di., 10. Mai 2016 12:57:
>
> > […]
> this.
> > […]
> same
> > […]
> their
> > […]
> comment
> > […]
> by
> > […]
>
> GET should never require automatic CSRF protection. If you need this,
> you're doing something fundamentally wrong.
>
> The only exception are things like OAuth, but these have to be handled
> manually anyway.
>
>  - Add session_csrf_validate() for manual validation
> > […]

---

## #93146 — Rowan Collins — 2016-05-10T12:36:24+00:00

URL: https://externals.io/message/93136#93146 · In reply to: #93142

Yasuo Ohgaki wrote on 10/05/2016 11:57:
> To protect all of URLs automatically, all URLs need to have token.
> That's the reason why all URLs have token.

In my opinion, that fails on both counts: not all URLs need protection 
(I would say for most applications, the majority of URLs do not need 
it), and not all URLs will be protected automatically (because rewriting 
HTML is a hard problem, and because some submissions that need 
protecting are not generated as HTML).

Interestingly, the OWASP page has a whole section on the dangers of 
exposing CSRF tokens in URLs: 
https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29_Prevention_Cheat_Sheet#Disclosure_of_Token_in_URL 
It backs up my gut feeling that exposing the CSRF token too widely can 
severely diminish its usefulness; for instance, by exposing tokens in 
Referer headers sent to external sites.

There may be types of application that would benefit from every page 
having a "CSRF or die" policy - e.g. online banking - but I don't think 
they represent a large proportion of the PHP user space, or benefit 
significantly from having the functionality built into the language. For 
everyone else, all that's needed is functions to manually generate, 
save, and validate tokens, and those can trivially be written as a 
userland library. Indeed there are plenty: 
https://packagist.org/search/?q=csrf

Regards,
-- 
Rowan Collins
[IMSoP]

---

## #93150 — Stanislav Malyshev — 2016-05-10T15:30:54+00:00

URL: https://externals.io/message/93136#93150 · In reply to: #93142

Hi!

> To protect all of URLs automatically, all URLs need to have token.
> That's the reason why all URLs have token. The risk is the same as
> Trans SID session management.

But not all URLs need protecting. There are a lot of URLs that do not
need protecting - and there are a lot of actions, especially in modern
web application, that aren't achieved by simply clicking the link in the
browser. Modern web application is usually a combination of backend and
frontend logic, and if you have any frontend logic driven by XHR or
such, URL rewriting is not going to work.

> Because of  likelihood of the vulnerability, it's better provide basic
> infrastructure. IMO. It's possible to give more control to users.

The problem is the RFC proposes to give less control to users - namely,
the defaults proposed are likely to break an average application *and*
not provide CSRF protection for it.

-- 
Stas Malyshev
smalyshev@gmail.com

---

## #93151 — Stanislav Malyshev — 2016-05-10T15:32:01+00:00

URL: https://externals.io/message/93136#93151 · In reply to: #93143

Hi!

> What happens with applications that do not produce HTML at all, such as REST,
>  - These apps may add SESSCSRF value manually.

Add where? And where that value would come from? RFC says nothing about
that.

-- 
Stas Malyshev
smalyshev@gmail.com

---

## #93154 — Fleshgrinder — 2016-05-10T16:48:03+00:00

URL: https://externals.io/message/93136#93154 · In reply to: #93136

> Hi all,
> 
> It's not nice to work on the same code (i.e. session module) for
> multiple RFCs, but time is limited.
> 
> I would like to hear from ideas/comments before I write patch for this.
> https://wiki.php.net/rfc/automatic_csrf_protection
> 
> Thank you for your comments.
> 
> Regards,
> 
> P.S. Precise session ID management is important, but this one is also
> important. I'll finish and start voting 2 active session RFCs soon. I
> may finish all of them hopefully.
> 

-1 CSRF protection is a very specific need of some parts of a website
and not something that is universally required.

-- 
Richard "Fleshgrinder" Fussenegger

---

## #93158 — Chris Riley — 2016-05-10T17:20:26+00:00

URL: https://externals.io/message/93136#93158 · In reply to: #93154

> 
> > […]
>
> -1 CSRF protection is a very specific need of some parts of a website
> and not something that is universally required.
>
> --
> Richard "Fleshgrinder" Fussenegger
>
>
Sorry but this isn't something that the language should be concerning
itself with. It will cause more pain than it's worth (think magic quotes).

Also, you suggest that PHP should raise an error on session_start if the
validation fails, most of the time if my app gets a csrf failure an error
would be inappropriate as I'd want to handle it myself and display for
example a form validation error message instead of blowing up the whole
script.

Given that this feature is optional it will do nothing to improve security
whilst adding pain to developers who are producing apps designed to run in
multiple environments eg drupal/wordpress etc so a big -1 from me.

---

## #93173 — Yasuo Ohgaki — 2016-05-10T22:03:46+00:00

URL: https://externals.io/message/93136#93173 · In reply to: #93146

Hi Rowan,


> Yasuo Ohgaki wrote on 10/05/2016 11:57:
> > […]
>
>
> In my opinion, that fails on both counts: not all URLs need protection (I
> would say for most applications, the majority of URLs do not need it), and
> not all URLs will be protected automatically (because rewriting HTML is a
> hard problem, and because some submissions that need protecting are not
> generated as HTML).
>
> Interestingly, the OWASP page has a whole section on the dangers of exposing
> CSRF tokens in URLs:
> https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29_Prevention_Cheat_Sheet#Disclosure_of_Token_in_URL
> It backs up my gut feeling that exposing the CSRF token too widely can
> severely diminish its usefulness; for instance, by exposing tokens in
> Referer headers sent to external sites.
>
> There may be types of application that would benefit from every page having
> a "CSRF or die" policy - e.g. online banking - but I don't think they
> represent a large proportion of the PHP user space, or benefit significantly
> from having the functionality built into the language. For everyone else,
> all that's needed is functions to manually generate, save, and validate
> tokens, and those can trivially be written as a userland library. Indeed
> there are plenty: https://packagist.org/search/?q=csrf

Exposure of CSRF token is obvious security risk.
As I wrote, the risk is the same as trans sid. In addition, it does not
add CSRF token to URLs by default now. (i.e. Protect POST automatically when
it is enabled)

Regards,

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #93174 — Yasuo Ohgaki — 2016-05-10T22:05:23+00:00

URL: https://externals.io/message/93136#93174 · In reply to: #93151

Hi Stas,

On Wed, May 11, 2016 at 12:32 AM, Stanislav Malyshev
<smalyshev@gmail.com> wrote:
> > […]
>
> Add where? And where that value would come from? RFC says nothing about
> that.

As usual. Query parameter when GET is used. Additional input when POST
is used. All users have to do is adding CSRF token to JS program.

Regards,

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #93175 — Yasuo Ohgaki — 2016-05-10T22:06:17+00:00

URL: https://externals.io/message/93136#93175 · In reply to: #93154

Hi,


> 
> > […]
>
> -1 CSRF protection is a very specific need of some parts of a website
> and not something that is universally required

Did you read RFC?
It does not enable CSRF protection for all website, but only when it is enabled.

Regards,

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #93179 — Stanislav Malyshev — 2016-05-10T22:58:53+00:00

URL: https://externals.io/message/93136#93179 · In reply to: #93174

Hi!

> > […]
> 
> As usual. Query parameter when GET is used. Additional input when POST
> is used. All users have to do is adding CSRF token to JS program.

GET and POST aren't the only HTTP methods. And where JS program would
get the correct token from? As far as I can see, there's no function in
the RFC that produces it.

-- 
Stas Malyshev
smalyshev@gmail.com

---

## #93180 — Stanislav Malyshev — 2016-05-10T23:01:12+00:00

URL: https://externals.io/message/93136#93180 · In reply to: #93175

Hi!

> Did you read RFC?
> It does not enable CSRF protection for all website, but only when it is enabled.

The RFC says: "Default: session.csrf_protection=1". Which means all
sites would have it (for POST) unless they specifically disable it by
changing configuration.

Also, new variants do not account for existence of other HTTP methods
such as PUT, DELETE, etc. Value "2" also makes little sense - why would
you want to protect GET, but not POST?

-- 
Stas Malyshev
smalyshev@gmail.com

---

## #93181 — Yasuo Ohgaki — 2016-05-11T00:17:39+00:00

URL: https://externals.io/message/93136#93181 · In reply to: #93175

Hi,


> 
> > […]
>
> Did you read RFC?
> It does not enable CSRF protection for all website, but only when it is enabled.

Oops. I set default to protect. Fixed it. Thanks.

Regards,

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #93182 — Yasuo Ohgaki — 2016-05-11T01:06:11+00:00

URL: https://externals.io/message/93136#93182 · In reply to: #93136

Hi All,


> It's not nice to work on the same code (i.e. session module) for
> multiple RFCs, but time is limited.
>
> I would like to hear from ideas/comments before I write patch for this.
> https://wiki.php.net/rfc/automatic_csrf_protection
>
> Thank you for your comments.

I've changed RFC target from "automatic" to "semi-automatic". i.e.
Changed title.

It is possible to set up web system that could be protected from CSRF
attack fully, but it requires web server setting/simple php script to
do so. If it requires web system modification anyway, it would be
better make this feature more generic.

Users has to write a setting for pages, but it should be good enough
to secure simple applications.

Regards,

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #93183 — Yasuo Ohgaki — 2016-05-11T01:11:57+00:00

URL: https://externals.io/message/93136#93183 · In reply to: #93179

Hi Stas,


> > […]
>
> GET and POST aren't the only HTTP methods. And where JS program would
> get the correct token from? As far as I can see, there's no function in
> the RFC that produces it.

PHP doesn't have other method support yet.
If users have their implementation PUT/etc, they may validate CSRF
token manually.

I intended this feature for simple applications that lacks CSRF
protection at first, but it seems I'm better to change objective. I'll
change target to semi automatic/manual CSRF protection.

Regards,

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #93184 — Yasuo Ohgaki — 2016-05-11T01:17:10+00:00

URL: https://externals.io/message/93136#93184 · In reply to: #93179

Hi Stas,


> > […]
>
> GET and POST aren't the only HTTP methods. And where JS program would
> get the correct token from? As far as I can see, there's no function in
> the RFC that produces it.

JS code that does not have pages at all may obtain CSRF token manually.

get_csrf_token.php
<?php
session_start(['csrf_protection'=>SESSION_CSRF_GET]);
echo json_encode(['SESSCSRF'=>SESSCSRF]);
?>

then JS apps may use the token. Users must be careful for CSRF token TTL.

Regards,

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #93185 — kinncj@gmail.com — 2016-05-11T01:20:52+00:00

URL: https://externals.io/message/93136#93185 · In reply to: #93184

> JS code that does not have pages at all may obtain CSRF token manually.

That's against CSRF protection... in fact, a remote app can obtain the
token also and make the cross site request forgery...

-1



> Hi Stas,
>
> On Wed, May 11, 2016 at 7:58 AM, Stanislav Malyshev <smalyshev@gmail.com>
> wrote:
> > […]
>
> JS code that does not have pages at all may obtain CSRF token manually.
>
> get_csrf_token.php
> <?php
> session_start(['csrf_protection'=>SESSION_CSRF_GET]);
> echo json_encode(['SESSCSRF'=>SESSCSRF]);
> ?>
>
> then JS apps may use the token. Users must be careful for CSRF token TTL.
>
> Regards,
>
> --
> Yasuo Ohgaki
> yohgaki@ohgaki.net
>
> --
> 
> 
>
>


-- 
*--*
*Kinn Coelho Julião*
*Toronto - ON/Canada*

---

## #93186 — Yasuo Ohgaki — 2016-05-11T02:18:12+00:00

URL: https://externals.io/message/93136#93186 · In reply to: #93185

Hi Kinn,


> > […]
>
> That's against CSRF protection... in fact, a remote app can obtain the token
> also and make the cross site request forgery...
>
> -1

You seem to __misunderstood__ behavior.

Random CSRF token generation key is stored in session data which is
private to users.
CSRF token is generated by using the secret key.

Therefore, attacker cannot get CSRF token unless they have stolen
session already (which is not scope of this RFC)

Regards,

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #93187 — kinncj@gmail.com — 2016-05-11T02:53:22+00:00

URL: https://externals.io/message/93136#93187 · In reply to: #93186

You seemed to misunderstood your own "get_csrf_token.php" and how attackers
would benefit from that.

Anyway, you're trying to transfer an application behaviour to the core...
Stick to -1.


> Hi Kinn,
>
> 
> > […]
> token
> > […]
>
> You seem to __misunderstood__ behavior.
>
> Random CSRF token generation key is stored in session data which is
> private to users.
> CSRF token is generated by using the secret key.
>
> Therefore, attacker cannot get CSRF token unless they have stolen
> session already (which is not scope of this RFC)
>
> Regards,
>
> --
> Yasuo Ohgaki
> yohgaki@ohgaki.net

---

## #93188 — kinncj@gmail.com — 2016-05-11T02:56:31+00:00

URL: https://externals.io/message/93136#93188 · In reply to: #93187

The point with your example is:
The cross site can request the "get_csrf_token.php", store on its session
(even curl can save the session id cookie or whatever), get the token and
request the endpoint with the retrieved token and session id.

Got it?


> You seemed to misunderstood your own "get_csrf_token.php" and how
> attackers would benefit from that.
>
> Anyway, you're trying to transfer an application behaviour to the core...
> Stick to -1.
> 
>
> > […]

---

Next page: https://externals.io/message/93136.md?page=2
