
Stealing passwords from McDonald's users - chx
https://finnwea.com/blog/stealing-passwords-from-mcdonalds-users
======
RKearney
The author of the article removed the disclosure timeline before this was
posted to HN.

The disclosure timeline was something around 5 business days before the author
posted this article. Extremely unprofessional and irresponsible.

EDIT: Original timeline can be found at
[https://web.archive.org/web/20170116061303/https://finnwea.c...](https://web.archive.org/web/20170116061303/https://finnwea.com/blog/stealing-
passwords-from-mcdonalds-users)

    
    
        24 Dec 2016 17:27:56 GMT	Reported the vulnerability to McDonald's via Twitter multiple times (no response).
        28 Dec 2016 21:28:39 GMT	Reported the vulnerability to McDonald's NL via mcdonalds.nl (they couldn't help).
        28 Dec 2016 21:36:12 GMT	Requested disclosure assistance on HackerOne (no response).
        30 Dec 2016 13:04:32 GMT	Reported the vulnerability to McDonald's via phone (they would contact me ASAP).
        05 Jan 2017 23:31:42 GMT	Public disclosure.

~~~
cocoa19
What are your thoughts on what a professional and responsible disclosure time
is?

~~~
btreesOfSpring
Google in their "Disclosure timeline for vulnerabilities under active
attack,"[0] states 60 days for disclosure for discovered security
vulnerabilities and seven days for critical, currently known in-the-wild
security bugs under active exploit.

[0] [https://security.googleblog.com/2013/05/disclosure-
timeline-...](https://security.googleblog.com/2013/05/disclosure-timeline-for-
vulnerabilities.html)

------
jasonkester
This seems to be a common practice, storing UserIDs, Usernames, etc. in
cookies rather than a unique SessionID that can be used to look those things
up (and will expire). I'm curious as to where people are getting the idea to
build things that way.

Because it never would have occurred to me to do so. Or rather, had it
occurred, it would have immediately begged the question of "what happens when
the user monkeys with their cookie". Surely everybody else thinks the same
way.

If so, how do we end up with this? Are there really "Teach yourself in 21
Days" books that have examples with this pattern that people are following?

Or does everybody just assume that they're going to be Facebook with 4000
servers and no way to quickly generate or store or manage or look up those
keys for millions of simultaneous users, and that it's worth the tradeoff?

~~~
ascotan
A couple of rambling thoughts on how we get here:

1\. Lack of experience. Most web devs that's I've met have never even heard of
using expiring session tokens in a cookie. (imho) It's been my experience that
most javascript guys can be relatively young as it's the new teaching language
(sorry python). They spend most of their time learning
react/redux/moxd/angularjs2/vue and just haven't been exposed to security
practices like expiring session tokens in cookie. It's not their fault, it's
just that we don't know, what we don't know. Not realizing that this practice
has been around for almost 20 years, the developer invented a new way of
logging in using cookies.

2\. Most people don't take security seriously. I recently had a conversation
with a dev that was being a cool kid by using JWT bearer tokens. He was
putting admin=true inside the bearer token and signing it. I asked him what
would happen if I stolen his token. Would I become the admin? The answer
appeared to be yes, the software would read the bearer token, inject
admin=true into your session, and give you admin rights on the webserver.
However, he explained the expiration of the JWT token was 1 hour. So I steal
and use your token I only have 1 hour to become admin on your site?, I asked.
Apparently he felt that was good enough.

3\. Security is expected to be provided by the framework. XSS, CSRF, SQL
injection - don't worry we're using Django. That seems to be the expectation
of most people. You don't need to know about security, because the framework
handles that. The problem is that this only gets you so far, there are things
that live outside of the scope of the framework that you probably should know
about, but don't. (I guess storing the user's password in a cookie would be
one of those)

~~~
luhn
I don't see how number two is a security issue. Maybe I'm misunderstanding or
maybe I'm ignorant. If I steal an admin's session token, it follows that I get
to be an admin. How does a JWT with admin=true exacerbate this issue, or how
would any other type of session token mitigate it?

~~~
sebular
Well, the comment you're replying to only described the issue as "being a cool
kid by using JWT bearer tokens", which isn't enough information to accurately
describe what's happening. One can only guess...

A JWT is just a base64 encoded JSON object that has a signature. You can pass
one to any base64decode() function to see the actual data, so the important
part is checking the signature to see whether it's been tampered with.

But the whole "admin=true" part, while it doesn't sound like best practice,
isn't inherently less secure than using the JWT notation for scopes.
"admin=true" might as well be "scope=admin" so the person criticizing the
"cool kid" doesn't seem to understand JWT usage themselves.

