Security model: log in to third-party site with us

2019-02-15 14:32发布

问题:

I develop a service (Service) which automates certain actions that users can do on another third-party site (3rd Party Site).

My service provides the following functionality for the users:

  • the user registers at the Service

    1. the user provides his/her 3rd Party Site username/password to the Service
    2. the Service uses that credentials to log in to the 3rd Party Site on the user's behalf
    3. the Service stores the cookie issued by the 3rd Party Site in its database
    4. from now on, the Service starts to log in to the 3rd Party Site regularly (cron) on the user's behalf by using the previously stored cookie (the username/password for the 3rd Party Site is not saved anywhere) and performs some actions on the users behalf on the 3rd Party Site

Notes:

  • before registering on the Service, the user is presented with the full information describing the interaction between the Service and the 3rd Party Site
  • there is a certain value in automating the user's login to the 3rd Party Site and users are interested in automating their logins and certain actions on the 3rd Party Site, i.e. they are interested in the Service doing some work for them at the 3rd Party Site
  • there is no OAuth functionality on the 3rd Party Site
  • there is no any user authentication token functionality on the 3rd Party Site

I have made a research here at Stack Exchange and I have not found any solutions:

  • https://security.stackexchange.com/questions/1335/storing-third-party-auth-info-securely
  • How save password of a third party application in my app for use with a api?
  • How to securely store passwords used to log in on third party websites
  • Rails storing third party credentials.. Anyone know best practice?
  • http://12factor.net/config
  • https://security.stackexchange.com/questions/31535/need-to-ephemerally-store-third-party-password
  • i *must* store third party credentials in my database. best way?
  • how to securely store a password for a 3rd party service in django?
  • What is the best way to store password in database when API call requires sending of password in plain text?
  • django & facebook: security & design for a facebook webapp that performs a third party login on behalf of the user

Moreover, from reading through the provided questions and answers I tend to think there is no way to secure the user's login data (passwords or 3rd Party Site cookies). I.e. if an attacker gets an access to the Service's server, the attacker gets the access to the users' accounts on the 3rd Party Site as well.

If I try to store the 3rd Party Site's cookies in the Service's database encrypted, then they will be only useful to the script that decrypts them. Therefore, to get access to the 3rd Party Site user account, the attacker would need to not only get an access to the Service's machine, but to modify the script (step 4) as well.

Storing a cookie for the 3rd Party Site on the Service is really similar to OAuth, but in this case a cookie used instead of a token (no passwords are stored).

What is the way to design a security model/architecture to securely store user's login data at a service to allow the service to login to a third-party site on the user's behalf regularly without manual interaction with the user?

P.S. I use Django, but I guess that the security model/architecture does not depend on a certain technology stack.

回答1:

To state the obvious: The important thing here is of course to not let an attacker on your site get access to all the cookies. You cannot completely protect against this, since your service will need access to the cookies (in unencrypted form) regularly. An attacker that has completely compromised your server will in theory be able to do anything your service can do, so if it is possible for your service to get access to the cookies, then an attacker with all rights will also be able to get access to them.

If you still want to do this, you should

1) make it more difficult for an attacker to get access to the cookies

Just to give you an example of how you can think about this: If your system is compromised, it is likely that the attacker will get access to your file system. If the cookies are stored in plain text on files, the attacker will have an easy time. Storing them in a database is better (and probably what you want to do anyway), but not much better unless you protect access to the database in some way. A dedicated attacker will not have a hard time if i.e. the password to the database is stored in the applications configuration file.

A solution that would improve the situation quite a lot would be if the cookies always was encrypted except just when you need them. The best solution would be if the encryption key was not stored in an application log, but was provided (typed in) by an operator every time the server is restarted. To break this the attacker would have to read the memory of the application (not impossible at all, but still more difficult).

Another measure would be to store the cookies in a separate database on a dedicated server and limit all access to this server to what is needed.

A complete strategy for this requires more intimate knowledge of your exact physical and logical setup.

2) create mechanisms so that it is likely that you can detect if the cookies was compromised

This is almost equally important. If this happens, you want to know and be able to take action immediately. There are of course standard IDS systems that can be used. You may also create more targeted systems that applies to your spesific application. The system could i.e. detect if someone is running an sql that scans the whole database table with cookies. Since you know how your own application normally behaves, you can also create a monitoring system that can detect if something that is not normal happens.

3) prepare a system for quickly invalidating all cookies if you detect that they are stolen

The third party services does probably have an option to log out and by that invalidate the cookies. You should prepare a job that does this for all your stored cookies that you can easily activate. Think about the difference in telling your users that someone may have had access to their service in 10 minutes before you disabled all cookies and telling them that someone still have access to the third party service and you don't know how to stop them.

In addition to this, it is of course important that your users understand what they do when they give you access and that the provider of the third party services approves of this. It is not obvious that a third party service provider will allow this kind of access. If they do, they may also help you with creating a special session cookie that is i.e. bound to your ip address.



回答2:

Your question seems to ask specifically about how to "securely store" the credential information, so let me address that narrow aspect of the question first.

Securely Storing the Credential Information

The only information to store is the cookie, which is obtained in clear text form, and needs to be used in the future in a clear text form. This leaves you with no option but to use a 2-way encryption, using a certain "secret". To make the scheme secure, you just need to secure your "secret", preferably by embedding it in a compile executable module (e.g., using a compiled language like Java). This way even after an attacker gains access to your entire machine, he/she cannot decode the cookie, except to run your program and use the decoded cookie using the logic built into your compiled program.

Overall Architectural Consideration

If the question is about an overall architecture though, without OAuth or some types of token support, your mechanism is not going to be reliable. Because the "Service" would expire the cookie, and you'll need to constantly use the cookie to visit the service, and convince the "Service" to never expire your session (hence the cookie). Even if you do this, hour or days later, or when the "Service" restarts, your cookie will cease to be valid, and your access will be denied.