• anonymous (unregistered) in reply to chubertdev
    chubertdev:
    JArkinstall:
    Post params would also be insecure. Anything served to a user is modifiable by that user.

    Simple mechanism: generate a token (can be as simple as a concatenation of the username and a random, unused n-digit key), send it to the 3rd party server to state that it belongs to the given user. Any invalid or pre-used tokens fail.

    The key is given to the user via the iFrame URI, and that associates the user with their session via the key given.

    More elaborate version (for the case when the 3rd party server is written by idiots): create a proxy application which sends manual requests to the other server, server side. A bit of a bodge but better than the alternative. The user has no access to the auth of the 3rd party server, and authentication is implicitly linked to their own login.

    TDWTF version: hash their ID. They'll probably never guess anyone else's ID, right? Obscurity and security are two different concepts sigh

    Captcha: facilisi - The people who control the illuminati.

    Don't forget to expire the token, as well.

    He covered that:

    pre-used tokens fail
  • (cs) in reply to anonymous

    [quote user="anonymous"]Don't forget to expire the token, as well.[/quote] He covered that: [quote]pre-used tokens fail[/quote][/quote]

    Oh, I was thinking of re-usable ones. Single use are definitely more secure, though.

    Addendum (2013-10-16 16:04):

    Whoops, tag soup.

    Anyways, before anyone points out that having re-usable tokens is a bad, bad idea, I hope that you all code in new applications and never inherit anything.

  • Mike (unregistered) in reply to MightyM

    Sun did change the String.hashcode method in the early days of Java. The original implementation used only the first 10 characters of the string to determine the code. It came to light that this was a bad idea when someone as stowing URLs (just the string, not the java.net.URL) and most cached to the same value. Apparently many URLs begin "http://www"

  • (cs)
    Important

    If two string objects are equal, the GetHashCode method returns identical values. However, there is not a unique hash code value for each unique string value. Different strings can return the same hash code.

    The hash code itself is not guaranteed to be stable. Hash codes for identical strings can differ across versions of the .NET Framework and across platforms (such as 32-bit and 64-bit) for a single version of the .NET Framework. In some cases, they can even differ by application domain.

    As a result, hash codes should never be used outside of the application domain in which they were created, they should never be used as key fields in a collection, and they should never be persisted.

    Finally, do not use the hash code instead of a value returned by a cryptographic hashing function if you need a cryptographically strong hash. For cryptographic hashes, use a class derived from the System.Security.Cryptography.HashAlgorithm or System.Security.Cryptography.KeyedHashAlgorithm class.

    For more information about hash codes, see Object.GetHashCode.

    http://msdn.microsoft.com/en-us/library/system.string.gethashcode.aspx

    Does "inside an iframe" count as a different application domain? haha

  • NullPlanException (unregistered) in reply to Mr.Bob

    I think we can conclude that it WASN'T collisions that caused the user ID's to be duped.

    I think Jan was let go for spending too much time on tDWTF inventing WTFs.

  • Mick (unregistered)
    article:
    Besides, did it ever occur to you that Strings don’t hash perfectly? Two user IDs can, and have, hashed to the same value!
    Hash Codes can only be unique where num of possible items < num of possible Hash Codes. It's got nothng to do with perfection.

    Also, I would have thought: replaceAll("user=","user=" + user.hashCode());

    whould end with user=<hashCode><user id>

    that is, it would be 48627102 (assuming, of course that it started as user=102....

  • JD (unregistered) in reply to Steve The Cynic
    Steve The Cynic:
    Zylon:
    "Jan" is a dude?
    Yup. In Norway, at least, it is a man's name, their equivalent of "John", pronounced "Yan" because the letter J is pronounced as if it were a Y.

    EDIT: From the non-encyclopedia:

    Jan is a variant of John in Catalan, Czech, Dutch, Scandinavian, Cornish, German, Afrikaans, Northern Germanic and Western Slavic Languages (in Slovak, spelled Ján)
    Dr Jan I Tor.
  • Say What (unregistered) in reply to Al H.
    Al H.:
    Any multiple of 2 (or adjacent value like 32767) should automatically be suspect as having triggered a rollover condition--a variable having met its threshold/ceiling and started back at 0 (or, in cases like this of signed values, a negative equivalent like -32767).

    The language doesn't matter--both VB6 and the latest whamma-jamma Java, Ruby or C# have datatypes with low thresholds for those purposes that make sense.

    Blaming a language for misuse by shortsighted programmers is silly. VB has had long integers since its inception.

    Uh, What? Any Multiple of two = Any Even number

    => Any multiple of 2 (or adjacent value) = set of all real integers....

  • Vlad Patryshev (unregistered)

    We had a similar accident in orkut team. Instead of actual user ids, some kind of hash was being produced, to make sure that Orkut Buyokokten, e.g., would not be exposed as User#1 (and Marissa, I believe, a User#3). The problem was, the produced hash code HAD TO BE non-negative, so the higher bit was being removed... except that the algorithm did not care.

    So one nice weekend new people started getting old people's accounts. It was pretty cool; it took about a week to split all these new accounts (hundreds of thousands of them, I believe).

    It was cultural. Google-cultural. Attempts to fix it BEFORE it happened bumped into Cool Senior Developers resistance - "we don't have time for these insignificant small improvements of yours".

  • (cs) in reply to Mick
    Mick:
    article:
    Besides, did it ever occur to you that Strings don’t hash perfectly? Two user IDs can, and have, hashed to the same value!
    Hash Codes can only be unique where num of possible items < num of possible Hash Codes. It's got nothng to do with perfection.
    strArticle = strArticle.Replace("perfectly", "distinctly");
    
  • (cs)

    I blame the cylons.

  • Mathlete (unregistered) in reply to chubertdev
    chubertdev:
    Mick:
    article:
    Besides, did it ever occur to you that Strings don’t hash perfectly? Two user IDs can, and have, hashed to the same value!
    Hash Codes can only be unique where num of possible items < num of possible Hash Codes. It's got nothng to do with perfection.
    strArticle = strArticle.Replace("perfectly", "distinctly");
    

    'Perfectly' is the correct adjective.

    http://en.wikipedia.org/wiki/Perfect_hash_function

  • Norman Diamond (unregistered) in reply to Vlad Patryshev
    Vlad Patryshev:
    (and Marissa, I believe, a User#3).

    So one nice weekend new people started getting old people's accounts.

    It was cultural. Google-cultural.

    New people getting old people's accounts is Yahoo-cultural now.

  • (cs) in reply to Mathlete
    Mathlete:
    'Perfectly' is the correct adjective.

    http://en.wikipedia.org/wiki/Perfect_hash_function

    neat

  • (cs) in reply to Geoff
    Geoff:
    Which will crop up all kinds of places, ints in 16-bit code, short db attributes, maybe some idiot decided to make value in struct int_16 so it would byte align neatly or something.
    Better yet is when you get someone do that and yet put it next to a pair of values with stricter alignment so that you get all of the lack-of-range without any space saving.

    It could be worse though. Worse would be using a tagged variable-width in-memory representation for all the fields so that every access to a value has to trawl over all the previous ones in the sequence, just so that the value can be accessed at all. (Bonus: pack things at the sub-byte level!) It does make some sense with strings — UTF-8 does this, but has other advantages that make it worth using— but for nearly anything else it is just such a poor decision. You really want something compressed? Use a separate compression step.

  • Uhh (unregistered)

    public int hashCode() { return String.valueOf(getId()).hashCode() % 32768; }

    Problem solved! (for some meanings of solved).

    Anyways, a system that stops working at 32768 users is 32 times better than a system that stops working at 100 users.

  • np (unregistered) in reply to kilroo
    kilroo:
    anonymous coward:
    Unfortunately for this story: there isn't a single collision for ids generated by this mechanism for the first 500 million numerical ids.

    Fortunately for this story, I have no trouble whatsoever imagining that a vendor who required that the IDs be small was either allowing the ID to wrap, or using their internal maximum for everyone who exceeded the limit.

    I'd like to think that the vendor was actually smarter and their "small ID" (only Anders mentions that his implementation has a limit of 32768, not that the vendor needed it at that limit) was fixed to allow larger values. So it was just Anders bug that was choking the system.

    Also Jan was using a test account (hence ID 102). The main system might have started numbering at 10000000000 to not conflict with another legacy system that started at 1000000000. Companies like big numbers (e.g. browser versions being bumped every month instead of every year).

  • _ (unregistered) in reply to Vlad Patryshev
    Vlad Patryshev:
    We had a similar accident in orkut team. Instead of actual user ids, some kind of hash was being produced, to make sure that Orkut Buyokokten, e.g., would not be exposed as User#1 (and Marissa, I believe, a User#3). The problem was, the produced hash code HAD TO BE non-negative, so the higher bit was being removed... except that the algorithm did not care.

    So one nice weekend new people started getting old people's accounts. It was pretty cool; it took about a week to split all these new accounts (hundreds of thousands of them, I believe).

    It was cultural. Google-cultural. Attempts to fix it BEFORE it happened bumped into Cool Senior Developers resistance - "we don't have time for these insignificant small improvements of yours".

    I believe!

  • Not Necessarily the same Mick (unregistered) in reply to chubertdev
    chubertdev:
    Mathlete:
    'Perfectly' is the correct adjective.

    http://en.wikipedia.org/wiki/Perfect_hash_function

    neat

    Point taken (a little) but in that case the comment in the article that Strings fon't hash perfectly is sort of irrelevant....the bottom line is that having more than 32768 (allowing for a 0) users is not going to Hash perfectly - no matter whether you hash an int, a string, a complex obect whatever....

  • Johnny (unregistered) in reply to Uhh
    Uhh:
    public int hashCode() { return String.valueOf(getId()).hashCode() % 32768; }

    Problem solved! (for some meanings of solved).

    Anyways, a system that stops working at 32768 users is 32 times better than a system that stops working at 100 users.

    yeah....but your proposal could start to misbehave well before 32768 users anyways.....

  • (cs) in reply to Zylon
    Zylon:
    "Jan" is a dude?

    No Jan is the President's daughter.

    No, Jan is Irish Girl.

  • Oslo (unregistered) in reply to faoileag
    faoileag:
    the article said:
    The value 48627 didn’t exist anywhere in the local database. Jan dug into the application source code, and found this line:
    url = iFrameUrl.replaceAll("user=","user=" + user.hashCode());
    Either the code got mangled in the obfuscation to protect "Anders", or I'm missing something:
    "user=102".replaceAll("user=", "user=48627");
    would result in "user=48627102" with the user id being 48627102 and not 48627.

    I am pretty sure you're not missing something. There are a TON of other people moaning on about how collisions wouldn't happen who are though. They weren't sending a hash of the user id, they were sending a hash of the user id padded with the user id. There's a difference, kids.

  • wernsey (unregistered) in reply to doh
    doh:
    Cyclops:
    32768 is the ceiling for int in VB6. Coincidence? I think not...

    There is this little thing in computers called binary, suggest you look it up some time before concluding that 10+10=vb6

    FTFY

  • Hasse (unregistered) in reply to Steve The Cynic
    Steve The Cynic:
    Zylon:
    "Jan" is a dude?
    Yup. In Norway, at least, it is a man's name, their equivalent of "John", pronounced "Yan" because the letter J is pronounced as if it were a Y.

    EDIT: From the non-encyclopedia:

    Jan is a variant of John in Catalan, Czech, Dutch, Scandinavian, Cornish, German, Afrikaans, Northern Germanic and Western Slavic Languages (in Slovak, spelled Ján)
    Further, Jan is a shortened form of Johannes, as is Hans.
  • (cs) in reply to levbor
    levbor:
    Jan is the problem here:
    Instead of doing anything to fix the issue, Jan wasted valuable time arranging a meeting to gossip with his buddy Anders instead. No wonder Jan was let go.

    If you need to make a change in a system and don't really know how it works, you have to know the motivation behind the code that you're changing. Otherwise you risk making new bugs. For example, it was Anders who told Jan that the external vendor's IDs have to be 16-bit.

    And that information should be in the documentation. So the WTF ought to be the lack of documentation on all sides.

  • (cs) in reply to nonpartisan
    nonpartisan:
    I used to work as a transport coordinator at a local hospital (2000-ish). In cooperation with our local air ambulance company, we obtained the new flight tracking software they were using. The software used a database backend called 4G; I'd not heard of it at the time. It also stored data -- medical, patient data -- on the non-local vendor server. Every customer.

    The vendor admitted it was possible, however rare, that the software or the server could screw up and we'd start seeing call information/patient data for other customers. If that happened, we were to call tech support immediately. The product started out as an in-house project for an air ambulance in Florida. They had this delusion of how great their software was and decided to market it.

    TRWTF? Even with their admission of the bug, our air ambulance company STILL bought it.

    No, TRWTF there is storing your data on someone else's machine.

  • Venio (unregistered) in reply to Warren
    Warren:
    Was the original programmer smoking something?

    Wrong Question. You certainly wanted to ask: What was the original programmer smoking?

  • Jibble (unregistered) in reply to anonymous coward
    anonymous coward:
    Unfortunately for this story: there isn't a single collision for ids generated by this mechanism for the first 500 million numerical ids.

    Did you squish those 500 million numbers into 16 bits each? Didn't think so...

    (What does VB do in case of overflow? Does it AND them with 65535 or does it clamp them to 32767?)

  • Jibble (unregistered) in reply to Cyclops
    Cyclops:
    32768 is the ceiling for int in VB6. Coincidence? I think not...

    Maybe you meant 32767...

  • Norman Diamond (unregistered) in reply to Venio
    Venio:
    Warren:
    Was the original programmer smoking something?
    Wrong Question. You certainly wanted to ask: _What_ was the original programmer smoking?
    Who needs to ask? How did you think the hashed code got hashed?
  • Bill C. (unregistered)

    Hurray, now I can inhale--

    oops, wrong Washington. Oh well.

  • Will C (unregistered) in reply to Oslo

    Unless the URL was a template with ...&user=&... embedded in it precisely so the user ID could be filled in (rather than replacing one already there)?

    Captcha: similis - a Virtual Disease?

  • (cs) in reply to Al H.
    Al H.:
    VB has had long integers since its inception.

    DEFLNG A-Z

  • Ben Linnus (unregistered) in reply to faoileag
    faoileag:
    Steve The Cynic:
    iannakin:
    32768 is just a 16 bits int max value (2^15)
    Or have I been trolled?
    Probably not. A lot of people take the positive upper limit of a signed type as max value of that type. Since types like "short", "int" and "long" usually do mean signed types, it can be seen as nitpicking to point out that there are unsigned types, too.
    TRWTF is dismissing this like it's an insignificant difference ...and people wonder where all the off-by-one errors come from!

    I've lost track of how many times I've heard this mistake made, and equally how many times I've complained loudly about it.

  • (cs) in reply to Gunslnger
    Gunslnger:
    No, TRWTF there is storing your data on someone else's machine.
    I agree in principle, however there are (or at least at the time were) very few vendors in the medical flight transport software field. I know of two others that existed at the time and I don't know if either one of those allowed you to have your own server or not.
  • (cs) in reply to Jibble
    Jibble:
    anonymous coward:
    Unfortunately for this story: there isn't a single collision for ids generated by this mechanism for the first 500 million numerical ids.

    Did you squish those 500 million numbers into 16 bits each? Didn't think so...

    (What does VB do in case of overflow? Does it AND them with 65535 or does it clamp them to 32767?)

    It raises the Overflow error.
  • anonymous (unregistered) in reply to Pawprint
    Pawprint:
    Jibble:
    anonymous coward:
    Unfortunately for this story: there isn't a single collision for ids generated by this mechanism for the first 500 million numerical ids.

    Did you squish those 500 million numbers into 16 bits each? Didn't think so...

    (What does VB do in case of overflow? Does it AND them with 65535 or does it clamp them to 32767?)

    It raises the Overflow error.
    You forgot the first line of every VB6 code ever written...
    On Error Resume Next
    Now what does it do?
  • (cs) in reply to Steve The Cynic
    Steve The Cynic:
    Zylon:
    "Jan" is a dude?
    Yup. In Norway, at least, it is a man's name, their equivalent of "John", pronounced "Yan" because the letter J is pronounced as if it were a Y.

    EDIT: From the non-encyclopedia:

    Jan is a variant of John in Catalan, Czech, Dutch, Scandinavian, Cornish, German, Afrikaans, Northern Germanic and Western Slavic Languages (in Slovak, spelled Ján)
    Good job he wasn't French or he'd have been Jean, and that would *really* have confused the arses off you rednecks.
  • (cs) in reply to Matt Westwood
    Matt Westwood:
    Good job he wasn't French or he'd have been Jean, and that would *really* have confused the arses off you rednecks.

    What do pants have to do with this?

  • (cs) in reply to Anonymous
    Anonymous:
    The Real WTF: System.out.println("102".hashCode()); The result was 48627.

    While they were trying to ensure that the app never sent a value bigger than 32768.

    Hey, it worked perfectly on all the one- and two-digit test account IDs they tried! Not the developers' fault if the customer eventually wanted to get their client numbers into the triple digits.

  • Jan (unregistered)

    This sounds familiar...

    It has been too long since I submitted this WTF for me to repudiate any of the technical or personal attacks but the gist of the story is true.

    I remember wondering how to decide which user actually got to keep the accidentally shared account on the external site if I was asked to fix the problem by implementing some sensible user id mapping mechanism.

    And, yes, I am a dude :-)

  • JRI (unregistered) in reply to me

    Mike Hammer?

Leave a comment on “Hashed Code”

Log In or post as a guest

Replying to comment #:

« Return to Article