• Jake Arkinstall (unregistered)

    TRWTF is authenticating users via an argument in the URL.

    That'd be the FRIST lawsuit of many.

  • MightyM (unregistered)

    Another thing: Are string hashcodes in Java identical for all versions? I know that .net outputs different strng hashes for different versions of the runtime.

  • Warren (unregistered)

    Hashing the user id makes a change from hashing passwords (not that most WTFs we see do that).

    Was the original programmer smoking something?

  • Taemyr (unregistered) in reply to MightyM
    MightyM:
    Another thing: Are string hashcodes in Java identical for all versions? I know that .net outputs different strng hashes for different versions of the runtime.
    Java API:
    Returns a hash code for this string. The hash code for a String object is computed as
     s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
    
    Taken from. http://docs.oracle.com/javase/6/docs/api/java/lang/String.html#hashCode%28%29
  • Cyclops (unregistered)

    32768 is the ceiling for int in VB6. Coincidence? I think not...

  • Vilx- (unregistered)

    32768 users should be enough for everyone!

  • Anonymous (unregistered)

    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.

  • anonymous coward (unregistered)

    Unfortunately for this story: there isn't a single collision for ids generated by this mechanism for the first 500 million numerical ids.

  • Don (unregistered) in reply to Jake Arkinstall
    Jake Arkinstall:
    TRWTF is authenticating users via an argument in the URL.
    Nope. Legal people typically have no concept of insecure vs secure, as long as they're satisfied that a user must use a password 95% of them are happy as a pig in sh-t...
  • faoileag (unregistered)
    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.
  • Geoff (unregistered) in reply to Cyclops

    Or you know it might just have something to do with it being the limit of 16-bit signed value..

    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.

    Its fun ragging on <= VB6, and all but anyone who has been doing any programing more that week should have run across 32768 and have some idea what the core reason for its significance is; without know anything about what this application does, and what technology is in use, I'd lay odds that yes

    32768 is the ceiling for int in VB6. Coincidence?
    is very much a coincidence.

  • faoileag (unregistered) in reply to Jake Arkinstall
    Jake Arkinstall:
    TRWTF is authenticating users via an argument in the URL.
    And just how exactly would you authenticate users instead if all you've got is a remote webserver that serves some CGI page and does not accept POST params?
  • MightyM (unregistered) 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.

    Using the hash code formula posted above the highest number with a hash code smaller than 32768 is 99.

  • MightyM (unregistered) in reply to MightyM
    MightyM:
    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.

    Using the hash code formula posted above the highest number with a hash code smaller than 32768 is 99.

    Correction: to be exact every number between bigger than 99 and smaller than 1000000 is guarantied to not work.

  • faoileag (unregistered)
    Anders told Jan:
    "The external vendor needs small IDs. This way we ensure we never send a value bigger than 32768"
    Very good example of RTFM. Or rather of not having RTFM.

    The Java documentation states that Object.hashCode() returns a value of the type "int", which, surprisingly, translates into a "32-bit signed integer".

    Ah well, perhaps the reasoning was "32768 starts with 32 so it msut be a 32-bit value".

  • anonymous (unregistered)

    Although the code is a WTF in the first place, I actually agree with Anders that a ticket should be created first before the error will be solved (if not already done). Doesn't look like an easy fix and a ticket helps tracking and documenting the solution. Nobody is helped by panic about it.

  • Jan is the problem here (unregistered)

    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.

  • Ash (unregistered) in reply to faoileag

    With a hammer would be my prefered method.

  • iannakin (unregistered) in reply to Cyclops

    32768 is just a 16 bits int max value (2^15). Could be any other languages, with 2 bytes int.

  • Big Hammer (unregistered) in reply to Ash
    Ash:
    With a hammer would be my prefered method.

    On someone's fingers (or head), I might add.

    Captcha: genitus -- This developers genitus was showing. (This was just wrong on so many levels!)

  • me (unregistered) in reply to Ash

    A Jan Hammer?

  • doh (unregistered) in reply to Cyclops
    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 2+2=vb6

  • (cs) 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.

    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.

  • faoileag (unregistered)

    A few things are odd about the story, though:

    the article:
    New users couldn’t create accounts
    For all we can see, the user-id gets transformed just to create an url for an iframe from "an external vendor".

    Sure account creation would be handled by Jan's shop? How could that fail if the user-id is auto-generated by the database? How can the external vendor play a role in that? If all he provides is an iframe?

    the article:
    and existing users sometimes found themselves logged in as other people
    Again, how is that possible if the accounts are handled by Jan's shop? I mean, being looged in as another user. A user might see some other user's data if that data is shown in the iframe supplied by the external vendor, but only then.

    But since the external vendor obviously does not authentificate a user by a password (hash duplicates might occur but these two users having the same password? Unlikely), that data would also be visible to the world if someone took the iframe url and began experimenting with the number following "user=".

    I think this story has been embellished a lot around a small "32-bit integer hashCode() vs 16-bit integer expected param" WTF.

  • (cs) in reply to Jan is the problem here
    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.

  • (cs) in reply to iannakin
    iannakin:
    32768 is just a 16 bits int max value (2^15). Could be any other languages, with 2 bytes int.
    Let's go back to basics. A *signed* 16-bit int goes up to only 32767, but (on two's complement hardware) down to -32768. And 32767 is 2**15-1, so you are almost right.

    An unsigned 16-bit int goes up to 2**16-1, 65535, and down to 0.

    Or have I been trolled?

  • faoileag (unregistered) in reply to Steve The Cynic
    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.
  • (cs) 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.
    I was thinking more of the mismatch between 32768 (iannakin) and 32767 (reality).
  • Valued Service (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.

    Fortunately for this story, sequential IDs aren't a requirement.

  • (cs)

    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.

  • faoileag (unregistered) in reply to Steve The Cynic
    Steve The Cynic:
    I was thinking more of the mismatch between 32768 (iannakin) and 32767 (reality).
    Hah, I completely missed that one! :-) Nevertheless, I still assume that you have not been trolled since 2^15 shows up as 32768 on calculators and people tend to forget that for the max value they have to subtract one.
  • Herr Otto Flick (unregistered) in reply to faoileag
    faoileag:
    Jake Arkinstall:
    TRWTF is authenticating users via an argument in the URL.
    And just how exactly would you authenticate users instead if all you've got is a remote webserver that serves some CGI page and does not accept POST params?

    Kerberos.

    Next question please.

  • Anon (unregistered) in reply to Herr Otto Flick
    Herr Otto Flick:
    faoileag:
    Jake Arkinstall:
    TRWTF is authenticating users via an argument in the URL.
    And just how exactly would you authenticate users instead if all you've got is a remote webserver that serves some CGI page and does not accept POST params?

    Kerberos.

    Next question please.

    I think "Stop hitting yourself" would be an equally valid answer.

  • Stabbitha (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 2+2=vb6

    What has the world come to when a person can't even make a VB joke without getting pounced on?

  • faoileag (unregistered) in reply to Herr Otto Flick
    Herr Otto Flick:
    faoileag:
    And just how exactly would you authenticate users instead if all you've got is a remote webserver that serves some CGI page and does not accept POST params?
    Kerberos.
    Sure. To display an iframe. Care to provide some sample code, I'd be especially interested in the attributes needed for the iframe-Tag so that the browser can accomplish this?
  • QJo (unregistered) in reply to faoileag
    faoileag:
    Anders told Jan:
    "The external vendor needs small IDs. This way we ensure we never send a value bigger than 32768"
    Very good example of RTFM. Or rather of not having RTFM.

    The Java documentation states that Object.hashCode() returns a value of the type "int", which, surprisingly, translates into a "32-bit signed integer".

    Ah well, perhaps the reasoning was "32768 starts with 32 so it msut be a 32-bit value".

    +1 Mirth. Featured comment, please.

  • (cs)

    "Jan" is a dude?

  • (cs) in reply to Zylon
    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)
  • (cs) in reply to faoileag
    faoileag:
    Jake Arkinstall:
    TRWTF is authenticating users via an argument in the URL.
    And just how exactly would you authenticate users instead if all you've got is a remote webserver that serves some CGI page and does not accept POST params?
    Start by dragging your webserver's sorry arse out of the Stone Age, ffs.
  • JArkinstall (unregistered) in reply to faoileag

    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.

  • Dumb and Dummer (unregistered) in reply to Herr Otto Flick
    Herr Otto Flick:
    faoileag:
    Jake Arkinstall:
    TRWTF is authenticating users via an argument in the URL.
    And just how exactly would you authenticate users instead if all you've got is a remote webserver that serves some CGI page and does not accept POST params?

    Kerberos.

    Next question please.

    Out of sheer morbid curiosity (and asbestos underpants are firmly affixed), hypothetically: IF we were developing our own web services, and IF as part of that development I needed to communicate/operate/etc. with another 3rd party service over which I had no control, and IF that 3rd party wanted ID/password but didn't support Kerberos, then wouldn't I have to roll my own solution? I mean, there exists times on the web where the only option is to send and ID and password to someone (oh gosh!).

    Just curious, but as many years as I've been doing this, Kerberos is not really ever been the blanket answer -- for us Unix dudes anyway (has it?).

  • Al H. (unregistered) in reply to Cyclops

    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.

  • Mr.Bob (unregistered) in reply to Valued Service
    Valued Service:
    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, sequential IDs aren't a requirement.

    Maybe it isn't a hash collision that's causing user IDs to be duped, but the external website is using a 16-bit signed int as the user ID, and really does require a max of 32767. Any ID bigger than 15 significant bits being truncated?

    Extra levels of WTF on the external site might be taking the abs() of the ID, since their testing (ha!) showed that for some unknown reason, big numbers came back negative...

  • (cs) in reply to faoileag
    faoileag:
    Steve The Cynic:
    I was thinking more of the mismatch between 32768 (iannakin) and 32767 (reality).
    Hah, I completely missed that one! :-) Nevertheless, I still assume that you have not been trolled since 2^15 shows up as 32768 on calculators and people tend to forget that for the max value they have to subtract one.
    To be more specific: there are 32768 values, one of which is 0, which makes the largest value 32767.
  • heh (unregistered) in reply to Al H.
    Al H.:
    Any multiple of 2 (or adjacent value [...]
    So.. any number then?
  • Vilx- (unregistered)

    This is a nice example of code reuse.

  • JAPH (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).

    I hope you meant any power of two instead of any multiple of two. We may need to strip you of your geek badge.

  • Mikerad (unregistered) in reply to Vilx-
    Vilx-:
    This is a nice example of code reuse.
    I think you misspelled "refuse"....
  • (cs) in reply to Stabbitha
    Stabbitha:
    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 2+2=vb6

    What has the world come to when a person can't even make a VB joke without getting pounced on?

    When it's a horrible joke that is completely misguided, everyone will fire away...

  • (cs) in reply to JArkinstall
    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.

Leave a comment on “Hashed Code”

Log In or post as a guest

Replying to comment #:

« Return to Article