What's important is where you sign and verify a JWT: Signing means using a
secret key, which means actually having a secret key stored, which means that
it has to happen server-side.

Proper JWT usage means that both the data creation/signing and data
reading/verifying are always happening on the server, and you've got to trust
the security of your servers, since they have the ability to read your shared
secret key.

So to be secure, you shouldn't really send the JWT to an insecure client like
a web browser at all. Since anyone can read a JWT, you're unnecessarily
leaking information about the inner workings of the app, just giving hackers
important info like the variable names you're checking for.

Instead, the best move is to use key/value storage for hashing your JWT into
garbage and sending that over to the browser. When the user performs an
action, they'll send the nonsense key and the server will retrieve the actual
JWT and verify/perform the actual request handling.

Of course, this just takes the conversation back to session handling. There
are various ways to mitigate the risk of someone stealing another user's
session data and using it to impersonate the user, but those aren't unique to
JWT.

Anyway, the comment above doesn't give enough detail about what the "cool kid"
was doing in order to determine whether it was bad security or not. Sounds
like either a lazy description of the actual scenario, or a poor understanding
of JWTs.

------
vortico
Before reading, I thought this about was stealing information from public
WiFi. After reading, I realize this is for the McDonalds website, but why do
people need a password for their website?

~~~
mwill
Maybe for delivery? I believe some McDonalds deliver, right?

~~~
marak830
They do here in Japan. But I am unsure if there is a login(from most examples
I see here, I would assume they do though).

~~~
tomw1808
God, you live in Japan _and_ you have McDonalds delivery. I am seriously
jealous right now!

~~~
NTripleOne
I've heard delivered Maccy's isn't very good (mind, this was in Singapore, not
Japan) - the food always arrives cold, sweaty and just generally gross.

~~~
dragonsky
I know that over the counter Mackas isn't very good. It's cold soggy and
generally going to disappoint.

------
ipince
Pardon my ignorance, but how are the passwords actually stolen?

If I understand correctly, this exploit lets you execute arbitrary code on the
search results page. And in this case, the code will load up an iframe from a
separate place in McD's domain, get the 'penc' cookie and decrypt your own
password.

So you would still need to send a link to a McD registered user, who clicked
in Remember Password, and then presumably send his/her decrypted password to
your own servers (how?). And also somehow steal their username/email.

Is that correct?

~~~
Orangeair
> Is that correct?

Yes, that's the classic XSS attack pattern. It's like phishing, but better
since you're sending the person a link to the actual website. And once they've
clicked on it, they're already screwed; they don't even need to manually enter
any information.

> how?

Once you have the cookie, its as simple as something like making an
XMLHttpRequest to your own server that includes the decrypted email and
password from the cookies.

~~~
chadscira
If they don't have X-Frame-Options the attacker can also just use a 1x1 iframe
on a popular website or shitty ad network to trigger that page to load

------
pierrec
They still haven't fixed it. I'm only getting it to work in Chrome though,
seems like the Angular sandbox escape doesn't work in Firefox. See for
yourself (I'm only posting the more harmless alert demo, but the others work
too):

    
    
      https://www.mcdonalds.com/us/en-us/search-results.html?q=%20{{x%20%3D%20{'y':''.constructor.prototype};%20x['y'].charAt%3D[].join;$eval('x%3Dalert(1)');}}
    

Then again, I wouldn't expect them to fix it very fast, considering how
abysmal it is to basically store a user's password in a cookie in the first
place.

------
three14
_I tried decrypting my password on the search page using a malicious search
payload, but it didn 't work. Somehow, the cookies contain hidden characters
on the search page causing the getCookie method to fail. The getCookie method
tries to trim whitespaces from cookie values. In the images below you can see
.charAt(0) returns a strange string when executed on the search page._

Note that the author doesn't seem to have checked what the sandbox escape
itself does: it redefines the charAt function to be Array.join, so of course
it produces garbage!

------
ams6110
Probably unlikely that McDonalds built that themselves. I would guess they
contracted it out. It's been a long time since I knew anyone in their in-house
IT division but it was entirely back office stuff not public facing.

~~~
rccrv
They own the company that develops their software[1] as far as I know. It's a
subsidiary.

