Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 13 of 13
  1. #1
    Super Moderator
    Join Date
    May 2002
    Location
    Perth Australia
    Posts
    4,073
    Thanks
    11
    Thanked 98 Times in 96 Posts

    PHP Captcha revisited

    Hi, an alternate type of Captcha test ...as opposed to trying to decipher the weird fonts ... count the little piggies

    (and no sadly it is not accessible though hints on how to make it so would be much appreciated)

    you can grab sample code and images here

    Sample Usage
    PHP Code:
    <?php
    session_start
    (); /*yes we need a session*/
    include_once './captcha/captcha.php';
        
    /*the check is best done as a static call*/
        
    if(captcha::validate($_REQUEST)===false){
            echo 
    'false';
        }else{
            echo 
    'true';
        }
        
    /* start the captcha using
            /home/www/captcha for the image directory
            using 3 unique images
            showing a total of 6 images for user to count from
            and ask 2 questions
        */
        
    $yaks=new captcha('/home/www/captcha',3,6,2);
        echo 
    $yaks->get_captcha();
        );
    ?>
    captcha.php class
    PHP Code:
    <?php /*alternative captcha class :: firepages.com.au*/
    DEFINE('CAPTCHA_TIMEOUT',3600);//an hour, way too much ?
    DEFINE('CIF','jpg');                            //CaptchaImageFormat
    DEFINE('CIM','image/jpeg');               //                     MimeType
    DEFINE('CONVERT','convert');           //Path to imagemagick convert library

    class captcha{
        var 
    $search = array('{Q_WHAT}','{Q_WHAT_IMG}','{Q_INAME}');
        var 
    $im_num;   #how many images to use from repository
        
    var $complex;  #how many images to show altogether
        
    var $img_path#path to image repository

        
    function captcha($img_path,$im_num=3,$complex=6,$num_questions=3){
            
    $ims=glob("$img_path/*.".CIF);
            
    $x=0;while($x<$im_num){
                
    $this->ims[]=$ims[$x];++$x;
            }
            
    $this->complex=$complex;
            
    $this->im_num=$im_num;
            
    $this->img_path=$img_path;
            
    $this->num_questions=$num_questions;
            
    /*image path relative to calling HTML*/
            
    $this->rel str_replace(array(getcwd(),basename(__FILE__)),'',__FILE__);
        }

        function 
    set_session($hash,$answers){
            unset(
    $_SESSION['fpa_captcha']);
            
    $_SESSION['fpa_captcha']['start'] = mktime();
            
    $_SESSION['fpa_captcha']['hash'] = $hash;
            
    $_SESSION['fpa_captcha']['a'] = $answers;
            
    $_SESSION['fpa_captcha']['CIF']=CIF;
            
    $_SESSION['fpa_captcha']['CIM']=CIM;
        }

        function 
    start_captcha(){
            
    $ims_used=array();$x=0;$a=array();
            while(
    $x $this->complex){
                
    $r=rand(0,($this->im_num-1));
                
    array_push($ims_used,str_replace('.'.CIF,'',basename($this->ims[$r])));
                @
    $a[str_replace('.'.CIF,'',basename($this->ims[$r]))]++;
                
    $str[] = $this->ims[$r];
                ++
    $x;
            }
            
    $ims_used=array_unique($ims_used);
            
    shuffle($ims_used);
            
    $this->ims_used $ims_used;
            
    $str implode(' ',$str);
            
    $hash MD5($str);
            
    $this->set_session($hash,$a);
            
    exec(CONVERT." $str  +append {$this->img_path}/out/{$hash}.".CIF);
            return 
    '<img src=".'.$this->rel.'out.php?r='.mktime().'" />';
        }

        function 
    get_questions($format=''){
            
    $format = empty($format) ? #default format if not passed
                
    'How many {Q_WHAT}\'s ? &nbsp; <input type="text" name="{Q_INAME}" value="" /><br />' :
                
    $format ;
            
    $arr=array_slice($this->ims_used,0,$this->num_questions);
            foreach(
    $arr as $im){
                
    $replace['{Q_WHAT}']=$im;
                
    $replace['{Q_WHAT_IMG}']='.'.$this->rel.$im.'.'.CIF;
                
    $replace['{Q_INAME}']=MD5($_SESSION['fpa_captcha']['hash'].$im);
                
    $str[] = str_replace($this->search,$replace,$format);
                
    $_SESSION['fpa_captcha']['q'][]=$im;
            }
            return 
    implode("\n",$str);
        }

    /*
    optional call to keep your code neat, wraps start_captcha and get_questions according to $format
    $format must include {IMG} and {QUESTIONS} replacers !!
    */
        
    function get_captcha($format="{IMG}<br />\n{QUESTIONS}"$q_format=''){
            return 
    str_replace(
                array(
    '{IMG}','{QUESTIONS}'),
                array(
    $this->start_captcha(),$this->get_questions($q_format)),
                
    $format
            
    );
        }

    /*validation can be static & MUST be called before start_captcha() if form is posting to itself !!*/
        
    function validate($req){
            
    $time=mktime();$valtime $_SESSION['fpa_captcha']['start'];
            if(empty(
    $_SESSION['fpa_captcha']) || (($time $valtime) > CAPTCHA_TIMEOUT)){
                return 
    false;
            }
            foreach(
    $_SESSION['fpa_captcha']['q'] as $q){
                if( 
    $req[MD5($_SESSION['fpa_captcha']['hash'].$q)] != $_SESSION['fpa_captcha']['a'][$q] ){
                    return 
    false;
                }
            }
            return 
    true;
        }
    }
    ?>
    out.php (for serving the capture image)
    PHP Code:
    <?php
    session_start
    ();
    header("Content-type:{$_SESSION['fpa_captcha']['CIM']}");
    echo 
    file_get_contents("out/{$_SESSION['fpa_captcha']['hash']}.{$_SESSION['fpa_captcha']['CIF']}");
    unlink("out/{$_SESSION['fpa_captcha']['hash']}.{$_SESSION['fpa_captcha']['CIF']}");
    ?>
    Updates and more examples can be found here
    resistance is...

    MVC is the current buzz in web application architectures. It comes from event-driven desktop application design and doesn't fit into web application design very well. But luckily nobody really knows what MVC means, so we can call our presentation layer separation mechanism MVC and move on. (Rasmus Lerdorf)

  • #2
    Senior Coder
    Join Date
    Jun 2002
    Location
    near Oswestry
    Posts
    4,508
    Thanks
    0
    Thanked 0 Times in 0 Posts
    I don't see how this can be made accessible, without adding alt text to the images, but then if you do that it's trivial to crack programatically.

    The only form of test that I'm aware of which is accessible is Eric Meyer's "gatekeeper" plugin for wordpress - http://www.meyerweb.com/eric/tools/w...atekeeper.html

    It basically ask random questions like "what color is an orange", or "how many is a dozen", and its crackability is how many different questions there are, so if someone does break it you can just add more questions, and each site you use it on can have a different, unique, set of questions.
    "Why bother with accessibility? ... Because deep down you know that the web is attractive to people who aren't exactly like you." - Joe Clark

  • #3
    Senior Coder
    Join Date
    Aug 2003
    Location
    One step ahead of you.
    Posts
    2,815
    Thanks
    0
    Thanked 3 Times in 3 Posts
    It is too easy to crack. I've written something that gives the correct number of those images and would probably work with any number of images.
    I'm not sure if this was any help, but I hope it didn't make you stupider.

    Experience is something you get just after you really need it.
    PHP Installation Guide Feedback welcome.

  • #4
    Super Moderator
    Join Date
    May 2002
    Location
    Perth Australia
    Posts
    4,073
    Thanks
    11
    Thanked 98 Times in 96 Posts
    Quote Originally Posted by brothercake
    I don't see how this can be made accessible, without adding alt text to the images, but then if you do that it's trivial to crack programatically.
    absolut , I am thinking along the lines of audio with the same basic premise , dynamically tack together several random audio files into one file, play it.. then ask the user .. `how many pigs did you hear` ? etc.. the only way I can do this at the moment is via flash files & I dont know how thats all gonna tie in with accessibility... any ideas appreciated.

    It is too easy to crack. I've written something that gives the correct number of those images and would probably work with any number of images
    how ? dont you need to do some image processing to work that out (since the capture image is a randomly named single image) , ok I appreciate that that's doable but hardly easy, most OCR cracks are text-based.

    ....unless you are working it out from the form input names & session id's ? I thought that the session based attacks should fail (not that I have tried it yet) please tell even though its just for captcha I would still like to secure it if possible.

    I mean its easy enough to brute force, 2 questions * 6 images = 64 attempts (I think) but there are other ways to spot brute-forcing (though not reliably)

    PS if nothing else it solved the spamming issue on the form I originally created it for (for now at least) so something is obviously better than nothing
    resistance is...

    MVC is the current buzz in web application architectures. It comes from event-driven desktop application design and doesn't fit into web application design very well. But luckily nobody really knows what MVC means, so we can call our presentation layer separation mechanism MVC and move on. (Rasmus Lerdorf)

  • #5
    Senior Coder
    Join Date
    Aug 2003
    Location
    One step ahead of you.
    Posts
    2,815
    Thanks
    0
    Thanked 3 Times in 3 Posts
    First of all you give the images used in that image in the questions.
    The cpatcha image has the images neatly lined up therefore checking if parts of the image are like one of those in the questions it is easy.
    even without the images in the questions you could count the number of different images. I'd suggest that the images to build up the captcha were different sizes, not aligned, tilted and the image it self deformed.

    BTW I've seen a php generated audio captcha, though it also seemed easy to crack.
    I'm not sure if this was any help, but I hope it didn't make you stupider.

    Experience is something you get just after you really need it.
    PHP Installation Guide Feedback welcome.

  • #6
    Super Moderator
    Join Date
    May 2002
    Location
    Perth Australia
    Posts
    4,073
    Thanks
    11
    Thanked 98 Times in 96 Posts
    ok what about this... if the images in the captcha image were randomly reversed, rotated and possibly re-coloured ? I dont want to distort them too much... but would that make it a bit harder ?, lol OK I know it would ... but how far do you go ?
    The problem with the best current Captcha images is that if they are too hard for OCR then they are often too hard for humans to read as well

    BTW using the images in the questions is optional you can just use the text but then you have the language issue.

    I think any such system is crackable... its a case of just making it harder for passing bots to automate attacks.
    resistance is...

    MVC is the current buzz in web application architectures. It comes from event-driven desktop application design and doesn't fit into web application design very well. But luckily nobody really knows what MVC means, so we can call our presentation layer separation mechanism MVC and move on. (Rasmus Lerdorf)

  • #7
    Senior Coder
    Join Date
    Aug 2003
    Location
    One step ahead of you.
    Posts
    2,815
    Thanks
    0
    Thanked 3 Times in 3 Posts
    Oh well security is not exactly a friend of accessability... and it is true that ultimate security is no accessability
    I'm not sure if this was any help, but I hope it didn't make you stupider.

    Experience is something you get just after you really need it.
    PHP Installation Guide Feedback welcome.

  • #8
    Regular Coder ralph l mayo's Avatar
    Join Date
    Nov 2005
    Posts
    951
    Thanks
    1
    Thanked 31 Times in 29 Posts
    PHP Code:
    $_SESSION['fpa_captcha']['a'] = $answers
    ...

    If the client accepts cookies they get plaintext answers?
    Last edited by ralph l mayo; 05-08-2006 at 03:42 AM.

  • #9
    Super Moderator
    Join Date
    May 2002
    Location
    Perth Australia
    Posts
    4,073
    Thanks
    11
    Thanked 98 Times in 96 Posts
    no they get a cookie containing a sessionID
    resistance is...

    MVC is the current buzz in web application architectures. It comes from event-driven desktop application design and doesn't fit into web application design very well. But luckily nobody really knows what MVC means, so we can call our presentation layer separation mechanism MVC and move on. (Rasmus Lerdorf)

  • #10
    Regular Coder ralph l mayo's Avatar
    Join Date
    Nov 2005
    Posts
    951
    Thanks
    1
    Thanked 31 Times in 29 Posts
    oh, ok.

  • #11
    Senior Coder
    Join Date
    Jun 2002
    Location
    near Oswestry
    Posts
    4,508
    Thanks
    0
    Thanked 0 Times in 0 Posts
    An audio captcha still isn't accessible - what if you're blind and deaf? Or what if you don't have an audio plugin, or no soundcard or speakers?

    Clearly it's better than just using a visual one, but not using one at all is the only way to be properly accessible. Not unless it's something that doesn't depend on output mode.

    Mind you, even the Gatekeeper isn't completely accessible - it requires an amount of knowledge that might make it unuseable by young children or someone with severe learning difficulties.

    Perhaps it could be simplified by a structure of questions with multiple-choices, only one of which could possibly be correct, such as, for instance "which of these is not a president?" where the possible answers are "president bush", "president mbeki" or "king husssein".

    My 3-year-old neice could get that right
    Last edited by brothercake; 05-08-2006 at 11:49 PM.
    "Why bother with accessibility? ... Because deep down you know that the web is attractive to people who aren't exactly like you." - Joe Clark

  • #12
    Regular Coder trib4lmaniac's Avatar
    Join Date
    Feb 2004
    Location
    Cornwall, UK
    Posts
    535
    Thanks
    0
    Thanked 0 Times in 0 Posts
    I saw an excellent captcha on a site earlier. Perhaps something like this would be better (I agree with marek_mar that your current implementation is far from uncrackable).
    Attached Thumbnails Attached Thumbnails PHP Captcha revisited-captcha.jpg  

  • #13
    Regular Coder
    Join Date
    Dec 2004
    Location
    Manchester, UK
    Posts
    134
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Pretty neat, but yeah a bit easy to evade. Cool all the same.

    I think logic tests are a good way to do this sort of thing too.

    For example, questions that anybody (should) be able to answer like "What color is grass?", "What is ten times two?"

    Just change the questions once a month or so.

    No captcha is the be all and end all to security of an application though, it's just yet another obstacle to get past.


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •