How can I hack my own Web project?
Recently I got a call and asked to help deal with very strange symptoms on the site. And the symptoms looked like this. Completely different clients called and told that they on the site get into the personal accounts of other random customers. Login by yourself. Enter your account, and then bam - and already in the account of another client. True, they did not realize that someone else could also be in their personal account.
Let me tell you a "failure story" so that others do not step on this rake.
I’ll try to reveal the details of what happened in the detective story. Particularly clever guess in the middle of the story where the problem crept in.
The project has user authentication. A classic scheme is used with a randomly generated session ID, which is set in the cookie of the client browser. On the server, session data is stored in memcached, because Application servers are several.
Obviously, the clients did not crack each other, the password for all of them was the same suddenly not set. At first glance, some kind of difficulty happened with user sessions - they began to fall into each other's sessions. But how? Since it is not yet clear, you can try restarting memcached so that all sessions are reset. Yes, not very humane - users will have to log in. But restarting memcached did not solve the problem.
They began to dig into the logs and it is really evident that, for example, a certain client always went to the same IP address, and now all of a sudden his actions are logged from a bunch of different IPs. Moreover, more importantly, it is in the authentication logs (when the client enters the username and password) that this client logged in only from his usual IP address. We conclude that when a client becomes another client, this does not happen through authentication, but he specifically gets into the session of another client (facepalm).
Did you change the code? No, they did not release anything. Migrated servers? Well…. they only included image caching in Nginx, which were not given as static (static has long been cached), but generated on the fly. But they do not change. Those. There is an endpoint of the form: / path / image? id = NNNN In fact, it is almost like a static, because a picture with a specific id will never change. Therefore, in order to optimize the resources of Application servers, they also decided to cache such requests.
Since I wrote about this, it is important. And because didn’t change anything else, it’s almost obvious that the problem is with this caching. Caching of course was turned off, but the problem did not go away.
So how did such caching suit the leapfrog on the site?
Here are a few more introductory (implementation details).
- The project implements the "auto-create sessions" approach. Those. if a client arrives that does not have a cookie that stores the session ID, then Backend will generate a session ID in response to ANY request and in the response headers there will be a Set-Cookie setting the session cookie . The same thing happens with requests to / path / image? Id = NNNN
- Pictures are given including to unauthorized customers.
Here you can already guess what happened ...
And the following happened. An unauthorized client arrived without session cookies. The GET request for the image / path / image? Id = NNNN is gone , which in response generated a session ID and, “ tearing our hair out ”, cached! Yes, it was cached along with the Set-Cookie header setting the cookie with a specific session ID. Then other victims come, get the same picture along with the SAME ID of the session , which they have forcibly rewritten in the browser. As a result, we have a bunch of users who have the same session ID in browsers in cookies.
It turns out that the client is authorized - his session. Then another client logs in and now in this session we have a second client. The first one is enough to refresh the page and he is already in the session of the second client. Now imagine the madness that was observed when a bunch of customers "lived" in one session.
Well, you understand that one of the goals of viruses is to steal cookies with session IDs so that an attacker can remotely replace my session and work on behalf of the victim. And here you don’t need to steal anything - everyone has one session ID. The site went into "single-user" mode.
Yes, of course, you still need to bind the session to the IP address, User Agent, etc., then such a leapfrog would not have happened. But nothing was done.
But the story does not end there. An inquisitive reader should go read the Nginx documentation on caching and find this:
response with the “Set-Cookie” header will not be cached .
Yeah, why was Set-Cookie cached in this case? There is one more nuance of the project: the engine in each answer makes a Set-Cookie for other needs that are not related to the session ID. Including when giving a picture. Therefore, in order for caching to work, the Nginx config also had the following parameter:
proxy_ignore_headers Cache-Control Expires Set-Cookie;
It was because of this cookie that it was cached.
In order for the story to be instructive, you need to talk about how to do it correctly in terms of Nginx settings. Specifically, in this case, the addition of
should solve the problem.
PS What is Backend written on? It seems to me it does not matter. "Auto-create sessions" can be present on any platform. Sometimes it is useful and simplifies life, and sometimes it is dangerous. Think with your head and everything will be fine. The story is more about the features of Nginx configuration.
PPS This is not a success story. This is the story of stuffing cones. The project developers are aware of the weaknesses in architecture that led to the described incident. Therefore, a big request in the comments not to develop the topic of which developers and admins are stupid, and you would have foreseen everything with 20 years of experience and did not step on this rake.