
CSRF in Doorkeeper OAuth2 gem - homakov
http://homakov.blogspot.com/2014/12/blatant-csrf-in-doorkeeper-most-popular.html
======
rplnt
Is there a browser extension (or browser) that could either open each new tab
"clean" (no cookies or anything) or even better lock it on the first domain
visited?

Example:

I open a new tab with example.com, and with this a new session would be
created which only contains data relevant to example.com. Anything I open
later on in this tab won't see anything else. I can always open link in a new
tab to start a "relevant" session (though that would require browser that can
work with tabs, i.e. not Chrome).

~~~
michaelt
Most browsers have a setting to disable 'third party cookies' \- e.g. if
you're on www.evil.com and that page sends a request to www.example.com the
example.com connection won't send cookies, or store received cookies.

You can set this up easily in Firefox [1] and Chrome [2]. It will break a
handful of things, for example some sites embed comments from facebook,
disqus, google+ etc. So for example when you visit www.youtube.com you won't
be able to comment, as comments are in iframe loaded from plus.google.com
which you can't log into without third party cookies enabled.

IMHO this is no great loss, and I block third party cookies all the time.

Of course, it's still possible to do certain attacks by redirecting the entire
browser window or opening a popup window.

[1] [https://support.mozilla.org/en-US/kb/disable-third-party-
coo...](https://support.mozilla.org/en-US/kb/disable-third-party-cookies) [2]
[https://support.google.com/chrome/answer/95647?hl=en-
GB](https://support.google.com/chrome/answer/95647?hl=en-GB)

~~~
IgorPartola
I did this after I learned that Safari on iOS does this by default. If in all
of my usage of my phone browser I didn't run into issues, I don't see why I
should on the desktop.

~~~
lmm
Developers often make special exceptions for iPhones that they won't make for
e.g. linux users.

~~~
IgorPartola
How so? You can't really get around not using third party cookies by doing
something different, and if you can, are you really going to detect the device
type rather than whether the UA accepted third party cookies? I guess anything
is possible. All I know is that turning off third party cookies has not
affected me in any way over the past three months. Then again, I block
advertisers at DNS and via ABP, and they are the main user of third party
cookies, so I guess you could say that the ads didn't properly work for me for
a while.

------
tutec
Hey there! You may upgrade to 1.4.1 or 2.0.0 to avoid this. Thanks for
posting.

------
Rygu
This is why it's increasingly important to not only test your code, but also
develop useful vulnerability scanners. I know, it sounds impossible to write a
complete vulnerability scanner, but many companies would pay for such a thing.

Existing solutions are either lacking or way too difficult to operate.

~~~
lmm
Any sufficiently advanced vulnerability scanner contains an contains an ad
hoc, informally-specified, bug-ridden, slow implementation of half of a type
system.

Seriously, the solution isn't better scanners or better tests, it's better
languages. Make whether something is taking a potentially-destructive action
part of its type, and then the compiler ensures that all such routes are
appropriately protected; you can do this today in e.g. Spray (which I'm using
in production, so this is not some ivory-tower theoretical solution).

~~~
dsacco
This suggestion eliminates bugs that are introduced by unsafe typing, sure.
But race conditions, logic flaws, misconfigured tools and almost every class
of web vulnerability wouldn't be eliminated just by implementing this.

Most vulnerabilities do not derive from a single faulty tool or framework, but
the incorrect combination of several (faulty or not!) tools over a
sufficiently large attack surface.

~~~
lmm
> This suggestion eliminates bugs that are introduced by unsafe typing, sure.
> But race conditions, logic flaws, misconfigured tools and almost every class
> of web vulnerability wouldn't be eliminated just by implementing this.

How often are security flaws a subtle, complex thing that couldn't have been
caught by a sensible type system? Almost all of the flaws we hear about, at
least here, are the really simple dumb mistakes that a better language
absolutely would have caught.

~~~
rudolf0
Do you mean a language with a very strong type system like Haskell, where you
could create a web framework in which things like user input have different
types associated with them? Those can offer some real advantages by never
mixing untrusted input with page output and various calls to other systems.

But you don't get a lot of web application security advantages when you
compare, say, Python and Java.

Of course, a very weak type system like PHP's can definitely introduce
additional security flaws.

~~~
jfoutz
A common pattern (at least getting there) in Scala/F#/Haskell is to have
paired types, UserInput and ValidatedUserInput. All the business logic
requires the Validated kind. A programmer can be certainly be lazy and just
return the supplied value, but this is a conscious choice to do the wrong
thing.

You can't accidentally forget to validate form parameters. It won't compile.
This is pretty easy to do in Java. On the weaker side, I would assume php and
python have something like perl's taint mode. It's such a simple thing and it
avoids so many xss problems.

------
VLM
Can someone provide a better "forwardable" explanation of CSRF than the
wikipedia version of "let me f-ing google that for you"?

I already unsuccessfully searched for a XKCD treatment.

Something I can forward to non-devs not written at dev level. Also no videos
(who has time for that?). It sounds like a graphics arts type project, like a
xkcd topic, so I guess something like that is what I'm looking for.

The wiki explanation is pretty good, just curious if anyone has anything
better for non-technical-ish people.

~~~
madgar
"It's expected that I can send you a link to facebook.com. But it's not okay
if I can send you a link that immediately deletes your account."

~~~
grimtrigger
Isn't this easily mitigated by making all request that change state (update
data in any way) as post requests?

~~~
adamdoupe
No. Check out the example in the article, an attacker can make your browser
submit a form with a POST request using JavaScript.

It's slightly harder to exploit, as the attacker can't just send you a link to
facebook.com, but they can send you a link to example.com which has the form
and uses JavaScript to submit the form.

------
Synthpixel
While I believe that allowing CSRF is terrible practice, as a user of
Doorkeeper, I think the problem here is Digital Ocean's atypical usage of
OAuth2. When you request an access token for a resource owner in OAuth2, you
are supposed _actually authenticate_ the owner. According to the OAuth2
spec[1], username and password are REQUIRED fields. Allowing clients to
generate tokens based off of cookies is reckless.

Useful CSRF exploits depend on the server to trust session data to
authenticate client actions. OAuth2 is designed for allowing external (third-
party) applications to communicate with you. Cross-site requests are an
expectation in OAuth2. If you ignore the spec and skip proper authentication,
you're in a bad spot anyway.

[1] [https://tools.ietf.org/html/rfc6749](https://tools.ietf.org/html/rfc6749)
(page 37 & 38)

~~~
diafygi
I can't name a single OAuth2-enabled website that does this. Facebook,
Twitter, Dropbox, Google, LinkedIn, ...

They all let you approve if you are already logged in.

~~~
ewang1
Usually those implementations redirect the user to a separate authentication
system. OAuth2 only handles authorization and not authentication. Upon
successful authentication, the user gets redirected back to the OAuth2 request
which then generates the authorization code.

When the user is already logged in via a cookie set by the authentication
system (i.e. an existing valid session), they don't get prompted for a
password again; the authentication system will simply redirect to the OAuth2
request url. The typical OAuth2 implementations shouldn't be reading the
authentication cookies directly.

The "password flow" in OAuth2 is really a special case for those who want to
bypass the separate authentication system and use OAuth2 directly for both
authentication and authorization.

------
Stefan-H
Am I missing something? While there does not seem to be a reason to allow CSRF
here, doesn't the fact that you need to have a client Id and client secret for
the oath endpoint make it so that this is a non-issue?

[https://github.com/doorkeeper-
gem/doorkeeper/wiki/authorizat...](https://github.com/doorkeeper-
gem/doorkeeper/wiki/authorization-flow)

I don't see a way to get the access token without having the client ID and
client secret.

~~~
homakov
you just need to create a client. Then you will have ID+secret. Most providers
allow anyone to get them

~~~
Stefan-H
So this only applies to those that use doorkeeper to act as oauth providers,
not to those that allow logins through other oauth providers, right?

~~~
homakov
Sure, Doorkeeper is oauth Provider gem, not client.

------
boracay
As long as we keep treating security as a purely technical problem the state
of software isn't going to improve significantly. Responsibility tends to
catch up with things. It's mostly a question if it's going to benefit software
or not.

~~~
pvnick
I disagree. Preventing vulnerabilities is not primarily an "attitude problem."
Writing code is hard enough as it is, and writing flawless code that can
withstand hostile attacks is _really_ hard. Odds favor vulnerability
existence, and when bad ones are inevitably discovered in production systems
people always claim the whole process is broken.

That being said, this one is pretty bad.

~~~
boracay
The demand for "safe"[0] software is going to reach critical mass sooner or
later. The question is if it's going to be solved by good tools, processes and
education or app stores, insurance ratings and regulation. Software isn't much
different from other types of infrastructure.

~~~
ploxiln
well, except for the rate of change

------
afiedler
This is pretty bad, but I believe it is only possible to get an access token
if you also allow malicious/non-trusted users to either create new OAuth
client registrations (`Doorkeeper::Application` models) or modify the redirect
URI of an existing OAuth client registration. The reason is that the access
token is delivered over a redirect, not in the response to the form POST.
Doorkeeper does check for a valid redirect URI.

------
mcbetz
Even if it is critical for some, for me it feels exactly how open source
works: someone uses an application in a way that was not intented or thought
about. And it turns out, that there is a problem with that approach. Someone
will blog about it, write a bug ticket or send a pull request. And gone is the
problem and the application got better. That's applied wisdom of the crowd.

------
Gepsens
Another show of the blatant amateurism of the Ruby community. I don't even
count the number of pull requests on gems considered cannon I've had to do
since I started coding in that language.

~~~
alinajaf
I think you probably mean canon.

~~~
skj
No, cannon. Like, really solid and made out of explosion-resistant iron.

~~~
alinajaf
Ah, sorry, my mistake.

~~~
wlll
Pretty sure he meant "canon" in that context.

1) A general law, rule, principle, or criterion by which something is judged
2) A collection or list of sacred books accepted as genuine

([http://www.oxforddictionaries.com/definition/english/canon](http://www.oxforddictionaries.com/definition/english/canon))

~~~
slater
_whooosh_

~~~
alinajaf
"Nothing flies over my head. My reflexes are too fast. I would catch them".

