验证码被破解了,建议大家别用了(captcha被识别)

我的网站被人刷票,开启验证码之后没有效果,从数据库看记录的每一票,验证码都被正确的填入,但是1万pv竟然有几百万的投票。而且时间非常短。从服务器访问结果来看,是机器所为。

return array(

       // captcha action renders the CAPTCHA image displayed on the contact page


        'captcha'=>array(


            'class'=>'AjaxCaptcha',


            'backColor'=>0xFFFFFF,


            'height'=>'30px',


            'width'=>'100px',


             'testLimit'=>1,


    'transparent'=>true,


        ),

你用的哪个版本?

yii 1.1.0

http://www.shotki.com/demo/uploads/100326123952682479vun1kt.jpg

图片不知道为啥不能上传了,你凑合看吧。反正我把验证码图片取消都弄掉了,人家还是能继续刷,说明不是人工的。而是机器的。

但是我就弄不明白,为啥存库里的验证码又没有啥异常的。所以很有可能被识别了

改成rcapthca之后还是不行,但是发现如果把图片改成肉眼无法识别,刷票也会被停止,感觉可能是半人工,或者就是太复杂了读图工具读不出来。

面对这种刷票的,真是没辙啊

这是个bug,在1.1.1/1.0.12里已经fix了。

/**

 * @return string the version of Yii framework


 */


public static function getVersion()


{


	return '1.1.2-dev';


}

刚查看了一下版本,不知道强说的bug是什么问题。我们今天几个分析了一下,最后得出结论可能是读图软件,或者人工加机器。但是量大的有点离谱。因为后来换了raptcha之后,数据库中仍然有正确的单词 验证码输入。如果是读图软件,应该没有那么轻易被迫。我试用了3个验证码,其中还有一种几乎是独立于yii的。因此不知道是不是yii在某些地方把验证码暴漏了

另外,为了支持ajax验证验证码,我将captcha扩展了,将其中的计数部分修改为如果是ajax请求,就不计数。否则每次ajax验证之后都会计一次书,这样limit就没法准确设定。很有可能用户刚好验证通过的时候是最后一次,这时候验证码已经更新,而$model->save()的时候却仍然再用原先的验证码,这样就造成失败了。

这个不计数的情况就是造成问题的地方,这也是1.1.1/1.0.12里更正的。原先yii的captcha是统计image显示的次数,更正后统计的是进行验证的次数。

你的数据验证应该和captcha验证绑定在一起,不然captcha就失去意义了。

对啊,您想想,如果limit为3,那么用户输入错误了1次,这时候前台验证了就浪费掉一次,后台的验证用掉一次,成功投票。可是页面刷新后,验证码还剩一次没有用,这时候用户即使输入正确的验证码,也只能通过前台验证,而因为次数限制通不过后台验证。

同样,如果用户第一次连输两遍验证码错误,第三遍正确了,那么也只能通过前台验证,而没法通过后台验证。

这也是我为什么扩展ajax请求不计次数的初衷。

请问这个问题如何解决呢?因为ajax验证码还是非常需要的,否则用户辛苦填了一堆数据,全部作废了

你有没有用1.1.1呢?1.1.0是按照captcha image的显示次数计数的。这样用户只要一次输对,然后不刷新image,就可以重复提交。

你这个ajax判断从理论上讲也是可以破解的,因为服务器端是没有可靠的办法判断一个请求是否ajax请求的(客户端总是可以伪造的)。

我的扩展的确给暴力读图破解留下了漏洞,因为不会过期了。

最理想的方式应该是,ajax验证的次数和后台验证次数分离,完了之后ajax验证次数达到之后,主动更新图片。后台验证最多只允许1次。

但是,现在的情况

我用的就是1.1.1

就是ajax验证的时候调用

protected function performAjaxValidation($model){

        if(isset($_POST['ajax'])&&$_POST['ajax']=='user-form'){


            echo CActiveForm::validate($model);


            Yii::app()->end();


        }


    }

ajax验证一次,limit次数少一次,经常出现用户输错两次,第三次的时候对了。但是limit次数到了。因此后台$model->save()调用的验证就是验证码已经过期了,通不过验证了。

如果我不扩展,就会出现这样的情况。用户前台明明最后填对了,正确提交了,到后台却通不过验证了

http://reg.kaixin001.com/

也许改成这样可行,输入错了直接刷新图片

同样问几个问题:1.如何控制验证码刷新,图片就刷新。(实现我说的方法)。还有就是页面刷新,验证码图片为啥不变

            2.yii的activeform是整个表单ajax提交到后台用后台的validate进行验证。有没有这个必要?是不是邮箱格式,手机格式之类的,用前台验证,而不用都提交到后台验证呢?  以前就用jquery .validator.js 然后只有需要ajax验证的项才请求。





            3.一打岔给忘了,问个无关痛痒的问题,如果我用的raptcha 扩展,但是库里存的也是单词,是不是可以认定刷票者至少用手工填了验证码这个,而不是直接读图的?

class AjaxCaptcha extends CCaptchaAction

{

/**


 * Validates the input to see if it matches the generated code.


 * @param string user input


 * @param boolean whether the comparison should be case-sensitive


 * @return whether the input is valid


 */


public function validate($input,$caseSensitive)


{


	$code=$this->getVerifyCode();


	$valid=$caseSensitive?($input===$code):!strcasecmp($input,$code);


	$session=Yii::app()->session;


	$session->open();


	$name=$this->getSessionKey().'count';


	if (Yii::app()->getRequest()->isAjaxRequest == false)//可能是漏洞


	{


        $session[$name]=$session[$name]+1;


    }


	if($session[$name]>$this->testLimit && $this->testLimit>0)


		$this->getVerifyCode(true);


	return $valid;


}

}

我的修改

先确定重复刷票的问题所在:用了1.1.1后是否还有这种情况?你一开始说用的是1.1.0。

客户端验证最多只能起到一个辅助的作用(让用户迅速得到反馈),服务器端验证是必须的。实现客户端验证当然不一定用activeform这种方式。不过activeform的方法可以确保你客户服务器端的验证结果是一致的。

我不大相信刷票者是通过识别图里的验证码达到目的的,这样做的代价太高。更有可能的是captcha验证实现上的漏洞,例如yii 1.1.1/1.0.12之前的版本。

对于你这个问题,最简单的方法是把testLimit改成无限次。每次用户成功提交后就刷新captcha:

Yii::app()->getController()->createAction($this->captchaAction)->getVerifyCode(true)

这样,只要用户没有真正实现智能识别captcha的算法,他就不可能自动重复刷票。

There are some limitations of CActiveForm regarding to its AJAX validation support. First, it does not validate with file upload fields. Second, it should not be used to perform validations that may cause server-side state change. For example, it is not suitable to perform CAPTCHA validation done by CCaptchAction because each validation request will increase the number of tests by one. Third, it is not designed to work with tabular data input for the moment.

我现在就是遇到你说的这个问题。increase the number of tests by one,不过我会参考开心的方式,只能用一次。ajax验证一次,图片刷新一次。另外你说的方法,我周一会尝试。我一开始用的1.1.2-dev。现在所有工作在svn上做的,周一回单位去尝试更新。

我们今天几个技术得出的结论是,人工加软件(因为每次投票要手工勾选60个人,因此纯手工不可能)。验证码人工填写。因为验证码弄特小特复杂之后,刷票就停止了。(是不是图读不了了不清楚)

但是如果是人工,一晚上几万的投票,也很厉害了

还有,你说的captcha的验证漏洞。这个我觉得不太现实,因为数据库正确的记录了所有票的验证码,每次不一样,而且,是中文的时候就是中文,是数字的时候数字。是单词的时候单词。

我们都比较愿意相信人工加软件。只不过量太大了。有点质疑

刚才查看了下,独立ip1000多,pv8000多,票数8000多票。好像比较正常。

如果这样的话,和我说的漏洞可能没关系,因为验证码的确被识别了。不过我还是不大相信是软件识别的(理论上是完全可能的,但实现起来比较费事)。

你有没有记录一下刷票的时间间隔,是不是比较有规律?

我知道有种破解captcha的方法:在一个色情网站或其它用户很多的网站上放captcha,让这些用户帮忙输入正确的captcha。当然,这还需要一些软件的支持实现整个过程自动化。