[HN Gopher] Lenovo Forums stores plaintext password as a cookie
___________________________________________________________________
Lenovo Forums stores plaintext password as a cookie
Author : ashitlerferad
Score : 189 points
Date : 2022-04-22 13:05 UTC (9 hours ago)
(HTM) web link (forums.lenovo.com)
(TXT) w3m dump (forums.lenovo.com)
| T3RMINATED wrote:
| mooreds wrote:
| I just tried to replicate this issue (because I wanted to see it
| in action).
|
| I was able to sign up and sign in repeatedly. I never saw a
| 'RMEPass' cookie set, nor was I able to click 'remember me'.
|
| So it seems like they have fixed at least one part of this issue.
| aendruk wrote:
| Or mitigated the issue by disabling the affected feature.
| mooreds wrote:
| Fair, hard to know which.
| megous wrote:
| As long as it's a http only secure cookie... it should not be a
| huge issue. Session ids are basically replacement for
| username+password anyway, and nobody cares they're stored in a
| cookie. Server knows the plaintext password already, too.
|
| So the only remaining issues are security issues around sharing
| your computer with other people, or programs. I guess stealing a
| session id is mildly less problematic than stealing the password
| in case the password is re-used elsewhere.
| [deleted]
| briffle wrote:
| Server knows the plaintext password already, too.
|
| Servers should NOT be storing passwords in plaintext, ever.
| This has been clear for at least 20 years now. You should only
| store a salted hash of a password, and please, do not roll your
| own. Use one of the many popular libraries for this.
| VWWHFSfQ wrote:
| The server knows the plaintext password in order to hash it,
| salt it, and compare it. How else would it do that
| p0sixlang wrote:
| I thought it could get hashed client side
| VWWHFSfQ wrote:
| Then the hashed password is effectively the plaintext
| password
| thamer wrote:
| It's not the same. If you the un-hashed password leaks it
| can often be used to authenticate on other websites since
| people reuse passwords. You can't do that if all you have
| is the hashed password.
| alophawen wrote:
| Does it matter when you can use the hashed password to
| log in?
| jaywalk wrote:
| I think you missed the _other_ websites reference. If you
| 're at the point of being able to steal the table of
| users, you're probably not too concerned about using the
| credentials to login to that website.
| sascha_sl wrote:
| Except, if you run rounds on the client and server, you
| now never handle plain passwords (that users might be
| reusing) and reversing the thing you store into something
| you can use against that services' API is still just as
| hard (if not harder because you need to do either do the
| total rounds on plain or the server rounds on a very long
| input)
| lxgr wrote:
| Not if it's scoped to the username/domain in some way
| (e.g. by making the client-sent value H(password,
| username, domain) rather than just password or
| H(password)).
|
| But that would require a canonical and secure (i.e. not
| (only) controlled by server-fetched code) way of client-
| side password preprocessing, and if you have that, you
| can just as well use a PAKE, modern instances of which
| have all of these nice properties and more.
| unethical_ban wrote:
| Not always. The client could salt and hash the password
| before sending it to the server for storage and comparison.
|
| To be clear: a properly designed system can and should
| operate without the server ever knowing the plaintext
| password.
| sascha_sl wrote:
| The browser can do it too, Keybase handled passwords like
| that.
| titaniczero wrote:
| No, the server doesn't "know" the plaintext password, the
| server knows the hashed password and the salt. The
| plaintext password is in memory during your login request's
| lifetime, once it is hashed and compared against the stored
| hashed password, the plaintext version no longer exists on
| the server.
|
| Very different case from storing them in plain text in the
| database or elsewhere.
| VWWHFSfQ wrote:
| If the plaintext password traverses the server's memory
| space then yes it "knows" the plaintext password. A
| nefarious server administrator can do whatever they want
| with those plaintext passwords.
| lxgr wrote:
| There is a large difference in attack surface there,
| though:
|
| Passwords stored unhashed in a database fail
| catastrophically and irrevocably against a point-
| compromise attacker. Hashed passwords, validated using
| plaintext passwords, only leak all passwords entered
| since the moment of compromise.
| VWWHFSfQ wrote:
| I'm certainly not denying that. But to try to claim that
| the server doesn't know the real password is completely
| false. Whether they hash/salt the stored value is
| completely irrelevant to the point that you have to trust
| the plaintext password handling end-to-end since the
| server can do anything it wants with your real password.
| stefs wrote:
| it's not about nefarious server administrators, it's
| about an attacker getting in, dumping the database
| content, logs and whatever else they can grab. they then
| search those for valuable information they can sell -
| like email addresses, username+password combos, payment
| info, the likes. those are then bundled and sold on the
| darknet to spammers and phishers.
|
| if the credentials are in the logs they'll harvest those
| to attempt logins on other sites.
| megous wrote:
| Servers routinely handle plaintext passwords when
| authenticating. They may not store it, but it's not something
| that is invisible to them, unless using some auth method that
| uses challenge/response instead of plaintext passwords. Most
| web apps use plaintext password auth.
| Kwpolska wrote:
| There is a difference between the plaintext password being
| stored in memory and in a database. One is just how things
| work (the client browser needs the password in plaintext as
| well), and another is a security breach waiting to happen.
| adolph wrote:
| > There is a difference between the plaintext password
| being stored in memory and in a database.
|
| Yes, if you already got in, then reading RAM for active
| users is much more convenient than exfiltrating a bunch
| of potential trash accounts.
| pdpi wrote:
| Any non-brain dead design will keep the password around
| only long enough to hash it and compare that to the store
| hash, and then promptly get rid of it. You can't just
| read passwords from memory as if it were an open book.
| alophawen wrote:
| You don't have to hold clear-text data around for very
| long for it to be exfiltrated.
|
| And noone said clear-text passwords would just stick
| around in ram.
| Dylan16807 wrote:
| Your first sentence seems to describe sticking around and
| your second sentence says nobody claimed they would stick
| around?
|
| But more directly, "reading RAM for active users" as a
| method of gaining passwords, written in context as a
| direct consequence of "the plaintext password being
| stored in memory", sure sounds to me like a claim that
| they're sticking around.
| pdpi wrote:
| If my password is only ever kept in RAM during my login
| process, there's a small window of time where it can be
| exfiltrated, it's only really at risk if there is an
| attack in progress while I'm logging in. Persistent
| storage is always susceptible to exfiltration.
|
| Nothing is ever 100% secure, but we can limit the
| exposure, and the blast radius when you do get breached.
| blenderdt wrote:
| Yes. It is not easy to 'logout' when the browser knows your
| basic auth credentials. Even if the server sends a new cookie
| that will overwrite the basic auth cookie the browser might
| send it again.
| mooreds wrote:
| Session ids != usernames/passwords.
|
| Not even close. Why?
|
| * Re-use across sites: people unfortunately reuse passwords
| across services. That means that getting access to these
| cookies would be great for credential stuffing attacks. A
| session identifier is no use for that type of attack.
|
| * Re-auth across devices: you can't typically exchange a
| session for another session on a different device, but you sure
| can do so with a password.
|
| * Session ids can be revoked with less user impact (they have
| to log in again). Passwords can be revoked too (it's a password
| reset), but it impacts users far more.
|
| As other comments mention, passwords should be manipulated in
| memory, only stored hashed and salted by a strong algorithm,
| and seen by the bare minimum of software. Preferably handled by
| software designed for handling passwords and other sensitive
| credentials. There are commercial options, free options, and
| open source options.
|
| (Full disclosure, I work for an auth company.)
| nirui wrote:
| There are considerations on the performance as well.
|
| Usually, a responsible website will password-hash the plain-
| text password into a hashed string before saving the hashed
| string into their storage. Password-hash is a special hashing
| process designed to be reasonability slow, so an attacker who
| somehow obtained the hashed string cannot easily collide the
| hash with another plain-text.
|
| Some password-hash configuration can took few milliseconds to
| run, that's really expensive if you have to do that for every
| request just so you can compare the client password-hash v.s.
| the one stored on your server.
|
| (Full disclosure, I designed few session manage systems for
| my job before :D)
| mooreds wrote:
| That's a great point. Hashing makes it more painful to
| credential stuff. I had a colleague write a few thousand
| words on the topic: https://fusionauth.io/learn/expert-
| advice/security/math-of-p...
| megous wrote:
| * Re-auth across devices: you can't typically exchange a
| session for another session on a different device, but you
| sure can do so with a password.
|
| Ever had Google deny you access for a perfectly valid
| username/password combo when loging in from "unfamiliar"
| location? :) Or a bank ask you for SMS code when logging in
| from a different browser?
|
| It really depends on level of paranoia of the authentication
| system. You can have user device validation even with
| username/password, and you may not have it for session IDs in
| a different implementation.
| mooreds wrote:
| That's a fair point. I guess I was speaking in the more
| general case, but yes, you can have multiple layers of
| authentication and it is super implementation dependent.
| Everyone has their own threat model (hopefully!).
|
| (I wrote a few thousand words on MFA a year or so ago:
| https://fusionauth.io/learn/expert-
| advice/authentication/mul... )
| dankboys wrote:
| Not in any way a web dev, but couldn't an XSS on Lenovo's site
| make it possible to leak these?
| 0des wrote:
| it's all the same- biscuits, macaroons, maybe next we can do
| churros or something.
| skeeks wrote:
| And what if the server is compromised in the future? It is
| trivially to then extract all the cookies and send them to a
| attacker-controlled server. The attacker then uses those
| password to try to login on different platforms.
|
| After initially setting a password, the database/server should
| only store a salted hash.
|
| No exceptions.
| megous wrote:
| If server is compromised, passwords are compromised too
| regardless if they are hashed or not.
|
| I can selectively deauth a user to make them login again in
| short order and take his password.
|
| It depends on the level of compromise, of course.
| Tepix wrote:
| If it's a short breakin where someone manages to dump the
| DB it makes a big difference.
|
| Strong hashes are the way to go.
| invokestatic wrote:
| Nothing stops a hacker from siphoning all the credentials
| from a login page either. Servers have to handle plaintext
| passwords regularly.
| djtriptych wrote:
| but only ever in memory. writing to disk is the issue here.
| UncleMeat wrote:
| But there is no evidence that they are writing the
| passwords to disk.
| djtriptych wrote:
| I'm talking about authenticating servers in general, not
| just lenovo.
| lxgr wrote:
| They are writing the passwords to _users '_ disks at
| least, which by itself is already really bad and easily
| avoidable.
| UncleMeat wrote:
| How is that bad?
|
| If you've got malware on your machine then you are
| already fucked. Desktops don't tend to have strong
| process isolation that keeps malware from reading a
| password in flight anyway.
| [deleted]
| foobarbecue wrote:
| No. Servers should never see the actual password. What case
| are you imagining where they need to?
| coder543 wrote:
| > Servers should never see the actual password.
|
| Are you _actually_ doing client-side hashing in addition
| to hashing on the server side? Otherwise, yes, the server
| does see the password. In most applications, a
| compromised server could just serve a login page that
| doesn 't do the client-side hashing anymore if the
| malicious actor wanted to collect credentials, so I don't
| see how this added complexity is really adding any
| security.
|
| The real way to add more security is to minimize
| dependence on passwords by implementing a better, second
| factor of authentication, such as TOTP, WebAuthn, SSO, or
| even SMS or email tokens. Unless a person is using a
| password manager to generate their passwords, then
| passwords are almost always terrible and weak, and
| usually reused across sites. More of my opinion is shared
| over here[0].
|
| [0]: https://news.ycombinator.com/item?id=30559443
| CorrectHorseBat wrote:
| >In most applications, a compromised server could just
| serve a login page that doesn't do the client-side
| hashing anymore if the malicious actor wanted to collect
| credentials, so I don't see how this added complexity is
| really adding any security.
|
| That takes much more time and requires the attacker to be
| able to, unnoticed, change the served data.
| coder543 wrote:
| "Much" more time? Do you have any sources to back that
| up? Why is combining client-side and server-side hashing
| not commonly considered best practice if it's so great?
|
| I don't agree at all. Login pages are static, since they
| don't need to be customized per user, because the users
| aren't logged in. Anyone could easily prepare a modified
| login page before compromising the underlying system, and
| swap it in immediately after compromise. The added
| implementation complexity for the original developer is
| simply security theater.
|
| Client-side hashing of passwords is actually a dangerous
| thing to recommend, in my opinion, because a lot of
| developers would assume that it removes the need to also
| hash on the server-side. At which point, they would
| literally be storing the _actual_ password in plaintext
| in their database, since the client-side hash _is_ the
| password.
|
| Client-side hashes also aren't going to have a per-user
| salt, which means that an attacker can just use a rainbow
| table to reverse the hash of most passwords... making it
| _even less_ worthwhile. The attacker doesn 't _even need_
| to change the served content, but they certainly _can_.
|
| As I mentioned in my previous comment, and I will repeat
| it here, _real_ benefit to authentication security only
| comes from adding 2FA or SSO. Don 't waste your time on
| security theater.
| Dylan16807 wrote:
| > As I mentioned in my previous comment, and I will
| repeat it here, real benefit to authentication security
| only comes from adding 2FA or SSO. Don't waste your time
| on security theater.
|
| In theory there's also convincing browsers to implement a
| zero-knowledge protocol like SRP.
| coder543 wrote:
| How is SRP materially better than WebAuthn, which is
| intended to be able to be used as a single factor
| authentication mechanism? (Unlike U2F)
|
| If SRP depends on a user to choose a password or to enter
| it only on the correct website, then it will be
| substantially less secure than WebAuthn, because users
| pick bad passwords and phishing can be very effective.
| WebAuthn sidesteps both of these issues entirely.
| Dylan16807 wrote:
| If you're using a different computer from normal, and
| don't have a hardware token or don't have it with you,
| you can't use WebAuthn.
|
| When it comes to systems that have passwords, a zero
| knowledge protocol should be best at keeping it safe, and
| while moving password entry out of websites and into the
| browser isn't a great protection against phishing it's a
| lot better than nothing.
| coder543 wrote:
| > If you're using a different computer from normal, and
| don't have a hardware token or don't have it with you,
| you can't use WebAuthn.
|
| This applies to literally all authentication schemes that
| use something beyond a password, including TOTP and SMS
| codes. It's also kinda the point. An attacker will have a
| much harder time impersonating you.
|
| You can use WebAuthn with just the fingerprint reader on
| your laptop or smartphone, or FaceID on iPhone. You don't
| _need_ an external hardware token, but those do work as
| well. You might even be able to use WebAuthn with your
| computer's TPM using just a PIN instead of biometrics,
| but I've never bothered to check, because I've never
| wanted to do it that way.
|
| A password by itself isn't good enough anymore, so your
| argument in favor of SRP isn't convincing, and I'm sure
| this is why browsers have never bothered to implement it.
| Making passwords slightly better doesn't even come close
| to fixing them.
| Dylan16807 wrote:
| > This applies to literally all authentication schemes
| that use something beyond a password, including TOTP and
| SMS codes.
|
| Yes, and?
|
| It's still a "real benefit" to passwords if they can't be
| stolen.
|
| Even if you do have an independent second factor, that
| means you still have a password. Surely you want to
| protect that password better, on top of the second
| factor?
| coder543 wrote:
| WebAuthn is designed to be able to be used as a strong
| single factor. You do not need a password. It cannot be
| MITMed or phished or leaked by server compromise. See an
| example here: https://webauthn.io/
|
| > It's still a "real benefit" to passwords if they can't
| be stolen.
|
| SRP does _not_ mean passwords can't be stolen. It just
| means that the backend of a particular website is no
| longer capable of stealing the password, as long as the
| user is careful to only use their browser's (currently
| nonexistent) SRP dialog box.
|
| The user's computer can still have a keylogger on it.
|
| The user can still be phished.
|
| > Surely you want to protect that password better, on top
| of the second factor?
|
| No, I want passwords to just go away. They add extremely
| little security on average. Power users like us might use
| strong, unique passwords, but almost no one does that in
| the real world. Protecting the password "better" doesn't
| matter when the user also uses that same, weak password
| on a dozen other websites already.
|
| SRP does not solve the actual problems people are facing,
| which is surely why browsers don't support it. It's a
| cool idea (honestly!), but it's a solution in search of a
| problem now that we have WebAuthn.
|
| If SRP is so beneficial even today, why don't browsers
| implement it? They implement _so much_ other stuff.
| You're implying quite a conspiracy, which doesn't make
| sense when it "compromises" the security of passwords
| going to Google and Apple just as much as it does
| everyone else. The "real benefit" appears to be lacking.
| Dylan16807 wrote:
| > SRP does not mean passwords can't be stolen. It just
| means that the backend of a particular website is no
| longer capable of stealing the password, as long as the
| user is careful to only use their browser's (currently
| nonexistent) SRP dialog box.
|
| Yes, sorry. Less likely to be stolen, and can't be stolen
| _by the server_.
|
| > No, I want passwords to just go away.
|
| That's fine and dandy but it's moving the goalposts
| significantly.
|
| I'm not going to disagree with your desire to get rid of
| passwords. But your initial premise was that second
| factors are good, and in that context it's also good to
| add more protection to passwords directly.
|
| > If SRP is so beneficial even today, why don't browsers
| implement it?
|
| I said it was better, not that it's the most amazing idea
| in the realm of security.
|
| Also when browsers implement optional security features
| they tend not to get website support.
|
| > You're implying quite a conspiracy
|
| No I'm not, don't be weird.
| coder543 wrote:
| I like how you completely ignored my statement about
| WebAuthn not needing a password. My original question to
| you said you didn't need a password: "How is SRP
| materially better than WebAuthn, which is intended to be
| able to be used as a single factor authentication
| mechanism?"
|
| WebAuthn as a single factor means there is no password or
| TOTP or anything else. Just WebAuthn.
|
| You can go back to my very first comment where I said
| "The real way to add more security is to minimize
| dependence on passwords". I tried to be clear from the
| beginning that passwords aren't the answer, in my
| opinion. Yes, people are psychologically accustomed to
| having a password in addition to other things, but I
| don't see the password as actually contributing much to
| the security.
|
| My first comment also linked to another comment of mine
| from two months ago where I said "I would personally push
| away from passwords on the whole at this point."
|
| I definitely wasn't moving the goal posts at any point,
| as I can point to multiple examples of holding this
| position the whole time, but I know that I'm not always
| the clearest communicator.
| hardware2win wrote:
| To generate tokens?
| born2discover wrote:
| I believe they are referencing the fact that upon a login
| attempt the server does receive a plaintext password per
| se.
|
| Usually it is stored in memory only long enough to
| compare it to the hashed version from the persistence
| layer but... that's in theory.
| tuwtuwtuwtuw wrote:
| When it comes to memory then it will typically be stored
| longer than necessary due to how garbage collection works
| in 99% of all of web applications.
| [deleted]
| eptcyka wrote:
| We know that people love to reuse passwords. We also know that
| enterprise software is often deployed in a rather complex,
| complicated, multi-layer fashion, which is to say that
| misconfiguring it to not use HTTPS isn't all too far fetched.
| Leaking a session ID is always strictly better than leaking a
| plaintext password and username combo.
| aendruk wrote:
| I don't see a "Remember me" option [1] on the login form anymore.
| Maybe they've removed it until this can be properly resolved?
|
| [1]: Screenshot at https://forums.lenovo.com/t5/Other-Linux-
| Discussions/Thinkpa...
| julianlam wrote:
| I wonder what forum stack they use...
|
| Asking as someone who works with forum software on a daily basis.
| switzer wrote:
| BuiltWith says that the CMS used at forums.lenovo.com is from
| Lithium Technologies, and it was first detected in July, 2012.
| I'm not sure if this is the forum software, or something else.
| tyingq wrote:
| Lithium is now Khoros (https://khoros.com/), which is in
| pretty broad use.
| daxaxelrod wrote:
| Judging by the network tab, it looks like they wrote their own.
| All the api requests fall under the same domain.
|
| https://forums.lenovo.com/api/v1/user/getCountryByIp
| https://forums.lenovo.com/api/v1/forums/getForumAccess
| https://forums.lenovo.com/api/v1/forums/getCurrentForumTrees
| https://forums.lenovo.com/api/v1/topic/getTopic?fid=6&tid=51...
|
| Also interesting that they have no auth requirement on the
| getCountryByIp route
| tyingq wrote:
| They seem to consistently mis-spell "community" in the code,
| which is kind of interesting: var
| __currentForum = window.CommuntiyForums&&CommuntiyForu
| ms.findCommuntiyHomepageByUrlPath()||'';
| if(__currentForum&&__currentForum.hit){
| lmdBrandVal = "Forum Details:"+ __currentForum.forum.board;
| }else{ var __websiteInfo =
| sessionStorage&&sessionStorage.websiteInfo ?
| sessionStorage.websiteInfo :
| sessionStorage.currentCommuntiySite;
| if(__websiteInfo&&JSON.parse(__websiteInfo).board) {
| lmdBrandVal = "Forum Details:" +
| JSON.parse(__websiteInfo).board; }
| }
| zbuf wrote:
| I inherited a codebase like this, from a developer coding
| in their native language. Function names or variables
| started with a typo, and they just carried on with tab/auto
| completion from then on.
|
| By the time I arrived the damage was wide and it was easier
| to leave it consistently wrong than try and fix across
| several codebases.
| 37 wrote:
| From Jan 31.... Wonder if this has been fixed yet
| iamdual wrote:
| Yeah, tested. They fixed.
| aendruk wrote:
| Did you select "Remember me" in your test?
| matthewaveryusa wrote:
| This is equivalent to basic HTTP authentication. If used over TLS
| it's safe-ish: The real issues arise from servers logging HTTP
| requests/headers and whatnot in plaintext. The two benefits of
| using a session over the raw password are that:
|
| 1) sessions are typically scoped in time, and
|
| 2) if the session is revealed, it can't be used for credential
| stuffing (using the same credentials on a different website to
| see if the password was used there too.)
|
| Having said that I'm not being an apologist: The design should be
| better
| eatonphil wrote:
| > HTTP authentication
|
| Just clarifying, do you mean basic auth with the
| `Authorization: Basic base64(username : password)` scheme?
| blenderdt wrote:
| Which can also be sent in the URL like:
| https://username:password@example.com
|
| But this is of course even worse because most servers log
| this. Headers are not often logged.
| tinus_hn wrote:
| Most servers obviously by default do not log the password,
| all of the ones I checked do not even have a way to do so.
| carlhjerpe wrote:
| "Use of the format "user:password" in the userinfo field is
| deprecated."
|
| https://www.ietf.org/rfc/rfc3986.txt
|
| FYI
| VWWHFSfQ wrote:
| I'm fairly certain that's just a convenience. The HTTP
| client will transform that into basic auth header in the
| actual request
| blenderdt wrote:
| Interesting. I wonder what really happens because I
| sometimes use this when I need to send an Authorization
| header to a location behind basic auth.
|
| As far as I know only Nginx accepts multiple
| Authorization headers.
| VWWHFSfQ wrote:
| Just testing it out with netcat, I can see the client is
| sending it as regular basic auth header:
| $ nc -l 127.0.0.1 8000 GET / HTTP/1.1
| Host: 127.0.0.1:8000 User-Agent: python-
| requests/2.22.0 Accept-Encoding: gzip, deflate
| Accept: */* Connection: keep-alive
| Authorization: Basic dGVzdDp0ZXN0 >>>
| requests.get("http://test:test@127.0.0.1:8000")
| eatonphil wrote:
| And if you also pass an Authorization header it just
| drops the basic auth header (tested against a mirror
| server): $ curl
| http://user:pass@localhost:8080
| GET / HTTP/1.1 Host: localhost:8080 User-
| Agent: curl/7.79.1 Accept: */* Authorization:
| Basic dXNlcjpwYXNz $ curl -H 'Authorization:
| Token blobbity' http://user:pass@localhost:8080 GET
| / HTTP/1.1 Host: localhost:8080 User-Agent:
| curl/7.79.1 Accept: */* Authorization: Token
| blobbity
| matthewaveryusa wrote:
| yeah -- updated.
| ptx wrote:
| Performance would be another benefit, wouldn't it? Password
| hashing algorithms are deliberately slow, so doing it for every
| request adds some overhead compared to doing it once and
| establishing a session ID. (Assuming that the passwords are
| hashed on the server.)
| jaywalk wrote:
| Nobody's hashing a password on every request. In this case,
| the cookie is used for a (very shoddily implemented)
| "Remember Me" feature, so the user doesn't have to login to
| the website every time they use it.
___________________________________________________________________
(page generated 2022-04-22 23:02 UTC)