The Daily WTF: Curious Perversions in Information Technology
Welcome to TDWTF Forums Sign in | Join | Help
in Search

Miserable captcha implementation

Last post 06-19-2006 11:18 AM by Ixpah. 31 replies.
Page 1 of 1 (32 items)
Sort Posts: Previous Next
  • 06-08-2006 6:56 AM

    • sam
    • Not Ranked
    • Joined on 06-08-2006
    • Posts 2

    Miserable captcha implementation



    I know that captchas aren't exactly supposed to be top security devices, but this site's implementation is so awful it could qualify for a dailyWTF.

    First, you should do none of: unlimited retries, 40-word dictionary, image conservation across retries. Any of them makes attacks easier, but this very combination of the three renders them ridiculously easy.

    Second, you usually try NOT to store the text that the user is required to type in the page source. Remember, it is to be hidden from bots, not from users. And no, obfuscating the UCS2 string using base64 then ROT13 is not exactly the thing you do either. The current captcha allows both easy retrieval of the answer without even loading the image and replay attacks.
  • 06-08-2006 8:30 AM In reply to

    Re: Miserable captcha implementation

    Here is a perfect case of where doing it "right" doesn't make any sense at all. Consider:

    1. The absolute minimum amount of time needed to be spent doing this since this is neither fun to do nor something I can get paid to do
    2. The CAPTCHA module used before (MSDN's HIP Example) didn't work for some reason
    3. It probably had something to do with the way it was using the application cache, but further analysis would have violated guideline #1
    4. All of the CAPTCHA code for .NET I found used the Session object (which I would have used), but Session State is disabled in CS for performance reasons, and i didn't want to turn it on just for this
    5. There probably were other .NET solutions out there that didn't use the session, but the search for this probably would have violated #1
    6. I had to whip something together without using the application cache (didn't trust it per #3) or the session (due to #4).
    7. Due to #6, the CAPTCHA would be propietary and, therfore, secure by its obscurity
    8. An attack against the site would be pretty silly considering that:
      1. It would have to be exclusively targeted against the site (as a result of #7)
      2. CS has some attack-prevention stuff to prevent this. so the attack would have to work around these, too
      3. Myself or moderators can delete posts pretty quickly using CS
      4. I can delete posts very fast using direct database queries
      5. I can have new srambling logic deployed in less than 30 minutes

    Perhaps the real WTF is that you spent so much time decoding all this ;-)

  • 06-08-2006 9:04 AM In reply to

    • sam
    • Not Ranked
    • Joined on 06-08-2006
    • Posts 2

    Re: Miserable captcha implementation

    Don't worry, reverse-engineering ROT13 and doing a word list did not take that much time :-)

    Most of your points are valid. #7 is somewhat weakened by the use of ROT13 which hardly qualifies as obscurity. Even mediocre crypto like XORing with a secret string stored on the server would have been better... As for #8, I won't discuss it, you're in the best position to weigh the risks. I just hope the implementation mistakes I pointed out won't find their way in other products.
  • 06-08-2006 9:33 AM In reply to

    Re: Miserable captcha implementation

    I have a (perhaps stupid) question about the site's CAPTCHA - where is it? Obviously, when I'm logged in, I don't see it. When I log out, though, I don't even see a 'reply' button. What am I missing?
  • 06-08-2006 10:16 AM In reply to

    Re: Miserable captcha implementation

    When you're not logged in, you should only be able to reply in the Main TDWTF forum. Also possibly in the Sidebar?

    The others won't show a Reply button.
    — Flurp.
  • 06-08-2006 11:13 AM In reply to

    Re: Miserable captcha implementation

    sam:
    Even mediocre crypto like XORing with a secret string stored on the server would have been better...

    My cryto experience is severly lacking. Perhaps you (or someone else) would like to fill in the blanks with some new code.

      public static string Encrypt(string s)
      {
       s = Convert.ToBase64String(Encoding.Unicode.GetBytes(s));
       s = s.Replace("==","~");
       s = s.Replace("=", "~~");
       s = ROT13Encode(s);
       return s;
      }

      public static string Decrypt(string s)
      {
       s = ROT13Encode(s);
       s = s.Replace("~~", "=");
       s = s.Replace("~","==");
       s = Encoding.Unicode.GetString(Convert.FromBase64String(s));
       return s;

      }

    sam:
    I just hope the implementation mistakes I pointed out won't find their way in other products.

    In my brief CAPTCHA search, it would appear worse techniques (plaintext in the cookie) most certainly have.

  • 06-08-2006 12:34 PM In reply to

    Re: Miserable captcha implementation

    I wrote a little program to run some of the CAPTCHAs across Microsoft Office's OCR engine - it got most of them on the first try - we need some better images (with lines across and stuff)
    It's funny because it's out of context.
  • 06-08-2006 2:55 PM In reply to

    • Ixpah
    • Top 500 Contributor
    • Joined on 05-11-2006
    • Posts 61

    Re: Miserable captcha implementation

    Will have to try using OCR on my quick and dirty version sometime. Currently I generate 128bit random number (and store this will all the other details in the database) then send this as a hidden form field as well as a query param to the image generator. I think this provides a reasonable level of security at the expensive of a DB call.

    Without storing something in a session object or the DB I don't know of a way of avoding re-tries although AES encryption with a random key would sort out the problem of decoding on the client.
  • 06-08-2006 3:21 PM In reply to

    • ammoQ
    • Top 10 Contributor
    • Joined on 04-13-2005
    • Vienna.Austria.Europe.Earth
    • Posts 3,445

    Re: Miserable captcha implementation

    Ixpah:
    Will have to try using OCR on my quick and dirty version sometime. Currently I generate 128bit random number (and store this will all the other details in the database) then send this as a hidden form field as well as a query param to the image generator. I think this provides a reasonable level of security at the expensive of a DB call.

    Without storing something in a session object or the DB I don't know of a way of avoding re-tries although AES encryption with a random key would sort out the problem of decoding on the client.


    What's the deal with the hidden form field? I don't get it. If the attacker replays an already used random number, will you accept it again?
    beanbag girl 4ever
  • 06-08-2006 7:53 PM In reply to

    Re: Miserable captcha implementation

    Alex Papadimoulis:

    My cryto experience is severly lacking. Perhaps you (or someone else) would like to fill in the blanks with some new code.


    You might want to check out the DESCryptoServiceProvider.  Initialize it with your key and IV, then use it to create a CryptoStream around a MemoryStream, so it will write to a byte array in memory.  Then you can flush the stream, and pull out the data with readBytes(...)
  • 06-09-2006 4:49 AM In reply to

    • Ixpah
    • Top 500 Contributor
    • Joined on 05-11-2006
    • Posts 61

    Re: Miserable captcha implementation

    ammoQ:
    What's the deal with the hidden form field? I don't get it. If the attacker replays an already used random number, will you accept it again?


    You need hidden form field so that when the form is submitted you know what image was being displayed on the form. Yes you could probably use sessions, but it doesn't. No you can't replay it as the row in the DB is deleted when the form is submitted.
  • 06-09-2006 10:38 AM In reply to

    • ammoQ
    • Top 10 Contributor
    • Joined on 04-13-2005
    • Vienna.Austria.Europe.Earth
    • Posts 3,445

    Re: Miserable captcha implementation

    Ixpah:
    ammoQ:
    What's the deal with the hidden form field? I don't get it. If the attacker replays an already used random number, will you accept it again?


    You need hidden form field so that when the form is submitted you know what image was being displayed on the form. Yes you could probably use sessions, but it doesn't. No you can't replay it as the row in the DB is deleted when the form is submitted.

    OK. Nothing wrong with that.
    beanbag girl 4ever
  • 06-10-2006 8:04 AM In reply to

    Re: Miserable captcha implementation

    Hmm but does the implementation of captcha like in http://fistfulofeuros.net/, or http://www.codinghorror.com/. It appears to work for them, with teh added bonus in that it's simple for users and it's extremely simple to code.
  • 06-11-2006 4:48 AM In reply to

    • Ixpah
    • Top 500 Contributor
    • Joined on 05-11-2006
    • Posts 61

    Re: Miserable captcha implementation

    Factory:
    Hmm but does the implementation of captcha like in http://fistfulofeuros.net/, or http://www.codinghorror.com/. It appears to work for them, with teh added bonus in that it's simple for users and it's extremely simple to code.


    codinghorror appears to have a fixed image, and the other appears to just ask you to enter "A", or is it just that I'm loosing the plot?
  • 06-11-2006 6:23 AM In reply to

    Re: Miserable captcha implementation

    Indeed, why are spammers are not going to bother manually checking the key for small sites, and if they do, well then you can start thinking of more intricate ways of defeating them.
  • 06-12-2006 5:25 PM In reply to

    Re: Miserable captcha implementation

    Ixpah:
    Factory:
    Hmm but does the implementation of captcha like in http://fistfulofeuros.net/, or http://www.codinghorror.com/. It appears to work for them, with teh added bonus in that it's simple for users and it's extremely simple to code.


    codinghorror appears to have a fixed image, and the other appears to just ask you to enter "A", or is it just that I'm loosing the plot?


    coding horror has also changed the image, but not the static word required to post. (Held me up a bit this morning, I had to remember what it was. :) )

    If that other site works like I think it does, it might not be totally useless. You could tell people to "type 5 a's in this box" or something like that. It's not terribly sophisticated, and looks terribly hackish, but I would be really surprised if any spam bots incoporate a natural language processor.
    Disclaimer: I am not now, nor have I to the best of my knowledge been in the past, an actual collision detection algorithm.
  • 06-14-2006 6:17 AM In reply to

    Re: Miserable captcha implementation

    HitScan:


    If that other site works like I think it does, it might not be totally useless. You could tell people to "type 5 a's in this box" or something like that. It's not terribly sophisticated, and looks terribly hackish, but I would be really surprised if any spam bots incoporate a natural language processor.


    Well, apparently spambots can be pretty sophisticated, otherwise most captha's wouldn't be so purposefully mangled and distorted so that only a human brain can figure it out. (blogger's captcha's are sometimes so twisted even I have trouble reading them)

    And the language processor doesn't have to be able to read the collected works of Kant, just interpret a small sentence that always asks for "type this to prevent spam" or something along those lines.

    But in any case, intelligent data parsing becomes more... intelligent, as time passes and technology progresses, so at a certain point, one may expect bots that can do stuff with a form any human could do -- and then any attempt to make a distinction for safety will fail.

    — Flurp.
  • 06-14-2006 4:47 PM In reply to

    Re: Miserable captcha implementation

    This is completely off the top of my head, since i've never implemented CAPTCHA nor do I know what's available in ASP, but...

    it seems to me that I've seen some sites that calculate an md5 checksum of the string in the image and embed that in the source in a hidden field. When the user types the string, all you have to do is calculate the md5 checksum of what they typed and compare it against the hidden field value.

    Since md5 is generally not reversable, this would be pretty effective, i'd think...
  • 06-14-2006 6:41 PM In reply to

    Re: Miserable captcha implementation

    dhromed:
    HitScan:


    If that other site works like I think it does, it might not be totally useless. You could tell people to "type 5 a's in this box" or something like that. It's not terribly sophisticated, and looks terribly hackish, but I would be really surprised if any spam bots incoporate a natural language processor.


    Well, apparently spambots can be pretty sophisticated, otherwise most captha's wouldn't be so purposefully mangled and distorted so that only a human brain can figure it out. (blogger's captcha's are sometimes so twisted even I have trouble reading them)

    And the language processor doesn't have to be able to read the collected works of Kant, just interpret a small sentence that always asks for "type this to prevent spam" or something along those lines.

    But in any case, intelligent data parsing becomes more... intelligent, as time passes and technology progresses, so at a certain point, one may expect bots that can do stuff with a form any human could do -- and then any attempt to make a distinction for safety will fail.

    Defeating natural language parsers: This box in you will type five As, if wanted is submission

    It's funny because it's out of context.
  • 06-15-2006 2:20 PM In reply to

    • db2
    • Top 200 Contributor
    • Joined on 06-15-2006
    • Posts 169

    Re: Miserable captcha implementation

    endergt:
    This is completely off the top of my head, since i've never implemented CAPTCHA nor do I know what's available in ASP, but...

    it seems to me that I've seen some sites that calculate an md5 checksum of the string in the image and embed that in the source in a hidden field. When the user types the string, all you have to do is calculate the md5 checksum of what they typed and compare it against the hidden field value.

    Since md5 is generally not reversable, this would be pretty effective, i'd think...


    Careful, you're falling into the dangerous pitfall of "trust the client". How do we know that the md5 sum in the post-back is actually from the server? In this scenario, it would be simple for the client to generate an arbitrary response, md5 that, and send both off to the server, which would happily accept it.

    But this can be made viable with a trivial change. Before calculating the md5 sum at the server, concatenate the plaintext with some secret key. In other words, ciphertext = md5(key & plaintext). Then you do the same with the plaintext response supplied by the client to make sure it matches up. If an attacker tries to supply a custom plaintext and a new md5 sum, the correlation between the two will be wrecked by prepending the secret key and it will be rejected.

    Then you can easily make this more secure by rotating the key, say every night at midnight, or sooner if desired. As long as the rotation interval is shorter than the feasible amount of time to do a brute force attack, you're in the clear. Cracking an expired key is useless as it's not being used to protect any data.

    This isn't exactly military-grade security, but anything more than this would be moving well into "more trouble than it's worth" territory, I'd think. :-)
  • 06-15-2006 2:54 PM In reply to

    Re: Miserable captcha implementation

    db2:

    But this can be made viable with a trivial change. Before calculating the md5 sum at the server, concatenate the plaintext with some secret key. In other words, ciphertext = md5(key & plaintext). Then you do the same with the plaintext response supplied by the client to make sure it matches up. If an attacker tries to supply a custom plaintext and a new md5 sum, the correlation between the two will be wrecked by prepending the secret key and it will be rejected.


    I suspected something like this was being done in the sites I looked at, and it makes perfect sense as to why. This would also prevent key reuse, it seems - any attempt to use the md5 from a few days ago would fail due to the new plaintext. Good call, and thanks for pointing it out.
  • 06-16-2006 6:12 AM In reply to

    • Ixpah
    • Top 500 Contributor
    • Joined on 05-11-2006
    • Posts 61

    Re: Miserable captcha implementation

    Using the "ciphertext = md5(key & plaintext)" idea how would you link this to the image? Remember the image is a completely separate HTTP request, and needs to know the plaintext to be rendering in the image.
  • 06-16-2006 8:06 AM In reply to

    • db2
    • Top 200 Contributor
    • Joined on 06-15-2006
    • Posts 169

    Re: Miserable captcha implementation

    Ixpah:
    Using the "ciphertext = md5(key & plaintext)" idea how would you link this to the image? Remember the image is a completely separate HTTP request, and needs to know the plaintext to be rendering in the image.


    An interesting point. Temporary files maybe? Or I guess we could take a slightly different approach and use reversible, symmetric encryption instead of hashing. Then the server would be able to quickly decode what the actual original plaintext is. I knew there had to be some drawback to the keyed md5 technique, but I was at a loss to think of what it might be. ;-)
  • 06-16-2006 9:27 AM In reply to

    Re: Miserable captcha implementation

    Ixpah:
    Using the "ciphertext = md5(key & plaintext)" idea how would you link this to the image? Remember the image is a completely separate HTTP request, and needs to know the plaintext to be rendering in the image.


    Just use the md5 string as the name of the image. I'm pretty sure that's what at least one of the sites I looked at did.
  • 06-16-2006 9:42 AM In reply to

    • Ixpah
    • Top 500 Contributor
    • Joined on 05-11-2006
    • Posts 61

    Re: Miserable captcha implementation

    Using symmetric encryption would work around that problem, but there still the problem of replay attacks, and too many guesses at the same image. Reply can be limited by having a time stamp in the payload but it would need to be atleast 5-10 minutes so the user has time to fill in the form before the captcha expires.

    Keep the ideas coming...
  • 06-16-2006 9:45 AM In reply to

    • Ixpah
    • Top 500 Contributor
    • Joined on 05-11-2006
    • Posts 61

    Re: Miserable captcha implementation

    endergt:
    Ixpah:
    Using the "ciphertext = md5(key & plaintext)" idea how would you link this to the image? Remember the image is a completely separate HTTP request, and needs to know the plaintext to be rendering in the image.


    Just use the md5 string as the name of the image. I'm pretty sure that's what at least one of the sites I looked at did.


    You could generate the image at the same time as the form and store it in the filesystem, so this would work, but you'd need a clean up task to remove old images though.
  • 06-16-2006 9:55 AM In reply to

    • Ixpah
    • Top 500 Contributor
    • Joined on 05-11-2006
    • Posts 61

    Re: Miserable captcha implementation

    Just thought storing it in file using the md5 as the name would allow you to stop replays/retries by deleting the image when the form is submitted. So apart from the cleanup task which could probably be done on the back of form submission this looks like a good solution.
  • 06-16-2006 11:27 AM In reply to

    Re: Miserable captcha implementation

    Ixpah:
    endergt:
    Ixpah:
    Using the "ciphertext = md5(key & plaintext)" idea how would you link this to the image? Remember the image is a completely separate HTTP request, and needs to know the plaintext to be rendering in the image.


    Just use the md5 string as the name of the image. I'm pretty sure that's what at least one of the sites I looked at did.


    You could generate the image at the same time as the form and store it in the filesystem, so this would work, but you'd need a clean up task to remove old images though.


    You could generate the image from a random generated alpa(numeric) code and not store it. There's really no need to store it anywhere. I mean, after the form's been visited, nobody will ever reuse the same image. One-off usage doesn't benefit from storage. Do you put your condoms back in the wrapper after use? I THINK NOT.

    The client loads the form, generates a generic "give me an image!" request and the server gives you a image with distorted random text on it. The server knows what the image says, because it generated it. It doesn't tell the client anything, and just sits there, cards up, poker face tightly in place. The client only gets the binary data of the image, which is meaningless to anything except an human mind -- well, and a quality OCR engine, which are starting to become better. When they can read Blogger's captcha's, all hope is lost.
    — Flurp.
  • 06-16-2006 12:06 PM In reply to

    • Ixpah
    • Top 500 Contributor
    • Joined on 05-11-2006
    • Posts 61

    Re: Miserable captcha implementation

    Using md5 you have to storage the image at the time the form is generated as this is the only point where the plaintext exists, also storing it and deleting on submission/failure provides a crude but probably effective defence against replay/retries. Other ways can be used, e.g. sessions or a database, instead of storing the image, but you've got to store something somewhere.
  • 06-16-2006 12:28 PM In reply to

    • Ixpah
    • Top 500 Contributor
    • Joined on 05-11-2006
    • Posts 61

    Re: Miserable captcha implementation

    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/hip_aspnet.asp
    is worth a read if you're interested in this area.

    As the article mentions you've got to be careful not to make the captcha implemention an easy DoS target as it uses quite a bit of CPU time to generate an image.
  • 06-19-2006 9:50 AM In reply to

    Re: Miserable captcha implementation

    Ixpah:

    You could generate the image at the same time as the form and store it in the filesystem, so this would work, but you'd need a clean up task to remove old images though.


    I don't think you'd need to use the filesystem - just store it in memory in a hashmap. The key to the map is the md5 string - when the request for the image comes in, retrieve it from the map and send it on. Delete it from the hashmap when the captcha is completed.

    This assumes that the http request for the image can be handled by your servlet/cgi/whatever rather than being handled by the http server.
  • 06-19-2006 11:18 AM In reply to

    • Ixpah
    • Top 500 Contributor
    • Joined on 05-11-2006
    • Posts 61

    Re: Miserable captcha implementation

    Using the filesystem in this way is purely a way of avoiding using sessions or application objects, not a great way of doing it but it does fit the "requirements".
Page 1 of 1 (32 items)
Powered by Community Server (Non-Commercial Edition), by Telligent Systems