
A bizarre “403 Forbidden” bug-hunting adventure - joshsharp
http://blog.hellocode.co/post/bug-hunting/
======
luketheobscure
"NSURLSession oh so helpfully auto-fucking-matically decided I would
probably—no, definitely—want to send those cookies in every single request my
app did after that. Forever and always."

I imagine it honors the "expires" property of cookies, it just probably wasn't
set. Also there's an "ephemeralSessionConfiguration" you can use if you don't
want to store the cookies. I enjoyed the article, up until the author blamed
the framework for their own ignorance.

~~~
joshsharp
Sure, the cookies expire (in two weeks I think, in this case) but that doesn't
invalidate the issue that the wkwebview silently shares cookies with
nsurlsession, nor does it negate the confusing journey of tracking down the
bug. Sheesh.

~~~
spullara
This is exactly what users want and you are basically breaking it by not
honoring the cookies.

~~~
joshsharp
We do not need to honour cookies when making requests to the API as we use
token authentication. Even if we wanted to keep users logged in within the web
view, which we don't because the web view is just for static help pages, we
wouldn't want to send those to the API.

~~~
eridius
Then you should disable cookies on your API calls by setting the
`httpCookieStorage` property of your URLSessionConfiguration to nil. You could
also use an ephemeral configuration (which will preserve cookies set by the
API in memory but won't share them with webviews), which may or may not be a
good idea depending on if you're using this session for anything that should
be cached to disk (e.g. downloading images).

~~~
salgernon
This is the correct answer and the reason that NSURLSession really came into
existence - there is a need to partition behaviors between different
frameworks and subsystems and the previous NSURLConnection model relied on a
smattering of process global configuration options.

I'd be surprised if AFNetworking didn't also offer the ability to create a
"private" NSURLSession with custom storage objects.

I'd also recommend looking into debugging these types of issues using, eg,
Charles Proxy. There's more information on logging at:

[https://developer.apple.com/library/content/qa/qa1887/_index...](https://developer.apple.com/library/content/qa/qa1887/_index.html)

See also:

[https://developer.apple.com/videos/play/wwdc2013/705/](https://developer.apple.com/videos/play/wwdc2013/705/)

Disclaimer: NSURLSession contributor...

------
js2
Oh hey, I know this. From a commit message earlier this year for an SDK I own:

 _SDKSender: switch to ephemeral NSURLSession and disable cookie storage

Switch to a private (ephemeral) session independent of the app and disables
cookies. The SDK otherwise shares the cookie storage with the app, which is
not desired. This was causing the SDK to send the $dayjob tracking cookie (and
others) to $dayjob API endpoint._

------
udioron
Another fix is to disable CSRF checks for all API calls which should not be
served by a browser (assuming they use a different auth mechanism which does
not involve cookies!). This makes sense since CSRF is a layer that relates to
attacks involving browsers/cookie authentication.

~~~
yeukhon
I always believe /login served by a browser and /login for api should never be
the same, to echo your statement they require different handler. It should be
two completely different view; but those views call the same login function
internally. Perhaps /login is a bad example, but use that in views where
authentication and authorization are needed.

------
Grollicus
Despite using Functions he doesn't really understand and yada yada i think
this is a good reason to have a dedicated api endpoint and not mix it with
domains where the normal web access happens.

------
exikyut
This is both awesome and depressing.

But it gave me a really interesting idea: a
service/network/community/forum/etc for people to gather and discuss Really
Confusing Bugs™ that they're trying to figure out. Not necessarily (?) for
contemporary end users (maybe highly technical end users).

This could actually be a really cool concept. Somewhere squarely between
HackerOne and StackOverflow - not for exploits, and not for simple(r) stuff,
but specifically for complicated and confusing bugs you've been staring at for
days/weeks and nothing's making any sense.

I can see a subscription model working for this, even - subscriptions would
work both to allow people to provide extended assistance, and also because a
contract makes NDAs easier.

Hmm. Thinking about how the subscription model would work... you sign up,
configure billing, that then allows you to request extended assistance.

\- One way that could work is that people offer you help in return for thanks,
which would work like a configurable upvote; higher quality answers attract
more rewards. Maybe anyone can reward answers (via the credit in their
account) after the fact?

\- Another way would be setting a minimum or exact reward amount up front to
attract more help.

Regardless of how it worked, the site would have all discussion be public and
open by default; you'd have to check a box to make the discussion private, and
even after that you'd have the ability to go through and selectively un-redact
parts of the conversations so everyone could be helped.

And anyone could sign up and offer answers instantly, and the rewards credited
to their account could be cashed out at any time. That would attract new
users.

I realize I've just described a weird kind of paid StackOverflow. I am very
curious why SE hasn't pursued such an idea. As in, I am 1000% confident
they've had this conversation _at least_ once, and I'd really love to hear
what the opinions were.

~~~
andreareina
ExpertsExchange was[1] a paid StackOverflow before the latter existed, SO came
along and ate EE's lunch. Some of that was undoubtedly due to EE's
(anecdotally, I never used it due to the money issue) bad UX, but free makes a
big difference.

[1] They still exist, and it apparently gets traffic/use, but never hear
anyone talking about them, and it never comes up when searching to resolve or
diagnose a problem.

~~~
pbhjpbhj
EE had a scheme where you could answer questions to get free membership; I
used that for a while.

I remember getting screwed over but don't remember the details: they locked up
the site and I couldn't even access the solutions I'd written anymore. A bit
later still they made it appear locked but you could still get to the answers
if you knew how (I think that was to get their solutions on Google.

I'd guess it was taken over and someone tried to squeeze the money out, hasn't
happened to SO yet.

~~~
wolco
if I remember you had to scroll down past the ad content.

------
catshirt
when you have a bizarre request issue... find a working request, find the
failing request, compare the headers... problem solved.

~~~
taormina
That was literally the first thing the author did.

~~~
catshirt
is that how you interpreted it? it's not until paragraph 13 (!) where author
states:

"Josh realised my app might be somehow getting cookies from visiting our site
inside this web view, and then sharing those cookies with AFNetworking's
underlying NSURLSession, which is handling my requests."

which would have been clear if they'd checked the cookies of the NSURLSession
request.

then, in paragraph 17, the author starts concluding:

> "And so the the CSRF check was failing every time, because I wasn't sending
> a Referer header, or any other related CSRF bits."

which would have been clear if they tried comparing a working request to a
failing request.

and finally,

> "And of course, I didn't even know about these cookies, so I wasn't deleting
> them on log out"

which leads me believe the author _never_ checked the request at all, let
alone before anything else.

i'm ignoring the fact the bug sat for months, and took a second person to fix,
and got a write up on the blog... so i'm going to have to assume my advice has
an audience (like anyone who would classify this bug as "bizarre").

(not trying to pass judgement on the author here at all... we have all been
there :))

------
stanleydrew
Not sure about the "fix", since now users can't persist a logged in browser
session?

If you aren't using cookies for API auth, is there not some way to configure
your server framework to just ignore them if received?

~~~
joshsharp
They shouldn't be logging in via the webview within the app anyway, so that's
moot.

We are using cookies, as the post says, as a fallback authentication so devs
can browse the API from a browser if they're logged in to the site.

~~~
eridius
Why are devs using a browser to hit API endpoints? There are much better
tools. My preferred one is called Paw ([https://paw.cloud](https://paw.cloud))
but there are others.

~~~
grkvlt
Because Paw is GBP 39.99 and a browser is free?

~~~
eridius
There are other free tools too, like Postman
([https://www.getpostman.com](https://www.getpostman.com)).

~~~
grkvlt
True, I actually use Postman in Chrome, forgot to mention that.

------
CodeWriter23
Just popped in to say Wireshark would have made short work of this bug.

------
foota
Are they using a header or s.t. for their authorization in app, then?

~~~
joshsharp
Using the Authorization header.

~~~
foota
Thanks for following up! Glad y'all found the bug :)

------
oretoz
Za

