2

Is it possible to safely include a password in a query string for a c# asp.net site.

Few assumptions and things I know -

  1. The site does not and will not have links/images/javascript/analytics to/from other sites. So no referrer links to worry about.
  2. ALL communication with the web browser will be over https.
  3. I know that the query string will remain in the history of the computer.
  4. More than just the password/username is needed to login. So simply pasting the url back into the browser will not result in a login.

I know the site may be susceptible to cross site scripting and replay attacks. How do I mitigate these?

Given the above scenario, how should I include a password in a query string?

Please don't ask me 'why', I know this is not a good idea, but it is what the client wants.

tom
  • 1,822
  • 4
  • 25
  • 43
  • 4
    Why would you want to do this? – Oliver Charlesworth Jan 19 '13 at 00:46
  • If it's over TLS, why would you not just use HTTP auth? – Kirk Woll Jan 19 '13 at 00:46
  • 1
    If the password had a limited lifespan you might mitigate some negative effects – Jason Sperske Jan 19 '13 at 00:48
  • @OliCharlesworth I have asked that too, but it has to be done this way for now. – tom Jan 19 '13 at 00:48
  • @JasonSperske unfortunately the lifespan of the password is long – tom Jan 19 '13 at 00:49
  • 1
    If you really have to do this, you could possibly encrypt it with a key. This way you have some sort of secuirty – tam tam Jan 19 '13 at 00:49
  • 6
    Well encrypting it wouldn't make any difference from the perspective of the hacker, they just need the URL history to break in – Jason Sperske Jan 19 '13 at 00:50
  • @tamtam I have looked at encryption, but it is such a specialized topic that it is very hard to know what type to use or to find 'industrial strength' examples. – tom Jan 19 '13 at 00:51
  • What if you used the password to generate a salted hash of the URL you want to request. Then it would work like a digital signature, but only the two parties who knew the password could safely generate it – Jason Sperske Jan 19 '13 at 00:52
  • @JasonSperske More than just the password/username is needed to login. Simply pasting the url back into the browser will not result in a login. – tom Jan 19 '13 at 00:53
  • @tom: What else is needed? Put another way, what is the purpose of putting the password in the query string? – Oliver Charlesworth Jan 19 '13 at 00:54
  • @OliCharlesworth the user has to answer some questions. Those are posted back to the server. – tom Jan 19 '13 at 00:55
  • 1
    @tom: Ok, so that implies the server is session-based? Which in turn implies there's no need for the password to be in the query string. Forgive me for driving this round in circles, but these requirements don't really make sense, so it's hard to come up with a meaningful response... – Oliver Charlesworth Jan 19 '13 at 00:56
  • 1
    @OliCharlesworth There shouldn't be a need to do this! But there is for the scenario and the client insists. I just have to do it as best I can in this very difficult scenario. – tom Jan 19 '13 at 00:57
  • Can you make POST request instead of a GET request? – Reactgular Jan 19 '13 at 01:07
  • @MathewFoscarini no, the client wants it in the query string. – tom Jan 19 '13 at 01:09
  • @Tom that sucks. I modified my answer to include encryption. – Reactgular Jan 19 '13 at 01:34
  • I do not understand why you need to have the password on the url, but not used to login. This have no logic. – Aristos Jan 19 '13 at 01:52
  • [How Secure Are Query Strings Over HTTPS?](https://blog.httpwatch.com/2009/02/20/how-secure-are-query-strings-over-https/) is an interesting article. – Nic Wortel May 05 '14 at 07:00

2 Answers2

7

SSL

You can safely send the password to a web server using a SSL connection. This encrypts all the communication between the client/server.

Hide In The Header

Basic authentication protocols place the user/password information in the HTTP request header. C# and many other web server languages can access this information, and use it to authenticate the request. When mixed with SSL this is very safe.

Register An Application Key

If none of the above is possible, then it's recommended that you create a unique key for each user. Rather then send their password this key is used. The advantage is that the key is stored in the database and can be removed. The user's password remains unchanged, but they must register again to get a new key. This is good if there is a chance someone could abuse their key.

Perform Hand Shaking

Hand shaking is where the client makes a request to the server, and the server sends back a randomly generated key. The client then generates a hash from that key using a secret, and sends it back to the server. The server can then check if the client knew the correct secret. The same thing can be done where the password is the secret instead and the client includes username details in the request. This can authenticate without ever sending the password.

Encrypt Password

If none of the above are possible options, then you could attempt to use JavaScript to encrypt the password before it's sent via an open URL. I found an open source version the AES block cipher. The project is called JSAES and supports 128 to 256 bit encryption. There might be other JS libraries that do the same thing.

Community
  • 1
  • 1
Reactgular
  • 52,335
  • 19
  • 158
  • 208
  • 2
    OP asked how to safely include the PW in query string ... encrypting the password requires a new secret (which the password already was), which loops the problem back upon itself (how will the key be safeguarded and transferred to decrypt the password)? – Darrell Teague Jan 11 '16 at 21:12
  • @ThinkingMedia https (SSL/TLS) encrypts the querry string. Only the URL address is left in the clear. – zaph Jan 11 '16 at 23:02
  • Use the public key to hash the password and send it to the server, and use the private key to generate the key that is matched in the database for the password column. No actual password text is used in this process, and you can generate public keys on the fly so that the hash is constantly changing. It's basically a more complicated way of sending MD5(my_password). Since anyone could figure out the original password using the MD5 as a guide. Encryption just makes it very difficult to reverse the hash back into the original password. – Reactgular Jan 11 '16 at 23:06
  • When you use MD5(password) it generates the same hash for each password, but encryption will generate a different hash every time for the same password. That's why the server needs to use the private key to generate hash that is consistent for that password. – Reactgular Jan 11 '16 at 23:08
  • While the overall answer is not recommended, what @Reactgular had to say has merit (using PKI) ... except it is exceedingly expensive and complicated to generate new public/private key pairs so would not do that. For general encryption cases, using hybrid encryption (random symmetric key for payload, RSA for encrypting key for known target) My answer here is germain: https://stackoverflow.com/questions/44391/how-do-i-prevent-replay-attacks/12472337 – Darrell Teague Aug 11 '20 at 18:56
2

It is generally not advisable to put secrets in a query string, which can then be book marked and copied, exposing the password at-rest in history files, cookies, etc.

To just safeguard the password in this use-case, an option would be to hash the password (one-way, not reversible). In this way, the actual password is not known in transit nor at-rest but... it implies that an attacker can still use the hashed value to login to the server that would presumably compare the hash value to its store for authentication.

Update: Switching to stateless (JWT) sessions

In the olden days when buggies were a thing (okay - they are still a thing with some fringe groups but) - we used "sessions". A "session-ID" (see JSESSION_ID) for example in Java/J2EE/Servlet based systems was stored as a cookie. That value, being a random number, was hard to guess - but it had problems from hijacking to memory and lookup overhead on the server.

In 2020 times (as of this writing) ... JSON Web Tokens (JWT) can be used to securely encapsulate the user-session information and be pushed back down in an immutable cookie without ever exposing the password and with very little server overhead.

In this model, after login, the server issues a token (using OAUTH2 or related), which has an expiration time-stamp.

This data and possibly other session information can then be encrypted, hashed, signed and wrapped up in a JWT (token) - as a cookie back to the web-browser.

Ref: https://oauth.net/2/jwt/

At this point, the client cannot do anything to compromise (or even view) the cookie because any sensitive data should have been encrypted (using AES256 et al or better) and the contents hashed and the hash signed. What this means is that when the server gets the token back, it looks at the timestamp and may throw it out - forcing re-authentication and then...

Can otherwise verify it signed the content, hash the contents and verify the hash and decrypt data if needed (which would not include the password but rather just the ID of the user - which is verified and not necessarily a secret per se).

This can include already-looked-up scopes (authorization) for what the user can do etc - avoiding round trips to the authentication server until the token times out.

Thus the above (using JWTs, hashing, signing, encrypting - into a cookie) is the recommended way to both go stateless and avoid passing around a secret between the client and server.

Ref: https://auth0.com/blog/stateless-auth-for-stateful-minds/

Additionally, consider that multi-factor authentication schemes (see Google authenticator) and related systems are a much stronger security posture (stealing password is not enough and the keys auto-rotate on external systems) but do require semi-frequent access to the rotating key system, which inhibits a smooth user experience to some extent.

Update: Multi-Factor auth by Google and others has gotten much better.

Older companies still use SMS one-time-passwords (OTP) ... which can be compromised by going to a wireless company store and claiming SIM card loss (given a known phone-number). Google and other more advanced companies comparatively use rotating tokens that can be embedded in a smartphone app that then are used for many services. Google even has push-notification where user just confirms by button press: "Yes - it is me".

Darrell Teague
  • 4,132
  • 1
  • 26
  • 38