文章目录

host header attack这个词也是从老外那里学来的。利用HTTP host头攻击的技术 这里翻译不是很流畅,最好看看原文。

tinyshop中生成找回密码邮件的方法如下:

public function forget_act(){
     $email =  Filter::sql(Req::args('email'));
     $model = $this->model->table('user');
     $obj = $model->where("email = '".$email."'")->find();
     if(!empty($obj)){
         $model = $this->model->table('reset_password');
         $obj = $model->where("email = '".$email."'")->find();
         $safecode = md5(md5($email).md5(CHash::random(32)));
         if(!empty($obj)){
             $obj['safecode'] = $safecode;
             $model->data($obj)->update();
         }
         else{
             $model->data(array('email'=>$email,'safecode'=>$safecode))->add();
         }


         $reset_url = Url::fullUrlFormat("/simple/reset_password/safecode/$safecode");
         $msg_content = '';

可以看到,生成32位随机数取hash坐位safecode,发送给用户重置密码,这个逻辑是没有问题的。跟一下fullUrlFormat方法。

static function fullUrlFormat($path)
    {
        $path = trim($path);
        if(preg_match('@[/\@#*!]?(https?://.+)$@i', $path,$matches)) return $matches[1];
        return self::getHost().self::urlFormat($path);
    }

静态方法fullUrlFormat使用了getHost()来获得当前网站自身的域名。继续跟gethost方法。

/**
 *取得网站的host地址
 */
public static function getHost($http='http')
{
    if(isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"]=='on') $http = "https";
    if(self::$_host!==null) return self::$_host;
    if(isset($_SERVER['HTTP_HOST']))
        self::$_host = $http.'://'.$_SERVER['HTTP_HOST'];
    else
        self::$_host = $http.'://'.$_SERVER['SERVER_NAME'];

    return  self::$_host;
}

这里输出一下可以看到找回密码的流程中,调用getHost的时候$_host变量的值是null。所以会依次尝试取$_SERVER[‘HTTP_HOST’]和$_SERVER[‘SERVER_NAME’]作为拼接url的域名使用。而$_SERVER[‘HTTP_HOST’]是取自客户端传递的host头部的值,即客户端是可以伪造这个值的。

漏洞危害因为需要交互,所以取决于用户量和用户价值。当用户收到这封真实的找回密码邮件,如果点击了URL,则safecode就会发送给攻击者,从而导致自己的账号被盗。

文章目录