使用php伪造referer的方法 利用referer防止图片盗链


Posted in PHP onJanuary 20, 2014

什么是HTTP Referer
简言之,HTTP Referer是header的一部分,当浏览器向web服务器发送请求的时候,一般会带上Referer,告诉服务器我是从哪个页面链接过来的,服务器籍此可以获得一些信息用于处理。比如从我主页上链接到一个朋友那里,他的服务器就能够从HTTP Referer中统计出每天有多少用户点击我主页上的链接访问他的网站。
Referer其实应该是英文单词Referrer,不过拼错的人太多了,所以编写标准的人也就将错就错了。
我的问题
我刚刚把feed阅读器改变为Gregarius,但他不像我以前用的liferea,访问新浪博客的时候,无法显示其中的图片,提示“此图片仅限于新浪博客用户交流与沟通”,我知道,这就是HTTP Referer导致的。
由于我上网客户端配置的特殊性,首先怀疑是squid的问题,但通过实验排除了,不过同时发现了一个Squid和Tor、Privoxy协同使用的隐私泄露问题,留待以后研究。
Gregarius能处理这个问题么?
答案是否定的,因为Gregarius只是负责输出html代码,而对图像的访问是有客户端浏览器向服务器请求的。
不过,安装个firefox扩展也许能解决问题,文中推荐的”Send Referrer”我没有找到,但发现另外一个可用的:”RefControl“,可以根据访问网站的不同,控制使用不同的Referer。
但是我不喜欢用Firefox扩展来解决问题,因为我觉得他效率太低,所以我用更好的方式——Privoxy。
Privoxy真棒
在Privoxy的default.action中添加两行:
{+hide-referrer{forge}}
.album.sina.com.cn
这样Gregarius中新浪博客的图片就出来了吧?+hide-referrer是Privoxy的一个过滤器,设置访问时对HTTP Referer的处理方式,后面的forge代表用访问地址当作Refere的,还可以换成block,代表取消Referer,或者直接把需要用的Referer网址写在这里。
用Privoxy比用Firefox简单的多,赶紧换吧。
From https to http
我还发现,从一个https页面上的链接访问到一个非加密的http页面的时候,在http页面上是检查不到HTTP Referer的,比如当我点击自己的https页面下面的w3c xhtml验证图标(网址为http://validator.w3.org/check?uri=referer),从来都无法完成校验,提示:
No Referer header found!
原来,在http协议的rfc文档中有定义:

15.1.3 Encoding Sensitive Information in URI's
Clients SHOULD NOT include a Referer header field in a (non-secure)
HTTP request if the referring page was transferred with a secure
protocol.

这样是出于安全的考虑,访问非加密页时,如果来源是加密页,客户端不发送Referer,IE一直都是这样实现的,Firefox浏览器也不例外。但这并不影响从加密页到加密页的访问。
Firefox中关于Referer的设置
都在里,有两个键值:
network.http.sendRefererHeader (default=2) 设置Referer的发送方式,0为完全不发送,1为只在点击链接时发送,在访问页面中的图像什么的时候不发送,2为始终发送。参见Privacy Tip #3: Block Referer Headers in Firefox
network.http.sendSecureXSiteReferrer (default=true) 设置从一个加密页访问到另外一个加密页的时候是否发送Referer,true为发送,false为不发送。

利用Referer防止图片盗链

虽然Referer并不可靠,但用来防止图片盗链还是足够的,毕竟不是每个人都会修改客户端的配置。实现一般都是通过apache的配置文件,首先设置允许访问的地址,标记下来:
# 只允许来自don.com的访问,图片可能就放置在don.com网站的页面上
SetEnvIfNoCase Referer "^http://www.don.com/" local_ref
# 直接通过地址访问
SetEnvIf Referer "^$" local_ref
然后再规定被标记了的访问才被允许:

<FilesMatch ".(gif|jpg)">
Order Allow,Deny
Allow from env=local_ref
</FilesMatch>

或者

<Directory /web/images>
   Order Deny,Allow
   Deny from all
   Allow from env=local_ref
</Directory>

不要使用Rerferer的地方

不要把Rerferer用在身份验证或者其他非常重要的检查上,因为Rerferer非常容易在客户端被改变,不管是通过上面介绍的Firefox扩展,或者是Privoxy,甚至是libcurl的调用,所以Rerferer数据非常之不可信。
如果你想限制用户必须从某个入口页面访问的话,与其使用Referer,不如使用session,在入口页面写入session,然后在其他页面检查,如果用户没有访问过入口页面,那么对应的session就不存在,参见这里的讨论。不过和上面说的一样,也不要过于相信这种方式的“验证”结果。
个人感觉现在Rerferer除了用在防盗链,其他用途最多的就是访问统计,比如统计用户都是从哪里的链接访问过来的等等。

使用php伪造referer的方法 利用referer防止图片盗链

HTTP-REFERER这个变量已经越来越不可靠了,完全就是可以伪造出来的东东。
以下是伪造方法:

PHP(前提是装了curl):

$ch = curl_init();
curl_setopt ($ch, CURLOPT_URL, "http://www.d.cn/xxx.asp");
curl_setopt ($ch, CURLOPT_REFERER, "http://www.d.cn/");
curl_exec ($ch);
curl_close ($ch);PHP(不装curl用sock)
$server = 'www.dc9.cn';
$host = 'www.dc9.cn';
$target = '/xxx.asp';
$referer = 'http://www.d.cn/'; // Referer
$port = 80;
$fp = fsockopen($server, $port, $errno, $errstr, 30);
if (!$fp) 
{
echo "$errstr ($errno)<br />\n";
} 
else 
{
$out = "GET $target HTTP/1.1\r\n";
$out .= "Host: $host\r\n";
$out .= "Cookie: ASPSESSIONIDSQTBQSDA=DFCAPKLBBFICDAFMHNKIGKEG\r\n";
$out .= "Referer: $referer\r\n";
$out .= "Connection: Close\r\n\r\n";
fwrite($fp, $out);
while (!feof($fp)) 
{
echo fgets($fp, 128);
}
fclose($fp);
}

javascript
xmlHttp.setRequestHeader("Referer", "http://URL");//   呵呵~假的~

JS不支持^_^

原理都是sock构造http头来senddata。其他语言什么的比如perl也可以,
目前比较简单的防御伪造referer的方法是用验证码(Session)。
现在有一些能防盗链软件的商业公司比如UUDOG,linkgate,VirtualWall什么的,都是开发的应用于IIS上面的dll。
有的是采用cookies验证、线程控制,有的是能随机生成文件名然后做URL重写。有的方法能的确达到不错的效果.
不过道高一尺,魔高一丈,这些雕虫小技终归是有破解方法的。
一般的就是这样的了,但是服务器就不好实现伪造,只能制造不多的数据了,如果可以实现访问网页就可以伪造,那就可以实现了真正的伪造,实现自然IP分布。

PHP 相关文章推荐
第五节 克隆 [5]
Oct 09 PHP
phpBB BBcode处理的漏洞
Oct 09 PHP
php代码优化及php相关问题总结
Oct 09 PHP
php判断字符以及字符串的包含方法属性
Aug 30 PHP
学习php笔记 字符串处理
Oct 19 PHP
php导出中文内容excel文件类实例
Jul 06 PHP
PHP使用file_get_content设置头信息的方法
Feb 14 PHP
Yii2实现上下联动下拉框功能的方法
Aug 10 PHP
yii2.0整合阿里云oss删除单个文件的方法
Sep 19 PHP
php+croppic.js实现剪切上传图片功能
Aug 14 PHP
PHP校验15位和18位身份证号的类封装
Nov 07 PHP
Yii2.0 RESTful API 基础配置教程详解
Dec 26 PHP
php fsockopen解决办法 php实现多线程
Jan 20 #PHP
linux系统下php安装mbstring扩展的二种方法
Jan 20 #PHP
php共享内存段示例分享
Jan 20 #PHP
php使用base64加密解密图片示例分享
Jan 20 #PHP
用Zend Studio+PHPnow+Zend Debugger搭建PHP服务器调试环境步骤
Jan 19 #PHP
php实现可以设置中奖概率的抽奖程序代码分享
Jan 19 #PHP
php根据身份证号码计算年龄的实例代码
Jan 18 #PHP
You might like
php导出CSV抽象类实例
2014/09/24 PHP
Windows 下安装 swoole 图文教程(php)
2017/06/05 PHP
PHP调用API接口实现天气查询功能的示例
2017/09/21 PHP
创建一个复制UBB软件信息的链接或按钮的js代码
2008/01/06 Javascript
JavaScript DOM学习第八章 表单错误提示
2010/02/19 Javascript
Javascript 拖拽的一些简单的应用(逐行分析代码,让你轻松了拖拽的原理)
2015/01/23 Javascript
JavaScript实现的圆形浮动标签云效果实例
2015/08/06 Javascript
纯javascript响应式树形菜单效果
2015/11/10 Javascript
angularjs 表单密码验证自定义指令实现代码
2016/10/27 Javascript
vue代码分割的实现(codesplit)
2018/11/13 Javascript
element-ui 弹窗组件封装的步骤
2021/01/22 Javascript
vue集成一个支持图片缩放拖拽的富文本编辑器
2021/01/29 Vue.js
基于Python_脚本CGI、特点、应用、开发环境(详解)
2017/05/23 Python
详解python里使用正则表达式的分组命名方式
2017/10/24 Python
Python用户推荐系统曼哈顿算法实现完整代码
2017/12/01 Python
Python设计模式之代理模式简单示例
2018/01/09 Python
python web.py开发httpserver解决跨域问题实例解析
2018/02/12 Python
Python实现线程状态监测简单示例
2018/03/28 Python
利用python如何处理百万条数据(适用java新手)
2018/06/06 Python
解决Pycharm下面出现No R interpreter defined的问题
2018/10/29 Python
Python列表切片操作实例总结
2019/02/19 Python
Python列表删除元素del、pop()和remove()的区别小结
2019/09/11 Python
python 实现任务管理清单案例
2020/04/25 Python
Python基于内置函数type创建新类型
2020/10/22 Python
基于HTML5 Canvas的3D动态Chart图表的示例
2017/11/02 HTML / CSS
印尼最大的婴儿用品购物网站:Orami
2017/09/28 全球购物
医学毕业生自荐信
2013/10/11 职场文书
员工年终自我评价
2014/09/14 职场文书
2014年会计主管工作总结
2014/12/20 职场文书
创业计划书之情侣餐厅
2019/09/29 职场文书
Python实现单例模式的5种方法
2021/06/15 Python
Python绘画好看的星空图
2022/03/17 Python
斗罗大陆八大特殊魂兽,龙族始祖排榜首,第五最残忍(翠魔鸟)
2022/03/18 国漫
vue使用refs获取嵌套组件中的值过程
2022/03/31 Vue.js
【海涛DOTA】D-cup邀请赛NV.cn vs DT.Love
2022/04/01 DOTA
关于对TypeScript泛型参数的默认值理解
2022/07/15 Javascript