一、检测referer的场景
》缓解CSRF攻击
若referer为空,或referer不属于自身域及子域,则拒绝后续操作(更改密码、更改昵称)
》加固以jsonp方式获取信息
譬如,链接https://passport.jd.com/loginservice.aspx?callback=jQuery8483115&method=UserInfo&_=1522914283457返回用户信息
攻击网页使用script标签,src设置为https://passport.jd.com/loginservice.aspx?callback=attack&method=UserInfo&_=1522914283457,然后声明函数attack,网页就可钓鱼获取到用户信息了
若referer为空,或referer不属于自身域及子域,则拒绝返回信息
》防止音视频盗链
在网页中使用video标签加载视频https://api.huoshan.com/hotsoon/item/video/_playback/?video_id=f0b9acc12f944e5294be13f906bbc86a&line=1&app_id=1112&vquality=normal,是会被服务器拒绝的,原因就是referer检测不通过
视频站检测可以避免为不法网站提供免费的视频存储
二、referer检测方法
referer检测本质就是从链接中获取host部分,判断host是否在允许域名列表中
,通常使用正则表达式进行检测,但往往会出现绕过情况,如下
受保护域名:www.target.com
验证方法:
1、 referer.indexof("target.com") !=-1
2、referer.match(/^http(s?):\/\/.+\.target\.com\//i)
3、referer.host.endwith("target.com")
4、referer.host.indexof("target.com") !=
-1
(host为referer中的域名部分)
攻击者referer:
1、http://www.attack.com/?id=target.com
2、http://www.attack.com/?idtarget.com/aaa
3、http://www.attacktarget.com/xxx
4、http://www.target.com.attack.com/xxx
可以发现上面的验证方法均存在漏洞
安全的做法
1、referer.host.match(/^.*\.target\.com$/)
2、referer.host.endwith(".target.com")
三、其他绕过方法
若检测规则为:若referer不为空,则referer必须来自允许的域名
则可以想办法使referer为空
》iframe src属性、embed src属性、object
data属性的data URI
(text/html)模式,可以发出不带referer的请求
iframe /embed
src="data
:text/html;base64,PHNjcmlwdD5hbGVydChkb2N1bWVudC5kb21haW4pPC9zY3JpcHQ+"
object data="data
:text/html;base64,PHNjcmlwdD5hbGVydChkb2N1bWVudC5kb21haW4pPC9zY3JpcHQ+"
》meta name="referrer"
content="no-referrer" 页面中的video等标签不会出现referer
》a标签的rel=noreferer
四、url跳转
》url跳转中也会涉及到以上host的判断
》结合parse_url和浏览器的一些特性,会出现一些新的绕过方式:
》》比如, desturl =
https://baidu.com#@target.com,
php会将最后一个@之前的部分解析成user:pass部分,所以desturl可以通过检测,但是浏览器却会忽略#后的字符,最终跳转到evil.com
(php parse_url bug:https://bugs.php.net/bug.php?id=73192)
》》比如oauth中,大部分应用会严格判断client_id和desturl的一致性,且会检测desturl是否在允许范围。但有些应用允许desturl为子域名
若desturl=http://evil.com\.target.com,php解析到的host为evil.com\.target.com,在子域名范围内,允许跳转。但在浏览器中正反斜杠代表一样内容,导致浏览器会跳转到evil.com