[1]: This company:
[https://www.rdisoftware.com/](https://www.rdisoftware.com/)

~~~
jgust
They only work on POS & POS data related applications for McDonald's. They
were purchased because of this fact.

------
nihonium
Biggest problem here is their architectural design. They're mixing server side
code with front end. They're printing angular code using back end, but they
are not filtering {} characters. Basically, user can execute any angular code,
therefore any javascript.

~~~
rtpg
Yeah, this problem is basically unsolvable if you wish to have { characters
_anywhere_ in your page from server-side rendering.

\- Have the possibility of {{ and }} in your server-side output (or whatever
symbols you configured Angular for)

\- Have Angular.JS on a page with server-side output

Choose one.

It's important to realize that this affects things like user input as well. So
form initials/form defaults can also be affected by this issue!

A bit of a silly way to fix this problem is to modify your server-side
escaping function (surely you have this!) to "escape" {{ with {<zero-width
space>{. This will mess up things that need to be equal to each other, and can
poison user input (because of form initials) but will protect you from this
issue.

~~~
catmanjan
If you're displaying user input you could just encode to their matching HTML
entities...

&#123; or the human friendlier one &rcurb (?)

~~~
rtpg
that doesn't work because the HTML entity decoding happens before Angular does
the scanning of the DOM for the brackets. So even if you use &rcurb; output
from the server, Angular will still interpret the brackets "properly"

As to why this works this way, consider the following:

do you have to do HTML entity decoding when getting an input value from
Javascript?

------
iancarroll
Their mobile application does or did send their Google GCM API keys to the
client, along with a bunch of other bizarre server configuration information.
I had no way to report it; I tried sending an email to their WHOIS contact to
no avail.

If anyone has successfully reported a vulnerability to them, let me know!

~~~
akjainaj
GCM keys means you can send notifications to other users of the app?

------
pimlottc
So the attack vector here is to send someone a link to the search results page
with a malicious query that injects JS into the page to decode the users
password and then submit it to the attacker's backend collection server? Is
that right?

~~~
xyzzy4
No. A more effective vector would be to send them to a funny video page to
watch, that has nothing to do with McDonalds. And inside that video page you
have a hidden iframe pointing to the malicious query which submits the
McDonald's password to another backend server.

~~~
rasz_pl
meh, make a mcdonalds.com search link that generates "Congratulations, you won
a free mechanically deboned meat product!!1" and share it on bookface.

------
gjkood
As we close the barn doors after the horses have left, we are left to ponder
these two valuable resources for further edification.

[1][https://www.owasp.org/index.php/Cryptographic_Storage_Cheat_...](https://www.owasp.org/index.php/Cryptographic_Storage_Cheat_Sheet)

[2][https://www.owasp.org/index.php/Password_Storage_Cheat_Sheet](https://www.owasp.org/index.php/Password_Storage_Cheat_Sheet)

------
beardog

       They use the same key and iv for every user
     

What dev sits down, starts writing code, and thinks something like this is a
good idea? Not to mention all the other problematic choices.

~~~
ianamartin
You ask this question, but it seems like you don't know how the real world
works.

In a lot of places, you aren't asked to build a product. Especially if your
core isn't technology. You are on a tech team that exists within the structure
of a large organization that really doesn't care about technology at all. It's
just a thing they want on a check list.

So you get asked to throw something together to see if people like it. So you
do. And you don't in your wildest dreams think that this piece of shit is
going to see the light of day. It's just concept.

And then the next thing you know, some assclown decides it's good. Okay great.
But you didn't hear about it because the company is the size of McDonalds. Not
a small startup with 6 people who all know what they are doing.

So ops and infra get together and deploy this toy shit that you thought was
just a joke mostly, and now you have incredible security problems.

That's one way this happens.

There are many others. Reality is a lot more complicated than what you are
trying to suggest.

~~~
mmahemoff
Also, that tech team might in another large organization (not McDonald's) in
another part of the world, where any work they do has to be budgeted for,
agreed on, spec'd, tested, and released through a tedious process.

Someone might be casually thinking "hmmm this doesn't seem quite right" but
there would be a dozen hurdles to jump from that suspicion to getting anything
done about it, so they keep quiet and move onto the next project. They might
never even know or care if their code went live.

~~~
bluedino
>> budgeted for, agreed on, spec'd, tested, and released through a tedious
process

This. You have to spec out even the most simplistic security practices when
you send work to a remote team or they won't get implemented.

------
mholt
I like how the page title changes to "Are you still there?" when you switch to
a different tab.

------
taken_username
Is it legal to publicly post a website security vulnerability? Or in other
words, what is the legal process (let say in US) to notify a website/vendor
that their app/website is vulnerable, without being accused of hacking?

~~~
bertil
There is not clear legal structure, but two practices are commonly advertised
by white-hat professionals:

\- only test your access on your own (test) accounts; as long as then can’t
prove that you accessed someone else’s information, you should be fine;
anecdotally, I have worked for Facebook, where you are not supposed to create
fake accounts; on the white-hat page, you can ask to have test accounts for
that purpose exclusively: those are entirely independent from the rest of the
graph and you are joyfully encourage to try to hack yours;

\- warn the security team ahead of time and tell them without feedback from
them, you will publish the information in X weeks. If what you have found is
valuable, you should hear back fast; if they do not respond, you can argue
that it was their silence who let you know this was not their priority (a
legally dubious argument but most of the community will be happy to criticise
their silence). You are not bound by their response (some corporations can be
very unreasonable) but specifying that you have not hacked any account except
a test one should help you if they throw lawyerese at you.

One way to avoid being caught off-guard by those is to have a bounty program,
but that’s not in security consultants’ hands.

------
quaz3l
This is a real cool way to explain XSS in an easy concrete way. Love the
thought process and actual code examples.

------
martinald
That disclosure timeline is very aggressive over the holiday period.

Did they ever get in touch with you after the 5th?

~~~
beedogs
No excuse. It's the middle of January now, the holidays are long over, and
they're one of the biggest companies on the planet. They had plenty of time to
respond.

~~~
trimbo
> they're one of the biggest companies on the planet

Yeah, making hamburgers! Out of 420,000 employees, they have all of 17 IT jobs
on their career site.

They deserve a break today.

~~~
sneak
> Yeah, making hamburgers! Out of 420,000 employees, they have all of 17 IT
> jobs on their career site.

How many credit cards get swiped/waved per day at their PoS terminals? If they
don't have a 24/7 infosec team they're Doing It Wrong™.

~~~
MichaelBurge
I'm not sure that agrees with the franchise model. McDonald's corporate owns
the real estate, but not most of the businesses. So most of those terminals
aren't actually theirs.

~~~
jessaustin
It's not as if franchisees can just choose to purchase whatever equipment they
want. It all has to come from corporate, so corporate is the place to enforce
security standards.

------
DonHopkins
McDonalds should invent some new characters like the Hackburglar and Cap'n
Crook to educate the public about computer security.

------
revelation
Love the CryptoJS. This is how I store all my own text files on my own
computer.

It's just so bizarre. What were they expecting that to achieve?

~~~
wnevets
It was probably a bullet point that helped sale the agency that built the site
to a McDonalds executive/manager.

------
opcon
Archive/mirror:
[https://web.archive.org/web/20170115144533/https://finnwea.c...](https://web.archive.org/web/20170115144533/https://finnwea.com/blog/stealing-
passwords-from-mcdonalds-users)

------
emmab
Better title would be "Non-persistent XSS on McDonald's website through
AngularJS misuse"

------
fractal618
Is it true that having one set of usernames and passwords makes it easier to
crack a set from another website?

Does every crack, or leak, of usernames and passwords make it slightly easier
to crack all other databases?

because some people still use the same password for multiple accounts.

~~~
nommm-nommm
Yes this has been researched and is true.

[http://www.pcworld.com/article/219303/password_use_very_comm...](http://www.pcworld.com/article/219303/password_use_very_common_research_shows.amp.html)

------
ascotan
So someone wrote an angular app that stores your password in a cookie in your
own browser that is encrypted client-side using cryptojs...

Hmm. Seems on par with the security of pretty much every angularjs site i've
seen. Moving on.

~~~
dotancohen
Why the downvote? This is extremely relevant. There is no 100% security, there
is no reason to store sensitive information (even "encrypted").

Had this been a session token the problem would have been less severe (session
tokens won't be reused on the user's Gmail account for instance), easier to
detect, and easier to mitigate once discovered.

~~~
LukeB_UK
> _Why the downvote?_

Probably because of this:

> _Hmm. Seems on par with the security of pretty much every angularjs site i
> 've seen. Moving on._

------
macygray
Interesting, how many users with password like '123' or 'monkey' has
McDonald's, like 50% ? Because, who will give such a website a normal
password?! ;)

------
reiichiroh
I wonder if this affects MyMcDs.ca in Canada.

------
teemothunder420
ADs are getting smarter

~~~
ribs
What are those?

------
nrjdhsbsid
HN next week: "stealing voucher tickets from Chuck E. Cheese"

Sweet sweet karma from some low hanging fruit never hurt eh? :)

~~~
icoder
The explanation on itself, regardless of 'impact', is already instructive and
worth an HN post, in my opinion.

The timeline at the bottom was informative as well; it shows that even (or
maybe 'especially') for an organisation as big as theirs it is hard to
actually get the problem at the right location in the enterprise, and / or
respond to it and / or solve it.

------
quizotic
Curious! Ten days after a public disclosure, and no statement from McDonald's?
Have they fixed the problem? Do they not know?

